Change AdvancedTextFormatter to rewrite entities in one pass and sanitize at the end

Also, minor refactoring to better match how other formatters are organized.
This commit is contained in:
Claire
2022-11-30 11:05:01 +01:00
parent 4a66e4daa3
commit 6a900d4c8b

View File

@@ -35,40 +35,28 @@ class AdvancedTextFormatter < TextFormatter
@text = format_markdown(text) if content_type == 'text/markdown' @text = format_markdown(text) if content_type == 'text/markdown'
end end
# Differs from TextFormatter by operating on the parsed HTML tree ;) # Differs from TextFormatter by not messing with newline after parsing
#
# See +#tree+
def to_s def to_s
return ''.html_safe if text.blank? return ''.html_safe if text.blank?
result = tree.dup html = rewrite do |entity|
result.css('mastodon-entity').each do |entity| if entity[:url]
case entity['kind'] link_to_url(entity)
when 'hashtag' elsif entity[:hashtag]
entity.replace(link_to_hashtag({ hashtag: entity['value'] })) link_to_hashtag(entity)
when 'link' elsif entity[:screen_name]
entity.replace(link_to_url({ url: entity['value'] })) link_to_mention(entity)
when 'mention'
entity.replace(link_to_mention({ screen_name: entity['value'] }))
end end
end end
result.to_html.html_safe # rubocop:disable Rails/OutputSafety
end
## html.html_safe # rubocop:disable Rails/OutputSafety
# Process the status into a Nokogiri document fragment, with entities end
# replaced with +<mastodon-entity>+s.
# # Differs from TextFormatter by operating on the parsed HTML tree
# Since +<mastodon-entity>+ is not allowed by the sanitizer, any such def rewrite
# elements in the output *must* have been produced by this algorithm.
#
# These elements will need to be replaced prior to serialization (see
# +#to_s+).
def tree
if @tree.nil? if @tree.nil?
src = text.gsub(Sanitize::REGEX_UNSUITABLE_CHARS, '') src = text.gsub(Sanitize::REGEX_UNSUITABLE_CHARS, '')
@tree = Nokogiri::HTML5.fragment(src) @tree = Nokogiri::HTML5.fragment(src)
Sanitize.node!(@tree, Sanitize::Config::MASTODON_OUTGOING)
document = @tree.document document = @tree.document
@tree.xpath('.//text()[not(ancestor::a | ancestor::code)]').each do |text_node| @tree.xpath('.//text()[not(ancestor::a | ancestor::code)]').each do |text_node|
@@ -89,18 +77,7 @@ class AdvancedTextFormatter < TextFormatter
document document
) )
end end
elt = Nokogiri::XML::Element.new('mastodon-entity', document) replacement << Nokogiri::HTML5.fragment(yield(entity))
if entity[:url]
elt['kind'] = 'link'
elt['value'] = entity[:url]
elsif entity[:hashtag]
elt['kind'] = 'hashtag'
elt['value'] = entity[:hashtag]
elsif entity[:screen_name]
elt['kind'] = 'mention'
elt['value'] = entity[:screen_name]
end
replacement << elt
processed_index = entity[:indices].last processed_index = entity[:indices].last
end end
if processed_index < content.size if processed_index < content.size
@@ -113,7 +90,8 @@ class AdvancedTextFormatter < TextFormatter
text_node.replace(replacement) text_node.replace(replacement)
end end
end end
@tree
Sanitize.node!(@tree, Sanitize::Config::MASTODON_OUTGOING).to_html
end end
private private