[Done] Fix div in li issue (#320)

* Lint and clean up github issue styles

* Use heredoc HTML for easier formatting

* Add better error handling for 404 github issues

* Use custom sanitizer for markdown render

* Refactor unless to ternary

* Rename file and tighten up sanitization

* Fix codepen and instagram tag styling
This commit is contained in:
Andy Zhao 2018-05-21 17:35:03 -04:00 committed by Ben Halpern
parent cc63a49ecc
commit c9c02ef3c0
13 changed files with 150 additions and 102 deletions

View file

@ -122,6 +122,29 @@
.edit-comment-hide {
padding: 15px 15px;
h1{
margin-left: 0;
font-size: 2em;
padding-bottom: 0.3em;
border-bottom: 1px solid #eaecef;
font-weight: 600;
}
h3{
margin-top: 24px;
margin-bottom: 16px;
padding: 0;
font-size: 1.25em;
font-weight: 600;
line-height: 1.25;
}
h4{
margin-top: 24px;
margin-bottom: 16px;
padding: 0;
}
*:first-child {
margin-top: 0 !important;
}

View file

@ -4,7 +4,6 @@
margin: 1px 1px 12px;
max-width: 450px;
width: calc(100% - 2px);
border-radius: 4px;
box-shadow: none;
display: block;
padding: 0px;

View file

@ -86,10 +86,10 @@ class ArticlesController < ApplicationController
@article.tag_list = []
@article.main_image = nil
edited_at_date = if @article.user == current_user && @article.published
DateTime.now
else
@article.edited_at
end
Time.now
else
@article.edited_at
end
if @article.update(article_params.merge(edited_at: edited_at_date))
handle_org_assignment
handle_hiring_tag

View file

@ -1,5 +1,4 @@
module ApplicationHelper
def user_logged_in_status
user_signed_in? ? "logged-in" : "logged-out"
end
@ -20,6 +19,7 @@ module ApplicationHelper
controller_name == "registrations" ||
controller_name == "users" ||
controller_name == "pages" ||
controller_name == "dashboards"||
controller_name == "moderations"||
controller_name == "videos"||
@ -39,7 +39,7 @@ module ApplicationHelper
page_title
end
def icon(name,pixels="20")
def icon(name, pixels = "20")
image_tag icon_url(name), alt: name, class:"icon-img", height: pixels, width: pixels
end
@ -47,25 +47,25 @@ module ApplicationHelper
prefix = "https://res.cloudinary.com/practicaldev/image/upload/"
case name
when "twitter"
url = prefix+"v1456342401/twitter-logo-silhouette_1_letrqc.png"
prefix + "v1456342401/twitter-logo-silhouette_1_letrqc.png"
when "github"
url = prefix+"v1456342401/github-logo_m841aq.png"
prefix + "v1456342401/github-logo_m841aq.png"
when "link"
url = prefix+"v1456342401/link-symbol_apfbll.png"
prefix + "v1456342401/link-symbol_apfbll.png"
when "volume"
url = prefix+"v1461589297/technology_1_aefet2.png"
prefix + "v1461589297/technology_1_aefet2.png"
when "volume-mute"
url = prefix+"v1461589297/technology_jiugwb.png"
prefix + "v1461589297/technology_jiugwb.png"
else
url = prefix+"v1456342953/star-in-black-of-five-points-shape_sor40l.png"
prefix + "v1456342953/star-in-black-of-five-points-shape_sor40l.png"
end
end
def cloudinary(url,width=nil,quality=80,format="jpg")
def cloudinary(url, width = nil, quality = 80, format = "jpg")
if Rails.env.development? && (url.blank? || !url.include?("http"))
return url
end
if url && url.size > 0
if url && url.size.positive?
if width
"https://res.cloudinary.com/practicaldev/image/fetch/c_scale,fl_progressive,q_auto,w_#{width}/f_auto/#{url}"
else
@ -78,19 +78,19 @@ module ApplicationHelper
def cloud_cover_url(url)
return nil unless url.present?
width = 1000
height = 420
quality = "auto"
width = 1000
height = 420
quality = "auto"
cl_image_path(url,
:type=>"fetch",
:width => width,
:height => height,
:crop => "imagga_scale",
:quality => quality,
:flags => "progressive",
:fetch_format => "auto",
:sign_url => true)
cl_image_path(url,
type: "fetch",
width: width,
height: height,
crop: "imagga_scale",
quality: quality,
flags: "progressive",
fetch_format: "auto",
sign_url: true)
end
def cloud_social_image(article)
@ -114,43 +114,38 @@ module ApplicationHelper
def tag_colors(tag)
Rails.cache.fetch("view-helper-#{tag}/tag_colors", expires_in: 5.hours) do
if found_tag = Tag.find_by_name(tag)
{background:found_tag.bg_color_hex,color:found_tag.text_color_hex}
{ background: found_tag.bg_color_hex,color: found_tag.text_color_hex }
else
{background:"#d6d9e0",color:"#606570"}
{ background: "#d6d9e0", color: "#606570" }
end
end
end
def beautified_url(url)
begin
url.sub(/^((http[s]?|ftp):\/)?\//, '').sub(/\?.*/, '').chomp('/')
rescue
url
end
url.sub(/^((http[s]?|ftp):\/)?\//, "").sub(/\?.*/, "").chomp("/")
rescue
url
end
def org_bg_or_white(org)
return "#ffffff" unless (org && org.bg_color_hex)
org.bg_color_hex
org&.bg_color_hex ? org.bg_color_hex : "#ffffff"
end
def sanitized_article_body(processed_html)
def sanitize_rendered_markdown(processed_html)
ActionController::Base.helpers.sanitize processed_html.html_safe,
tags: %w(button strong em a table tbody thead tfoot th tr td col colgroup del p h1 h2 h3 h4 h5 h6 blockquote time div span i em u b ul ol li dd dl dt q code pre img sup sub cite center br small hr video source figcaption add ruby rp rt),
attributes: %w(href strong em class ref rel src title alt colspan height width size rowspan span value start data-conversation data-lang data-no-instant data-url id name type loop)
scrubber: RenderedMarkdownScrubber.new
end
def sanitized_sidebar(text)
ActionController::Base.helpers.sanitize simple_format(text),
tags: %w(p, b, i, em, strike, strong, u, br),
attributes: %w()
tags: %w(p b i em strike strong u br)
end
def track_split_version(url,version)
def track_split_version(url, version)
"trackOutboundLink('#{url}','#{version}'); return false;"
end
def follow_button(followable,style="full")
def follow_button(followable, style = "full")
"<button class='cta follow-action-button' data-info='{\"id\":#{followable.id},\"className\":\"#{followable.class.name}\",\"style\":\"#{style}\"}' data-follow-action-button>&nbsp;</button>".html_safe
end

View file

@ -64,7 +64,7 @@ class MarkdownParser
catch_xss_attempts(@content)
escaped_content = escape_liquid_tags_in_codeblock(@content)
html = markdown.render(escaped_content)
sanitized_content = sanitized_article_body(html)
sanitized_content = sanitize_rendered_markdown(html)
begin
parsed_liquid = Liquid::Template.parse(sanitized_content)
rescue StandardError => e

View file

@ -2,17 +2,17 @@ class CodepenTag < LiquidTagBase
def initialize(tag_name, link, tokens)
super
@link = parse_link(link)
@height = 500
@height = 600
end
def render(context)
html = <<~HTML
html = <<-HTML
<iframe height="#{@height}"
src="#{@link}?height=500&default-tab=result&embed-version=2"
scrolling="yes"
scrolling="no"
frameborder="no"
allowtransparency="true"
style="width: 100%">
style="width: 100%;">
</iframe>
HTML
finalize_html(html)

View file

@ -15,36 +15,36 @@ class GithubTag < LiquidTagBase
end
def render(context)
contentJSON = @content.issue_serialized
content_json = @content.issue_serialized
body = @content.processed_html
username = contentJSON[:user][:login]
user_html_url = contentJSON[:user][:html_url]
user_avatar_url = contentJSON[:user][:avatar_url]
date = Date.parse(contentJSON[:created_at].to_s).strftime('%b %d, %Y')
date_link = contentJSON[:html_url]
username = content_json[:user][:login]
user_html_url = content_json[:user][:html_url]
user_avatar_url = content_json[:user][:avatar_url]
date = Date.parse(content_json[:created_at].to_s).strftime("%b %d, %Y")
date_link = content_json[:html_url]
title = generate_title
html = '' \
"<div class=\"ltag_github-liquid-tag\"> "\
"#{title}" \
"<div class=\"github-thread\"> " \
"<div class=\"timeline-comment-header\"> " \
"<a href=\"#{user_html_url}\"> " \
"<img class=\"github-liquid-tag-img\" src=\"#{user_avatar_url}\" alt=\"#{username} avatar\"> " \
"</a> " \
"<span class=\"arrow-left-outer\"></span> " \
"<span class=\"arrow-left-inner\"></span> " \
"<div class=\"timeline-comment-header-text\"> " \
"<strong> " \
"<a href=\"#{user_html_url}\">#{username}</a> " \
"</strong> commented on <a href=\"#{date_link}\">#{date}</a> <span class=\"timestamp\"></span> " \
"</div> " \
"</div> " \
"<div class=\"edit-comment-hide\"> " \
"#{body.chomp} " \
"</div> " \
"</div> " \
"</div>"
html = <<-HTML
<div class="ltag_github-liquid-tag">
#{title}
<div class="github-thread">
<div class="timeline-comment-header">
<a href="#{user_html_url}">
<img class="github-liquid-tag-img" src="#{user_avatar_url}" alt="#{username} avatar">
</a>
<span class="arrow-left-outer"></span>
<span class="arrow-left-inner"></span>
<div class="timeline-comment-header-text">
<strong>
<a href="#{user_html_url}">#{username}</a>
</strong> commented on <a href="#{date_link}">#{date}</a> <span class="timestamp"></span>
</div>
</div>
<div class="edit-comment-hide">
#{body.chomp}
</div>
</div>
</div>
HTML
finalize_html(html)
end
@ -52,7 +52,7 @@ class GithubTag < LiquidTagBase
def parse_link(link)
link = ActionController::Base.helpers.strip_tags(link)
link_no_space = link.delete(' ')
link_no_space = link.delete(" ")
if valid_link?(link_no_space)
generate_api_link(link_no_space)
else
@ -69,10 +69,10 @@ class GithubTag < LiquidTagBase
end
def generate_title
contentJSON = @content.issue_serialized
title = contentJSON[:title]
number = contentJSON[:number]
link = contentJSON[:html_url]
content_json = @content.issue_serialized
title = content_json[:title]
number = content_json[:number]
link = content_json[:html_url]
return unless title
"<h1> " \
"<a href=\"#{link}\">" \

View file

@ -6,24 +6,13 @@ class GithubIssue < ApplicationRecord
find_by_url(url) || fetch(url)
end
# def self.fetch(url)
# begin
# return try_to_get_issue(url)
# rescue StandardError => e
# raise StandardError, e.message
# end
# end
def self.fetch(url)
tries = 0
issue = nil
until tries > 4 || issue
begin
return issue = try_to_get_issue(url)
rescue => e
puts e
tries += 1
end
return try_to_get_issue(url)
rescue StandardError => e
if e.message.include?("404 - Not Found")
raise StandardError, "A GitHub issue 404'ed and could not be found!"
else
raise StandardError, e.message
end
end

View file

@ -0,0 +1,23 @@
class RenderedMarkdownScrubber < Rails::Html::PermitScrubber
def initialize
super
self.tags = %w(a add b blockquote br button center cite code col colgroup dd del dl dt em em figcaption h1 h2 h3 h4 h5 h6 hr i img li ol p pre q rp rt ruby small source span strong sub sup table tbody td tfoot th thead time tr u ul video)
self.attributes = %w(alt class colspan data-conversation data-lang data-no-instant data-url em height href id loop name ref rel rowspan size span src start strong title type value width)
end
def allowed_node?(node)
@tags.include?(node.name) || valid_codeblock_div?(node)
end
private
def valid_codeblock_div?(node)
node.name == "div" &&
node.attributes.count == 1 &&
node.children.first.name == "pre" &&
node.parent.name == "#document-fragment" &&
node.attributes.values.any? do |attribute_value|
attribute_value.value == "highlight"
end
end
end

View file

@ -52,7 +52,7 @@
<% if @commentable.processed_html.present? %>
<% if @commentable.processed_html.size < 350 %>
<div class="body">
<%= sanitized_article_body(@commentable.processed_html.html_safe) %>
<%= sanitize_rendered_markdown(@commentable.processed_html.html_safe) %>
</div>
<% else %>
<div class="body">

View file

@ -32,6 +32,7 @@ module PracticalDeveloper
config.autoload_paths += Dir["#{config.root}/app/liquid_tags/"]
config.autoload_paths += Dir["#{config.root}/app/observers/"]
config.autoload_paths += Dir["#{config.root}/app/black_box/"]
config.autoload_paths += Dir["#{config.root}/app/sanitizers"]
config.autoload_paths += Dir["#{config.root}/lib/"]
config.active_record.observers = :article_observer, :reaction_observer

View file

@ -1,6 +1,6 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<iframe height="500" src="https://codepen.io/twhite96/embed/XKqrJX ?height=500&amp;default-tab=result&amp;embed-version=2" scrolling="yes" frameborder="no" allowtransparency="true" style="width: 100%"> </iframe>
<iframe height="600" src="https://codepen.io/twhite96/embed/XKqrJX ?height=500&amp;default-tab=result&amp;embed-version=2" scrolling="no" frameborder="no" allowtransparency="true" style="width: 100%;"> </iframe>
</body>
</html>

View file

@ -1,7 +1,22 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<div class="ltag_github-liquid-tag"> <h1> <a href="https://github.com/facebook/react/issues/9218"><span class="issue-title">[Feature] granular forceUpdate </span> <span class="issue-number">#9218</span> </a></h1> <div class="github-thread"> <div class="timeline-comment-header"> <a href="https://github.com/thysultan"> <img class="github-liquid-tag-img" src="https://avatars2.githubusercontent.com/u/810601?v=4" alt="thysultan avatar" /></a> <span class="arrow-left-outer"></span> <span class="arrow-left-inner"></span> <div class="timeline-comment-header-text"> <strong> <a href="https://github.com/thysultan">thysultan</a> </strong> commented on <a href="https://github.com/facebook/react/issues/9218">Mar 19, 2017</a> <span class="timestamp"></span> </div> </div> <div class="edit-comment-hide"> <p>When <code>forceUpdate</code> is called on a long list at the very least the whole list must be traversed. For example with the following list <code>arr = [1, 2, 3, 4, 5, 6]</code> and if we where to push 7 <code>arr.push(7)</code> the reconciler will go through elements 1 - 6 and then add a 7 at the end of that list. The suggestion to add support for the following forceUpdate signature.</p>
<div class="ltag_github-liquid-tag">
<h1> <a href="https://github.com/facebook/react/issues/9218"><span class="issue-title">[Feature] granular forceUpdate </span> <span class="issue-number">#9218</span> </a></h1>
<div class="github-thread">
<div class="timeline-comment-header">
<a href="https://github.com/thysultan">
<img class="github-liquid-tag-img" src="https://avatars2.githubusercontent.com/u/810601?v=4" alt="thysultan avatar" /></a>
<span class="arrow-left-outer"></span>
<span class="arrow-left-inner"></span>
<div class="timeline-comment-header-text">
<strong>
<a href="https://github.com/thysultan">thysultan</a>
</strong> commented on <a href="https://github.com/facebook/react/issues/9218">Mar 19, 2017</a> <span class="timestamp"></span>
</div>
</div>
<div class="edit-comment-hide">
<p>When <code>forceUpdate</code> is called on a long list at the very least the whole list must be traversed. For example with the following list <code>arr = [1, 2, 3, 4, 5, 6]</code> and if we where to push 7 <code>arr.push(7)</code> the reconciler will go through elements 1 - 6 and then add a 7 at the end of that list. The suggestion to add support for the following forceUpdate signature.</p>
<div class="highlight highlight-source-js"><pre><span class="pl-en">forceUpdate</span>(a<span class="pl-k">:</span> {<span class="pl-k">function</span>|number}, b: number?)</pre></div>
<p>Where when passed as an integer <code>a</code> is the start index and <code>b</code> the number of items to traverse similar to how <code>str.substr()</code> works.</p>
<p>When the function encounters a number as the <code>a</code> argument it changes the start index of where to start when reconciling the components children and when the <code>b</code> argument is set it changes the end index of where to end the traversal of the components children. So with the above mentioned example if i wanted to optimize the reconciliation process for append updates i could do the following.</p>
@ -13,6 +28,9 @@
<div class="highlight highlight-source-js"><pre><span class="pl-en">setState</span>(a<span class="pl-k">:</span> {<span class="pl-k">function</span>|Object}, b: (<span class="pl-k">function</span>|number)?, c: {number})
<span class="pl-c"><span class="pl-c">//</span> usage</span>
setState({arr<span class="pl-k">:</span> [<span class="pl-k">...</span>]}, <span class="pl-c1">this</span>.<span class="pl-smi">state</span>.<span class="pl-smi">arr</span>.<span class="pl-c1">length</span>);</pre></div> </div> </div> </div>
setState({arr<span class="pl-k">:</span> [<span class="pl-k">...</span>]}, <span class="pl-c1">this</span>.<span class="pl-smi">state</span>.<span class="pl-smi">arr</span>.<span class="pl-c1">length</span>);</pre></div>
</div>
</div>
</div>
</body>
</html>