diff options
-rw-r--r-- | app/lib/emoji_formatter.rb | 68 |
1 files changed, 30 insertions, 38 deletions
diff --git a/app/lib/emoji_formatter.rb b/app/lib/emoji_formatter.rb index 194849c23..a9785d5f9 100644 --- a/app/lib/emoji_formatter.rb +++ b/app/lib/emoji_formatter.rb @@ -23,48 +23,40 @@ class EmojiFormatter def to_s return html if custom_emojis.empty? || html.blank? - i = -1 - tag_open_index = nil - inside_shortname = false - shortname_start_index = -1 - invisible_depth = 0 - last_index = 0 - result = ''.dup - - while i + 1 < html.size - i += 1 - - if invisible_depth.zero? && inside_shortname && html[i] == ':' - inside_shortname = false - shortcode = html[shortname_start_index + 1..i - 1] - char_after = html[i + 1] - - next unless (char_after.nil? || !DISALLOWED_BOUNDING_REGEX.match?(char_after)) && (emoji = emoji_map[shortcode]) - - result << html[last_index..shortname_start_index - 1] if shortname_start_index.positive? - result << image_for_emoji(shortcode, emoji) - last_index = i + 1 - 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 + 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 + + if inside_shortname && text[i] == ':' + inside_shortname = false + shortcode = text[shortname_start_index + 1..i - 1] + char_after = text[i + 1] + + next unless (char_after.nil? || !DISALLOWED_BOUNDING_REGEX.match?(char_after)) && (emoji = emoji_map[shortcode]) + + result << Nokogiri::XML::Text.new(text[last_index..shortname_start_index - 1], tree.document) if shortname_start_index.positive? + result << Nokogiri::HTML.fragment(image_for_emoji(shortcode, emoji)) + + 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] == ':' && (i.zero? || !DISALLOWED_BOUNDING_REGEX.match?(html[i - 1])) - inside_shortname = true - shortname_start_index = i end - end - result << html[last_index..-1] + result << Nokogiri::XML::Text.new(text[last_index..-1], tree.document) + node.replace(result) + end - result.html_safe # rubocop:disable Rails/OutputSafety + tree.to_html.html_safe # rubocop:disable Rails/OutputSafety end private |