1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# frozen_string_literal: true
class Sanitize
module Config
HTTP_PROTOCOLS = %w(
http
https
).freeze
LINK_PROTOCOLS = %w(
http
https
dat
dweb
ipfs
ipns
ssb
gopher
xmpp
magnet
).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
next true if %w(center centered abstract).include?(e)
end
node['class'] = class_list.join(' ')
end
DATA_NAME_ALLOWLIST_TRANSFORMER = lambda do |env|
node = env[:node]
name_list = node['data-name']&.split(/[\t\n\f\r ]/)
return unless name_list
name_list.keep_if do |name|
next true if %w(summary abstract permalink footer).include?(name)
end
node['data-name'] = name_list.join(' ')
end
LINK_REL_TRANSFORMER = lambda do |env|
return unless env[:node_name] == 'a' and env[:node]['href']
node = env[:node]
rel = (node['rel'] || '').split(' ') & ['tag']
unless env[:config][:outgoing] && TagManager.instance.local_url?(node['href'])
rel += ['nofollow', 'noopener', 'noreferrer']
end
node['rel'] = rel.join(' ')
end
UNSUPPORTED_HREF_TRANSFORMER = lambda do |env|
return unless env[:node_name] == 'a'
current_node = env[:node]
scheme = begin
if current_node['href'] =~ Sanitize::REGEX_PROTOCOL
Regexp.last_match(1).downcase
else
:relative
end
end
current_node.replace(current_node.text) unless LINK_PROTOCOLS.include?(scheme)
end
MASTODON_STRICT ||= freeze_config(
elements: %w(p br span a abbr del pre blockquote code b strong u sub sup i em h1 h2 h3 h4 h5 ul ol li img h6 s center details summary),
attributes: {
'a' => %w(href rel class title),
'span' => %w(class),
'abbr' => %w(title),
'blockquote' => %w(cite data-name),
'ol' => %w(start reversed),
'li' => %w(value),
'img' => %w(src alt title),
'p' => %w(data-name),
},
add_attributes: {
'a' => {
'target' => '_blank',
},
},
protocols: {
'a' => { 'href' => LINK_PROTOCOLS },
'blockquote' => { 'cite' => LINK_PROTOCOLS },
},
transformers: [
CLASS_WHITELIST_TRANSFORMER,
DATA_NAME_ALLOWLIST_TRANSFORMER,
UNSUPPORTED_HREF_TRANSFORMER,
LINK_REL_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
|