Skip to content

Commit 233c7d4

Browse files
Aaron Cannonjavawizard
authored andcommitted
A11y: Allow the insertion of MathML via the HTML editor
Fixes CNVS-28473 Test plan: - Visit a page with an editor - Switch to the HTML view. - Insert MathML. - Switch to and from the RCE editor and HTML editor. - Verify that the MathML remains unchanged. - Insure that it is not removed or otherwise redacted on save. Change-Id: I46d55505518f0427fa342eff175a58bdcb0c5284 Reviewed-on: https://gerrit.instructure.com/79588 Tested-by: Jenkins Reviewed-by: Simon Williams <simon@instructure.com> Product-Review: Aaron Cannon <acannon@instructure.com> QA-Review: Pierce Arner <pierce@instructure.com>
1 parent 51bf52a commit 233c7d4

3 files changed

Lines changed: 154 additions & 38 deletions

File tree

gems/canvas_sanitize/lib/canvas_sanitize/canvas_sanitize.rb

Lines changed: 141 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,14 @@ def self.clean_style_value(config, value)
8080
'del', 'ins', 'iframe', 'font',
8181
'colgroup', 'dd', 'div', 'dl', 'dt', 'em', 'figure', 'figcaption', 'i', 'img', 'li', 'ol', 'p', 'pre',
8282
'q', 'small', 'source', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tbody', 'td',
83-
'tfoot', 'th', 'thead', 'tr', 'u', 'ul', 'object', 'embed', 'param', 'video', 'audio'],
83+
'tfoot', 'th', 'thead', 'tr', 'u', 'ul', 'object', 'embed', 'param', 'video', 'audio',
84+
# MathML
85+
'annotation', 'annotation-xml', 'maction', 'maligngroup', 'malignmark', 'math',
86+
'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mlongdiv',
87+
'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mprescripts', 'mroot',
88+
'mrow', 'ms', 'mscarries', 'mscarry', 'msgroup', 'msline', 'mspace', 'msqrt', 'msrow',
89+
'mstack', 'mstyle', 'msub', 'msubsup', 'msup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder',
90+
'munderover', 'none', 'semantics'].freeze,
8491

8592
:attributes => {
8693
:all => ['style',
@@ -128,42 +135,139 @@ def self.clean_style_value(config, value)
128135
'aria-valuemax',
129136
'aria-valuemin',
130137
'aria-valuenow',
131-
'aria-valuetext',
132-
],
133-
'a' => ['href', 'target', 'name'],
134-
'blockquote' => ['cite'],
135-
'col' => ['span', 'width'],
136-
'colgroup' => ['span', 'width'],
137-
'img' => ['align', 'alt', 'height', 'src', 'width'],
138-
'iframe' => ['src', 'width', 'height', 'name', 'align', 'frameborder', 'scrolling', 'sandbox', 'allowfullscreen','webkitallowfullscreen','mozallowfullscreen'],
139-
'ol' => ['start', 'type'],
140-
'q' => ['cite'],
141-
'table' => ['summary', 'width', 'border', 'cellpadding', 'cellspacing', 'center', 'frame', 'rules'],
142-
'tr' => ['align', 'valign', 'dir'],
143-
'td' => ['abbr', 'axis', 'colspan', 'rowspan', 'width', 'align', 'valign', 'dir'],
144-
'th' => ['abbr', 'axis', 'colspan', 'rowspan', 'width', 'align', 'valign', 'dir', 'scope'],
145-
'ul' => ['type'],
146-
'param' => ['name', 'value'],
147-
'object' => ['width', 'height', 'style', 'data', 'type', 'classid', 'codebase'],
148-
'source' => ['src', 'type'],
149-
'embed' => ['name', 'src', 'type', 'allowfullscreen', 'pluginspage', 'wmode', 'allowscriptaccess', 'width', 'height'],
150-
'video' => ['name', 'src', 'allowfullscreen', 'muted', 'poster', 'width', 'height', 'controls'],
151-
'audio' => ['name', 'src', 'muted'],
152-
'font' => ['face', 'color', 'size'],
153-
},
138+
'aria-valuetext'].freeze,
139+
'a' => ['href', 'target', 'name'].freeze,
140+
'blockquote' => ['cite'].freeze,
141+
'col' => ['span', 'width'].freeze,
142+
'colgroup' => ['span', 'width'].freeze,
143+
'img' => ['align', 'alt', 'height', 'src', 'width'].freeze,
144+
'iframe' => ['src', 'width', 'height', 'name', 'align', 'frameborder', 'scrolling',
145+
'sandbox', 'allowfullscreen','webkitallowfullscreen','mozallowfullscreen'].freeze,
146+
'ol' => ['start', 'type'].freeze,
147+
'q' => ['cite'].freeze,
148+
'table' => ['summary', 'width', 'border', 'cellpadding', 'cellspacing', 'center', 'frame', 'rules'].freeze,
149+
'tr' => ['align', 'valign', 'dir'].freeze,
150+
'td' => ['abbr', 'axis', 'colspan', 'rowspan', 'width', 'align', 'valign', 'dir'].freeze,
151+
'th' => ['abbr', 'axis', 'colspan', 'rowspan', 'width', 'align', 'valign', 'dir', 'scope'].freeze,
152+
'ul' => ['type'].freeze,
153+
'param' => ['name', 'value'].freeze,
154+
'object' => ['width', 'height', 'style', 'data', 'type', 'classid', 'codebase'].freeze,
155+
'source' => ['src', 'type'].freeze,
156+
'embed' => ['name', 'src', 'type', 'allowfullscreen', 'pluginspage', 'wmode',
157+
'allowscriptaccess', 'width', 'height'].freeze,
158+
'video' => ['name', 'src', 'allowfullscreen', 'muted', 'poster', 'width', 'height', 'controls'].freeze,
159+
'audio' => ['name', 'src', 'muted'].freeze,
160+
'font' => ['face', 'color', 'size'].freeze,
161+
# MathML
162+
'annotation' => ['href', 'xref', 'definitionURL', 'encoding', 'cd', 'name', 'src'].freeze,
163+
'annotation-xml' => ['href', 'xref', 'definitionURL', 'encoding', 'cd', 'name', 'src'].freeze,
164+
'maction' => ['href', 'xref', 'mathcolor', 'mathbackground', 'actiontype', 'selection'].freeze,
165+
'maligngroup' => ['href', 'xref', 'mathcolor', 'mathbackground', 'groupalign'].freeze,
166+
'malignmark' => ['href', 'xref', 'mathcolor', 'mathbackground', 'edge'].freeze,
167+
'math' => ['href', 'xref', 'display', 'maxwidth', 'overflow', 'altimg', 'altimg-width',
168+
'altimg-height', 'altimg-valign', 'alttext', 'cdgroup', 'mathcolor',
169+
'mathbackground', 'scriptlevel', 'displaystyle', 'scriptsizemultiplier',
170+
'scriptminsize', 'infixlinebreakstyle', 'decimalpoint', 'mathvariant',
171+
'mathsize', 'width', 'height', 'valign', 'form', 'fence', 'separator',
172+
'lspace', 'rspace', 'stretchy', 'symmetric', 'maxsize', 'minsize', 'largeop',
173+
'movablelimits', 'accent', 'linebreak', 'lineleading', 'linebreakstyle',
174+
'linebreakmultchar', 'indentalign', 'indentshift', 'indenttarget',
175+
'indentalignfirst', 'indentshiftfirst', 'indentalignlast', 'indentshiftlast',
176+
'depth', 'lquote', 'rquote', 'linethickness', 'munalign', 'denomalign',
177+
'bevelled', 'voffset', 'open', 'close', 'separators', 'notation',
178+
'subscriptshift', 'superscriptshift', 'accentunder', 'align', 'rowalign',
179+
'columnalign', 'groupalign', 'alignmentscope', 'columnwidth', 'rowspacing',
180+
'columnspacing', 'rowlines', 'columnlines', 'frame', 'framespacing',
181+
'equalrows', 'equalcolumns', 'side', 'minlabelspacing', 'rowspan',
182+
'columnspan', 'edge', 'stackalign', 'charalign', 'charspacing', 'longdivstyle',
183+
'position', 'shift', 'location', 'crossout', 'length', 'leftoverhang',
184+
'rightoverhang', 'mslinethickness', 'selection', 'xmlns'].freeze,
185+
'menclose' => ['href', 'xref', 'mathcolor', 'mathbackground', 'notation'].freeze,
186+
'merror' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
187+
'mfenced' => ['href', 'xref', 'mathcolor', 'mathbackground', 'open', 'close', 'separators'].freeze,
188+
'mfrac' => ['href', 'xref', 'mathcolor', 'mathbackground', 'linethickness', 'munalign',
189+
'denomalign', 'bevelled'].freeze,
190+
'mglyph' => ['href', 'xref', 'mathcolor', 'mathbackground', 'src', 'alt', 'width', 'height', 'valign'].freeze,
191+
'mi' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'].freeze,
192+
'mlabeledtr' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
193+
'mlongdiv' => ['href', 'xref', 'mathcolor', 'mathbackground', 'longdivstyle', 'align',
194+
'stackalign', 'charalign', 'charspacing'].freeze,
195+
'mmultiscripts' => ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift',
196+
'superscriptshift'].freeze,
197+
'mn' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'].freeze,
198+
'mo' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize', 'form',
199+
'fence', 'separator', 'lspace', 'rspace', 'stretchy', 'symmetric', 'maxsize',
200+
'minsize', 'largeop', 'movablelimits', 'accent', 'linebreak', 'lineleading',
201+
'linebreakstyle', 'linebreakmultchar', 'indentalign', 'indentshift',
202+
'indenttarget', 'indentalignfirst', 'indentshiftfirst', 'indentalignlast',
203+
'indentshiftlast'].freeze,
204+
'mover' => ['href', 'xref', 'mathcolor', 'mathbackground', 'accent', 'align'].freeze,
205+
'mpadded' => ['href', 'xref', 'mathcolor', 'mathbackground', 'height', 'depth', 'width',
206+
'lspace', 'voffset'].freeze,
207+
'mphantom' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
208+
'mprescripts' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
209+
'mroot' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
210+
'mrow' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
211+
'ms' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize', 'lquote', 'rquote'].freeze,
212+
'mscarries' => ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'location',
213+
'crossout', 'scriptsizemultiplier'].freeze,
214+
'mscarry' => ['href', 'xref', 'mathcolor', 'mathbackground', 'location', 'crossout'].freeze,
215+
'msgroup' => ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'shift'].freeze,
216+
'msline' => ['href', 'xref', 'mathcolor', 'mathbackground', 'position', 'length',
217+
'leftoverhang', 'rightoverhang', 'mslinethickness'].freeze,
218+
'mspace' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize'].freeze,
219+
'msqrt' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
220+
'msrow' => ['href', 'xref', 'mathcolor', 'mathbackground', 'position'].freeze,
221+
'mstack' => ['href', 'xref', 'mathcolor', 'mathbackground', 'align', 'stackalign',
222+
'charalign', 'charspacing'].freeze,
223+
'mstyle' => ['href', 'xref', 'mathcolor', 'mathbackground', 'scriptlevel', 'displaystyle',
224+
'scriptsizemultiplier', 'scriptminsize', 'infixlinebreakstyle',
225+
'decimalpoint', 'mathvariant', 'mathsize', 'width', 'height', 'valign',
226+
'form', 'fence', 'separator', 'lspace', 'rspace', 'stretchy', 'symmetric',
227+
'maxsize', 'minsize', 'largeop', 'movablelimits', 'accent', 'linebreak',
228+
'lineleading', 'linebreakstyle', 'linebreakmultchar', 'indentalign',
229+
'indentshift', 'indenttarget', 'indentalignfirst', 'indentshiftfirst',
230+
'indentalignlast', 'indentshiftlast', 'depth', 'lquote', 'rquote',
231+
'linethickness', 'munalign', 'denomalign', 'bevelled', 'voffset', 'open',
232+
'close', 'separators', 'notation', 'subscriptshift', 'superscriptshift',
233+
'accentunder', 'align', 'rowalign', 'columnalign', 'groupalign',
234+
'alignmentscope', 'columnwidth', 'rowspacing', 'columnspacing', 'rowlines',
235+
'columnlines', 'frame', 'framespacing', 'equalrows', 'equalcolumns', 'side',
236+
'minlabelspacing', 'rowspan', 'columnspan', 'edge', 'stackalign',
237+
'charalign', 'charspacing', 'longdivstyle', 'position', 'shift', 'location',
238+
'crossout', 'length', 'leftoverhang', 'rightoverhang', 'mslinethickness',
239+
'selection'].freeze,
240+
'msub' => ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift'].freeze,
241+
'msubsup' => ['href', 'xref', 'mathcolor', 'mathbackground', 'subscriptshift', 'superscriptshift'].freeze,
242+
'msup' => ['href', 'xref', 'mathcolor', 'mathbackground', 'superscriptshift'].freeze,
243+
'mtable' => ['href', 'xref', 'mathcolor', 'mathbackground', 'align', 'rowalign',
244+
'columnalign', 'groupalign', 'alignmentscope', 'columnwidth', 'width',
245+
'rowspacing', 'columnspacing', 'rowlines', 'columnlines', 'frame',
246+
'framespacing', 'equalrows', 'equalcolumns', 'displaystyle', 'side',
247+
'minlabelspacing'].freeze,
248+
'mtd' => ['href', 'xref', 'mathcolor', 'mathbackground', 'rowspan', 'columnspan',
249+
'rowalign', 'columnalign', 'groupalign'].freeze,
250+
'mtext' => ['href', 'xref', 'mathcolor', 'mathbackground', 'mathvariant', 'mathsize',
251+
'width', 'height', 'depth', 'linebreak'].freeze,
252+
'mtr' => ['href', 'xref', 'mathcolor', 'mathbackground', 'rowalign', 'columnalign', 'groupalign'].freeze,
253+
'munder' => ['href', 'xref', 'mathcolor', 'mathbackground', 'accentunder', 'align'].freeze,
254+
'munderover' => ['href', 'xref', 'mathcolor', 'mathbackground', 'accent', 'accentunder', 'align'].freeze,
255+
'none' => ['href', 'xref', 'mathcolor', 'mathbackground'].freeze,
256+
'semantics' => ['href', 'xref', 'definitionURL', 'encoding'].freeze,
257+
}.freeze,
154258

155259
:protocols => {
156260
'a' => {'href' => ['ftp', 'http', 'https', 'mailto',
157-
:relative]},
158-
'blockquote' => {'cite' => ['http', 'https', :relative]},
159-
'img' => {'src' => ['http', 'https', :relative]},
160-
'q' => {'cite' => ['http', 'https', :relative]},
161-
'object' => {'data' => ['http', 'https', :relative]},
162-
'embed' => {'src' => ['http', 'https', :relative]},
163-
'iframe' => {'src' => ['http', 'https', :relative]},
164-
'style' => {'any' => ['http', 'https', :relative]}
165-
},
166-
:style_methods => ['url'],
261+
:relative].freeze}.freeze,
262+
'blockquote' => {'cite' => ['http', 'https', :relative].freeze}.freeze,
263+
'img' => {'src' => ['http', 'https', :relative].freeze}.freeze,
264+
'q' => {'cite' => ['http', 'https', :relative].freeze}.freeze,
265+
'object' => {'data' => ['http', 'https', :relative].freeze}.freeze,
266+
'embed' => {'src' => ['http', 'https', :relative].freeze}.freeze,
267+
'iframe' => {'src' => ['http', 'https', :relative].freeze}.freeze,
268+
'style' => {'any' => ['http', 'https', :relative].freeze}.freeze
269+
}.freeze,
270+
:style_methods => ['url'].freeze,
167271
:style_properties => [
168272
'background', 'border', 'clear', 'color',
169273
'cursor', 'direction', 'display', 'float',
@@ -177,7 +281,7 @@ def self.clean_style_value(config, value)
177281
'top', 'vertical-align',
178282
'visibility', 'white-space', 'width',
179283
'z-index', 'zoom'
180-
],
284+
].freeze,
181285
:style_expressions => [
182286
/\Abackground-(?:attachment|color|image|position|repeat)\z/,
183287
/\Abackground-position-(?:x|y)\z/,
@@ -187,12 +291,12 @@ def self.clean_style_value(config, value)
187291
/\Alist-style-(?:image|position|type)\z/,
188292
/\Amargin-(?:bottom|left|right|top|offset)\z/,
189293
/\Apadding-(?:bottom|left|right|top)\z/
190-
],
294+
].freeze,
191295
:transformers => lambda { |env|
192296
CanvasSanitize.sanitize_style(env) if env[:node]['style']
193297
Sanitize.clean_node!(env[:node], {:remove_contents => true}) if env[:node_name] == 'style'
194298
}
195-
}
299+
}.freeze
196300

197301
module ClassMethods
198302

0 commit comments

Comments
 (0)