summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaire <claire.github-309c@sitedethib.com>2022-11-09 15:38:46 +0100
committerClaire <claire.github-309c@sitedethib.com>2022-11-14 11:09:11 +0100
commit0ce2b4d358e791cc1710ecb50764a18458652d77 (patch)
treea43dcf557c51d6132d7103bb712f0982c9d244da
parent6f26dcae4d89fa6a303f8fbdd5c4efc5e8da7361 (diff)
Fix emoji substitution not applying only to text nodes in backend code
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
-rw-r--r--app/lib/formatter.rb65
1 files changed, 31 insertions, 34 deletions
diff --git a/app/lib/formatter.rb b/app/lib/formatter.rb
index 1610f368925..d2caf042abb 100644
--- a/app/lib/formatter.rb
+++ b/app/lib/formatter.rb
@@ -8,6 +8,8 @@ class Formatter
include ActionView::Helpers::TextHelper
+ DISALLOWED_BOUNDING_REGEX = /[[:alnum:]:]/.freeze
+
def format(status, **options)
if status.reblog?
prepend_reblog = status.reblog.account.acct
@@ -140,54 +142,49 @@ class Formatter
emoji_map = emojis.each_with_object({}) { |e, h| h[e.shortcode] = [full_asset_url(e.image.url), full_asset_url(e.image.url(:static))] }
- i = -1
- tag_open_index = nil
- inside_shortname = false
- shortname_start_index = -1
- invisible_depth = 0
+ tree = Nokogiri::HTML.fragment(html)
+ tree.xpath('./text()|.//text()[not(ancestor[@class="invisible"])]').to_a.each do |node|
+ i = -1
+ inside_shortname = false
+ shortname_start_index = -1
+ last_index = 0
+ text = node.content
+ result = Nokogiri::XML::NodeSet.new(tree.document)
+
+ while i + 1 < text.size
+ i += 1
- while i + 1 < html.size
- i += 1
+ if inside_shortname && text[i] == ':'
+ inside_shortname = false
+ shortcode = text[shortname_start_index + 1..i - 1]
+ char_after = text[i + 1]
- if invisible_depth.zero? && inside_shortname && html[i] == ':'
- shortcode = html[shortname_start_index + 1..i - 1]
- emoji = emoji_map[shortcode]
+ next unless (char_after.nil? || !DISALLOWED_BOUNDING_REGEX.match?(char_after)) && (emoji = emoji_map[shortcode])
- if emoji
original_url, static_url = emoji
- replacement = begin
+
+ result << Nokogiri::XML::Text.new(text[last_index..shortname_start_index - 1], tree.document) if shortname_start_index.positive?
+
+ result << Nokogiri::HTML.fragment(
if animate
image_tag(original_url, draggable: false, class: 'emojione', alt: ":#{shortcode}:", title: ":#{shortcode}:")
else
image_tag(original_url, draggable: false, class: 'emojione custom-emoji', alt: ":#{shortcode}:", title: ":#{shortcode}:", data: { original: original_url, static: static_url })
end
- end
- before_html = shortname_start_index.positive? ? html[0..shortname_start_index - 1] : ''
- html = before_html + replacement + html[i + 1..-1]
- i += replacement.size - (shortcode.size + 2) - 1
- else
- i -= 1
- end
+ )
- inside_shortname = false
- elsif tag_open_index && html[i] == '>'
- tag = html[tag_open_index..i]
- tag_open_index = nil
- if invisible_depth.positive?
- invisible_depth += count_tag_nesting(tag)
- elsif tag == '<span class="invisible">'
- invisible_depth = 1
+ last_index = i + 1
+ elsif text[i] == ':' && (i.zero? || !DISALLOWED_BOUNDING_REGEX.match?(text[i - 1]))
+ inside_shortname = true
+ shortname_start_index = i
end
- elsif html[i] == '<'
- tag_open_index = i
- inside_shortname = false
- elsif !tag_open_index && html[i] == ':'
- inside_shortname = true
- shortname_start_index = i
end
+
+ result << Nokogiri::XML::Text.new(text[last_index..-1], tree.document)
+ node.replace(result)
end
- html
+ tree.to_html
end
# rubocop:enable Metrics/BlockNesting