| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| // Like assert_array_equals, but disregard element order. |
| function assert_array_same(actual, expected) { |
| assert_array_equals(actual.sort(), expected.sort()); |
| } |
| |
| // Element names: |
| const elems_valid = [ |
| "p", "template", "span", "custom-elements", "potato", |
| // Arguments will be stringified, so anything that stringifies to a valid |
| // name is also valid. |
| 123 |
| ]; |
| const elems_invalid = [ |
| "", {name: ""}, |
| ]; |
| |
| // Attribute names: |
| const attrs_valid = [ |
| "href", "span", |
| ]; |
| const attrs_invalid = [ |
| ]; |
| |
| const all_elems = elems_valid.concat(elems_invalid); |
| const all_attrs = attrs_valid.concat(attrs_invalid); |
| for (const item of ["elements", "removeElements", "replaceWithChildrenElements"]) { |
| test(t => { |
| const sanitizer = new Sanitizer({[item]: all_elems}); |
| assert_array_same(sanitizer.getConfiguration()[item], |
| elems_valid.map(x => "" + x)); |
| }, `Element names in config item: ${item}`); |
| } |
| for (const item of ["attributes", "removeAttributes"]) { |
| test(t => { |
| const sanitizer = new Sanitizer({[item]: all_attrs}); |
| assert_array_same(Object.keys(sanitizer.getConfiguration()[item]), |
| attrs_valid.map(x => "" + x)); |
| }, `Attribute names in config item: ${item}`); |
| } |
| |
| // Quick sanity tests for namespaced elements. |
| // Each test case is a duo or triplet: |
| // - a Sanitizer config string for an element. |
| // - an HTML probe string. |
| // - the expected result. (If different from the probe.) |
| const SVG_NS = "http://www.w3.org/2000/svg"; |
| const MATHML_NS = "http://www.w3.org/1998/Math/MathML"; |
| [ |
| [ "p", "<p>Hello</p>" ], |
| [ "svg", "<svg>Hello</svg>", "Hello" ], |
| [ { name: "svg", namespace: SVG_NS }, "<svg>Hello</svg>" ], |
| [ "math", "<math>Hello</math>", "Hello" ], |
| [ { name: "math", namespace: SVG_NS }, "<math>Hello</math>", "Hello" ], |
| [ { name: "math", namespace: MATHML_NS }, "<math>Hello</math>" ], |
| ].forEach(([elem, probe, expected], index) => { |
| test(t => { |
| const options = { elements: [elem], |
| // TODO(https://github.com/WICG/sanitizer-api/issues/167) |
| unknownMarkup: true}; |
| const template = document.createElement("template"); |
| template.setHTML(probe, {sanitizer: options}); |
| assert_equals(template.innerHTML, expected ?? probe); |
| }, `Namespaced elements #${index}: elements: [${JSON.stringify(elem)}]`); |
| }); |
| |
| // Same for attributes: |
| const XLINK_NS = "http://www.w3.org/1999/xlink"; |
| [ |
| [ { name: "style"}, "<p style=\"bla\"></p>" ], |
| [ { name: "href"}, "<p href=\"bla\"></p>" ], |
| [ { name: "xlink:href"}, "<p xlink:href=\"bla\"></p>" ], |
| [ { name: "href", namespace: XLINK_NS}, "<p xlink:href=\"bla\"></p>", "<p></p>" ], |
| [ { name: "href", namespace: XLINK_NS}, "<p href='bla'></p>", "<p></p>" ], |
| [ { name: "href"}, "<p xlink:href='bla'></p>", "<p></p>" ], |
| ].forEach(([attr, probe, expected], index) => { |
| test(t => { |
| const options = {attributes: [attr], |
| // TODO(https://github.com/WICG/sanitizer-api/issues/167) |
| unknownMarkup: true}; |
| const template = document.createElement("template"); |
| template.setHTML(probe, {sanitizer: options}); |
| assert_equals(template.innerHTML, expected ?? probe); |
| }, `Namespaced attributes #${index}: attributes: [${JSON.stringify(attr)}]`); |
| }); |
| |
| // Test for namespaced attribute inside namespace element |
| test(t => { |
| const probe = `<svg><a xlink:href="bla"></a></svg>`; |
| |
| const options = { |
| elements: [ |
| {name: "svg", namespace: SVG_NS}, |
| {name: "a", namespace: SVG_NS, attributes: [ |
| { name: "href", namespace: XLINK_NS } |
| ]} |
| ], |
| // TODO(https://github.com/WICG/sanitizer-api/issues/167) |
| unknownMarkup: true}; |
| const template = document.createElement("template"); |
| template.setHTML(probe, {sanitizer: options}); |
| assert_equals(template.innerHTML, probe); |
| }, "Namespaced attribute xlink:href inside SVG tree"); |
| |
| // Most element and attribute names are lower-cased, but "foreign content" |
| // like SVG and MathML have some mixed-cased names. |
| [ |
| [ "feBlend", "<feBlend></feBlend>" ], |
| [ "feColorMatrix", "<feColorMatrix></feColorMatrix>" ], |
| [ "textPath", "<textPath></textPath>" ], |
| ].forEach(([elem, probe], index) => { |
| const sanitize = (elem, probe) => { |
| const options = {elements: [ |
| { name: "svg", namespace: SVG_NS }, |
| { name: elem, namespace: SVG_NS } |
| ], |
| // TODO(https://github.com/WICG/sanitizer-api/issues/167) |
| unknownMarkup: true}; |
| const template = document.createElement("template"); |
| template.setHTML(`<svg>${probe}</svg>`, {sanitizer: options}); |
| return template.content.firstElementChild.innerHTML; |
| }; |
| test(t => { |
| assert_equals(sanitize(elem, probe), probe); |
| }, `Mixed-case element names #${index}: "svg:${elem}"`); |
| test(t => { |
| // Lowercase element names should be normalized to mixed-case. |
| assert_equals(sanitize(elem.toLowerCase(), probe), probe); |
| }, `Lower-case element names #${index}: "svg:${elem.toLowerCase()}"`); |
| test(t => { |
| assert_not_equals(sanitize(elem.toUpperCase(), probe), probe); |
| }, `Upper-case element names #${index}: "svg:${elem.toUpperCase()}"`); |
| test(t => { |
| const elems = ["svg:" + elem]; |
| assert_array_equals( |
| new Sanitizer({elements: elems}).getConfiguration().allowElements, |
| elems); |
| }, `Mixed case element names #${index}: "${elem}" is preserved in config.`); |
| }); |
| </script> |
| </body> |
| </html> |