diff --git a/lib/sanitize_ext/sanitize_config.rb b/lib/sanitize_ext/sanitize_config.rb index 7387807e47..c264548eb5 100644 --- a/lib/sanitize_ext/sanitize_config.rb +++ b/lib/sanitize_ext/sanitize_config.rb @@ -64,6 +64,44 @@ class Sanitize current_node.wrap('

') end + # We assume that incomming nodes are of the form + # ...... + # according to the [FEP]. We try to grab the most relevant plain-text + # annotation from the semantics node, and use it to display a representation + # of the mathematics. + # + # FEP: https://codeberg.org/fediverse/fep/src/branch/main/fep/dc88/fep-dc88.md + MATH_TRANSFORMER = lambda do |env| + math = env[:node] + return if env[:is_allowlisted] + return unless math.element? && env[:node_name] == 'math' + + semantics = math.element_children[0] + return if semantics.nil? || semantics.name != 'semantics' + + # next, we find the plain-text description + is_annotation_with_encoding = lambda do |encoding, node| + return false unless node.name == 'annotation' + + node.attributes['encoding'].value == encoding + end + + annotation = semantics.children.find(&is_annotation_with_encoding.curry['application/x-tex']) + if annotation + text = if math.attributes['display']&.value == 'block' + "$$#{annotation.text}$$" + else + "$#{annotation.text}$" + end + math.replace(math.document.create_text_node(text)) + return + end + # Don't bother surrounding 'text/plain' annotations with dollar signs, + # since it isn't LaTeX + annotation = semantics.children.find(&is_annotation_with_encoding.curry['text/plain']) + math.replace(math.document.create_text_node(annotation.text)) unless annotation.nil? + end + MASTODON_STRICT = freeze_config( elements: %w(p br span a del s pre blockquote code b strong u i em ul ol li ruby rt rp), @@ -86,6 +124,7 @@ class Sanitize transformers: [ ALLOWED_CLASS_TRANSFORMER, TRANSLATE_TRANSFORMER, + MATH_TRANSFORMER, UNSUPPORTED_ELEMENTS_TRANSFORMER, UNSUPPORTED_HREF_TRANSFORMER, ] diff --git a/spec/lib/sanitize/config_spec.rb b/spec/lib/sanitize/config_spec.rb index 17b78a95f6..b1cab85827 100644 --- a/spec/lib/sanitize/config_spec.rb +++ b/spec/lib/sanitize/config_spec.rb @@ -57,5 +57,25 @@ RSpec.describe Sanitize::Config do it 'keeps a with supported scheme and no host' do expect(Sanitize.fragment('Test', subject)).to eq 'Test' end + + it 'sanitizes math to LaTeX' do + mathml = 'xn+yx^n+y' + expect(Sanitize.fragment(mathml, subject)).to eq '$x^n+y$' + end + + it 'sanitizes math blocks to LaTeX' do + mathml = 'xn+yx^n+y' + expect(Sanitize.fragment(mathml, subject)).to eq '$$x^n+y$$' + end + + it 'math sanitizer falls back to plaintext' do + mathml = 'xsqrt(x)' + expect(Sanitize.fragment(mathml, subject)).to eq 'sqrt(x)' + end + + it 'prefers latex' do + mathml = 'xsqrt(x)\\sqrt x' + expect(Sanitize.fragment(mathml, subject)).to eq '$\sqrt x$' + end end end