10924fc580
Support abbr, del, pre, blockquote, code, strong, b, em, i, ul, ol, li and h1 to h5 tags in remote statuses.
87 lines
2.4 KiB
Ruby
87 lines
2.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Sanitize
|
|
module Config
|
|
HTTP_PROTOCOLS ||= ['http', 'https', 'dat', 'dweb', 'ipfs', 'ipns', 'ssb', 'gopher', :relative].freeze
|
|
|
|
CLASS_WHITELIST_TRANSFORMER = lambda do |env|
|
|
node = env[:node]
|
|
class_list = node['class']&.split(/[\t\n\f\r ]/)
|
|
|
|
return unless class_list
|
|
|
|
class_list.keep_if do |e|
|
|
next true if e =~ /^(h|p|u|dt|e)-/ # microformats classes
|
|
next true if e =~ /^(mention|hashtag)$/ # semantic classes
|
|
next true if e =~ /^(ellipsis|invisible)$/ # link formatting classes
|
|
end
|
|
|
|
node['class'] = class_list.join(' ')
|
|
end
|
|
|
|
UNSUPPORTED_ELEMENTS_TRANSFORMER = lambda do |env|
|
|
return unless %w(h1 h2 h3 h4 h5 h6 blockquote pre ul ol li).include?(env[:node_name])
|
|
|
|
case env[:node_name]
|
|
when 'li'
|
|
env[:node].traverse do |node|
|
|
node.add_next_sibling('<br>') if node.next_sibling
|
|
node.replace(node.children) unless node.text?
|
|
end
|
|
else
|
|
env[:node].name = 'p'
|
|
end
|
|
end
|
|
|
|
MASTODON_STRICT ||= freeze_config(
|
|
elements: %w(p br span a abbr del pre blockquote code b strong i em h1 h2 h3 h4 h5 ul ol li),
|
|
|
|
attributes: {
|
|
'a' => %w(href rel class title),
|
|
'span' => %w(class),
|
|
'abbr' => %w(title),
|
|
'blockquote' => %w(cite),
|
|
},
|
|
|
|
add_attributes: {
|
|
'a' => {
|
|
'rel' => 'nofollow noopener',
|
|
'target' => '_blank',
|
|
},
|
|
},
|
|
|
|
protocols: {
|
|
'a' => { 'href' => HTTP_PROTOCOLS },
|
|
'blockquote' => { 'cite' => HTTP_PROTOCOLS },
|
|
},
|
|
|
|
transformers: [
|
|
CLASS_WHITELIST_TRANSFORMER,
|
|
UNSUPPORTED_ELEMENTS_TRANSFORMER,
|
|
]
|
|
)
|
|
|
|
MASTODON_OEMBED ||= freeze_config merge(
|
|
RELAXED,
|
|
elements: RELAXED[:elements] + %w(audio embed iframe source video),
|
|
|
|
attributes: merge(
|
|
RELAXED[:attributes],
|
|
'audio' => %w(controls),
|
|
'embed' => %w(height src type width),
|
|
'iframe' => %w(allowfullscreen frameborder height scrolling src width),
|
|
'source' => %w(src type),
|
|
'video' => %w(controls height loop width),
|
|
'div' => [:data]
|
|
),
|
|
|
|
protocols: merge(
|
|
RELAXED[:protocols],
|
|
'embed' => { 'src' => HTTP_PROTOCOLS },
|
|
'iframe' => { 'src' => HTTP_PROTOCOLS },
|
|
'source' => { 'src' => HTTP_PROTOCOLS }
|
|
)
|
|
)
|
|
end
|
|
end
|