FIX: Do not add empty use/svg tags in ExcerptParser (#19969)

There was an issue where if hashtag-cooked HTML was sent
to the ExcerptParser without the keep_svg option, we would
end up with empty </use> and </svg> tags on the parts of the
excerpt where the hashtag was, in this case when a post
push notification was sent.

Fixed this, and also added a way to only display a plaintext
version of the hashtag for cases like this via PrettyText#excerpt.
This commit is contained in:
Martin Brennan 2023-01-24 14:40:24 +10:00 committed by GitHub
parent 799202d50b
commit 63fdb6dd65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 5 deletions

View File

@ -23,7 +23,14 @@ class PostAlerter
topic_title: post.topic.title,
topic_id: post.topic.id,
excerpt:
excerpt || post.excerpt(400, text_entities: true, strip_links: true, remap_emoji: true),
excerpt ||
post.excerpt(
400,
text_entities: true,
strip_links: true,
remap_emoji: true,
plain_hashtags: true,
),
username: username || post.username,
post_url: post_url,
}

View File

@ -216,7 +216,7 @@ module Email
correct_first_body_margin
correct_footer_style
correct_footer_style_highlight_first
decorate_hashtags
strip_hashtag_link_icons
reset_tables
html_lang = SiteSetting.default_locale.sub("_", "-")
@ -396,7 +396,7 @@ module Email
end
end
def decorate_hashtags
def strip_hashtag_link_icons
@fragment
.search(".hashtag-cooked")
.each do |hashtag|

View File

@ -181,10 +181,10 @@ class ExcerptParser < Nokogiri::XML::SAX::Document
when "div", "span"
throw :done if @start_excerpt
when "svg"
characters("</svg>", truncate: false, count_it: false, encode: false)
characters("</svg>", truncate: false, count_it: false, encode: false) if @keep_svg
@in_svg = false
when "use"
characters("</use>", truncate: false, count_it: false, encode: false)
characters("</use>", truncate: false, count_it: false, encode: false) if @keep_svg
end
end

View File

@ -469,10 +469,21 @@ module PrettyText
DiscourseEvent.trigger(:reduce_excerpt, doc, options)
strip_image_wrapping(doc)
strip_oneboxed_media(doc)
if SiteSetting.enable_experimental_hashtag_autocomplete && options[:plain_hashtags]
convert_hashtag_links_to_plaintext(doc)
end
html = doc.to_html
ExcerptParser.get_excerpt(html, max_length, options)
end
def self.convert_hashtag_links_to_plaintext(doc)
doc
.css("a.hashtag-cooked")
.each { |hashtag| hashtag.replace("##{hashtag.attributes["data-slug"]}") }
end
def self.strip_links(string)
return string if string.blank?

View File

@ -1209,6 +1209,22 @@ RSpec.describe PostAlerter do
expect(JSON.parse(body)).to eq(payload)
end
it "does not have invalid HTML in the excerpt when enable_experimental_hashtag_autocomplete is enabled" do
SiteSetting.enable_experimental_hashtag_autocomplete = true
Fabricate(:category, slug: "random")
Jobs.run_immediately!
body = nil
stub_request(:post, "https://site2.com/push").to_return do |request|
body = request.body
{ status: 200, body: "OK" }
end
create_post_with_alerts(user: user, raw: "this, @eviltrout, is a test with #random")
expect(JSON.parse(body)["notifications"][0]["excerpt"]).to eq(
"this, @eviltrout, is a test with #random",
)
end
context "with push subscriptions" do
before do
Fabricate(:push_subscription, user: evil_trout)