FIX: Calculation of text length for <details> in excerpt was wrong

This commit is contained in:
Gerhard Schlager
2018-03-12 16:52:06 +01:00
parent 2cb6fcb3d6
commit d243b82fb3
3 changed files with 51 additions and 17 deletions

View File

@ -49,7 +49,8 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
end end
def include_tag(name, attributes) def include_tag(name, attributes)
characters("<#{name} #{attributes.map { |k, v| "#{k}=\"#{escape_attribute(v)}\"" }.join(' ')}>", false, false, false) characters("<#{name} #{attributes.map { |k, v| "#{k}=\"#{escape_attribute(v)}\"" }.join(' ')}>",
truncate: false, count_it: false, encode: false)
end end
def start_element(name, attributes = []) def start_element(name, attributes = [])
@ -130,12 +131,12 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
case name case name
when "a" when "a"
unless @strip_links unless @strip_links
characters("</a>", false, false, false) characters("</a>", truncate: false, count_it: false, encode: false)
@in_a = false @in_a = false
end end
when "p", "br" when "p", "br"
if @keep_newlines if @keep_newlines
characters("<br>", false, false, false) characters("<br>", truncate: false, count_it: false, encode: false)
else else
characters(" ") characters(" ")
end end
@ -144,18 +145,31 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
when "details" when "details"
@in_details_depth -= 1 @in_details_depth -= 1
if @in_details_depth == 0 if @in_details_depth == 0
full = "<details><summary>#{clean(@summary_contents)}</summary>#{clean(@detail_contents)}</details>" @summary_contents = clean(@summary_contents)
if @current_length + full.length > @length @detail_contents = clean(@detail_contents)
@excerpt << "<details class='disabled'><summary>#{@summary_contents[0..@length]}</summary></details>"
if @current_length + @summary_contents.length >= @length
characters(@summary_contents,
encode: false,
before_string: "<details class='disabled'><summary>",
after_string: "</summary></details>")
else else
@excerpt << full characters(@summary_contents,
truncate: false,
encode: false,
before_string: "<details><summary>",
after_string: "</summary>")
characters(@detail_contents,
encode: false,
after_string: "</details>")
end end
end end
when "summary" when "summary"
@in_summary = false if @in_details_depth == 1 @in_summary = false if @in_details_depth == 1
when "div", "span" when "div", "span"
throw :done if @start_excerpt throw :done if @start_excerpt
characters("</span>", false, false, false) if @in_spoiler characters("</span>", truncate: false, count_it: false, encode: false) if @in_spoiler
@in_spoiler = false @in_spoiler = false
end end
end end
@ -164,7 +178,7 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
ERB::Util.html_escape(str.strip) ERB::Util.html_escape(str.strip)
end end
def characters(string, truncate = true, count_it = true, encode = true) def characters(string, truncate: true, count_it: true, encode: true, before_string: nil, after_string: nil)
return if @in_quote return if @in_quote
# we call length on this so might as well ensure we have a string # we call length on this so might as well ensure we have a string
@ -178,15 +192,20 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
return return
end end
@excerpt << before_string if before_string
encode = encode ? lambda { |s| ERB::Util.html_escape(s) } : lambda { |s| s } encode = encode ? lambda { |s| ERB::Util.html_escape(s) } : lambda { |s| s }
if count_it && @current_length + string.length > @length if count_it && @current_length + string.length > @length
length = [0, @length - @current_length - 1].max length = [0, @length - @current_length - 1].max
@excerpt << encode.call(string[0..length]) if truncate @excerpt << encode.call(string[0..length]) if truncate
@excerpt << (@text_entities ? "..." : "&hellip;") @excerpt << (@text_entities ? "..." : "&hellip;")
@excerpt << "</a>" if @in_a @excerpt << "</a>" if @in_a
@excerpt << after_string if after_string
throw :done throw :done
end end
@excerpt << encode.call(string) @excerpt << encode.call(string)
@excerpt << after_string if after_string
@current_length += string.length if count_it @current_length += string.length if count_it
end end
end end

View File

@ -4,17 +4,32 @@ require "excerpt_parser"
describe ExcerptParser do describe ExcerptParser do
it "handles nested <details> blocks" do it "handles nested <details> blocks" do
html = <<~HTML html = <<~HTML.strip
<details> <details>
<summary>FOO</summary> <summary>
<details> FOO</summary>
<summary>BAR</summary> <details>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ultrices, ex bibendum vestibulum vestibulum, mi velit pulvinar risus, sed consequat eros libero in eros. Fusce luctus mattis mauris, vitae semper lorem sodales quis. Donec pellentesque lacus ac ante aliquam, tincidunt iaculis risus interdum. In ullamcorper cursus massa ut lacinia. Donec quis diam finibus, rutrum odio eu, maximus leo. Nulla facilisi. Nullam suscipit quam et bibendum sagittis. Praesent sollicitudin neque at luctus ornare. Maecenas tristique dapibus risus, ac dictum ipsum gravida aliquam. Phasellus vehicula eu arcu sed imperdiet. Vestibulum ornare eros a nisi faucibus vehicula. Quisque congue placerat nulla, nec finibus nulla ultrices vitae. Quisque ac mi sem. Curabitur eu porttitor justo. Etiam dignissim in orci iaculis congue. Donec tempus cursus orci, a placerat elit varius nec.</p> <summary>
</details> BAR</summary>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ultrices, ex bibendum vestibulum vestibulum, mi velit pulvinar risus, sed consequat eros libero in eros. Fusce luctus mattis mauris, vitae semper lorem sodales quis. Donec pellentesque lacus ac ante aliquam, tincidunt iaculis risus interdum. In ullamcorper cursus massa ut lacinia. Donec quis diam finibus, rutrum odio eu, maximus leo. Nulla facilisi. Nullam suscipit quam et bibendum sagittis. Praesent sollicitudin neque at luctus ornare. Maecenas tristique dapibus risus, ac dictum ipsum gravida aliquam. Phasellus vehicula eu arcu sed imperdiet. Vestibulum ornare eros a nisi faucibus vehicula. Quisque congue placerat nulla, nec finibus nulla ultrices vitae. Quisque ac mi sem. Curabitur eu porttitor justo. Etiam dignissim in orci iaculis congue. Donec tempus cursus orci, a placerat elit varius nec.</p>
</details>
</details> </details>
HTML HTML
expect(ExcerptParser.get_excerpt(html, 200, strip_links: true)).to eq(%{<details class='disabled'><summary>FOO</summary></details>}) expect(ExcerptParser.get_excerpt(html, 50, {})).to match_html(<<~HTML)
<details><summary>FOO</summary>BAR
Lorem ipsum dolor sit amet, consectetur adi&hellip;</details>
HTML
expect(ExcerptParser.get_excerpt(html, 6, {})).to match_html('<details><summary>FOO</summary>BAR&hellip;</details>')
expect(ExcerptParser.get_excerpt(html, 3, {})).to match_html('<details class="disabled"><summary>FOO</summary></details>')
end end
it "respects length parameter for <details> block" do
html = '<details><summary>foo</summary><p>bar</p></details>'
expect(ExcerptParser.get_excerpt(html, 100, {})).to match_html('<details><summary>foo</summary>bar</details>')
expect(ExcerptParser.get_excerpt(html, 5, {})).to match_html('<details><summary>foo</summary>ba&hellip;</details>')
expect(ExcerptParser.get_excerpt(html, 3, {})).to match_html('<details class="disabled"><summary>foo</summary></details>')
expect(ExcerptParser.get_excerpt(html, 2, {})).to match_html('<details class="disabled"><summary>fo&hellip;</summary></details>')
end
end end

View File

@ -389,7 +389,7 @@ describe PrettyText do
end end
it "should keep details if too long" do it "should keep details if too long" do
expect(PrettyText.excerpt("<details><summary>expand</summary><p>hello</p></details>", 30)).to match_html "<details class='disabled'><summary>expand</summary></details>" expect(PrettyText.excerpt("<details><summary>expand</summary><p>hello</p></details>", 6)).to match_html "<details class='disabled'><summary>expand</summary></details>"
end end
it "doesn't disable details if short enough" do it "doesn't disable details if short enough" do