# frozen_string_literal: true # Generated HTML is transformed back to GFM by app/assets/javascripts/behaviors/markdown/marks/inline_diff.js module Banzai module Filter class InlineDiffFilter < HTML::Pipeline::Filter IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set INLINE_DIFF_DELETION_UNTRUSTED = '(?:\[\-(.*?)\-\]|\{\-(.*?)\-\})' INLINE_DIFF_DELETION_UNTRUSTED_REGEX = Gitlab::UntrustedRegexp.new(INLINE_DIFF_DELETION_UNTRUSTED, multiline: false) INLINE_DIFF_ADDITION_UNTRUSTED = '(?:\[\+(.*?)\+\]|\{\+(.*?)\+\})' INLINE_DIFF_ADDITION_UNTRUSTED_REGEX = Gitlab::UntrustedRegexp.new(INLINE_DIFF_ADDITION_UNTRUSTED, multiline: false) def call doc.xpath('descendant-or-self::text()').each do |node| next if has_ancestor?(node, IGNORED_ANCESTOR_TAGS) content = node.to_html html_content = inline_diff_filter(content) next if content == html_content node.replace(html_content) end doc end def inline_diff_filter(text) html_content = INLINE_DIFF_DELETION_UNTRUSTED_REGEX.replace_gsub(text) do |match| %(#{match[1]}#{match[2]}) end INLINE_DIFF_ADDITION_UNTRUSTED_REGEX.replace_gsub(html_content) do |match| %(#{match[1]}#{match[2]}) end end end end end