color_transformer = lambda do |env|
node = env[:node]
# Only process element nodes with a style attribute
return unless node.type == Nokogiri::XML::Node::ELEMENT_NODE
return unless node['style']
# Parse each declaration
allowed_declarations = node['style'].split(';').filter_map do |declaration|
property, value = declaration.split(':').map(&:strip)
next unless property == 'color'
# Allow only:
# - Named colors: red, blue, darkslategray, etc. OR NOT?
# - Hex colors: #fff, #ff6600
# - RGB: rgb(0, 128, 255)
# - HSL: hsl(120, 100%, 50%)
valid_color = value.match?(
/\A(
\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}) | # hex
rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\) | # rgb()
hsl\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*\) | # hsl()
[a-zA-Z]{2,50} # named color
)\z/x
)
"color: #{value}" if valid_color
end
if allowed_declarations&.any?
node['style'] = allowed_declarations.join('; ')
else
node.remove_attribute('style')
end
end
config = {
elements: ['p', 'span', 'em', 'strong'],
attributes: {
:all => ['style']
},
css: {
properties: ['color']
},
transformers: [color_transformer]
}
Sanitize.fragment(html, config)
Originally posted by @perlygatekeeper in #1440