mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-06-18 20:40:03 +08:00
This commit updates the graphviz plugin implementation to match the official Discourse mermaid theme-component. This moves the rendering to be 100% client-side and 100% SVG, with a builtin fullscreen view. The change improves image quality and simplifies the implementation. Graphviz diagrams will now adopt a fixed 16:9 size in posts, to avoid any scroll jumps.
71 lines
2.9 KiB
JavaScript
Vendored
71 lines
2.9 KiB
JavaScript
Vendored
/* eslint-disable no-script-url */
|
|
import { module, test } from "qunit";
|
|
import { sanitizeGraphvizSvg } from "discourse/plugins/discourse-graphviz/discourse/lib/render-graphviz";
|
|
|
|
function sanitize(inner) {
|
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">${inner}</svg>`;
|
|
const doc = new DOMParser().parseFromString(svg, "image/svg+xml");
|
|
return sanitizeGraphvizSvg(doc.documentElement).outerHTML;
|
|
}
|
|
|
|
module("Unit | Utility | render-graphviz | sanitize", function () {
|
|
test("strips anchors with javascript: URLs", function (assert) {
|
|
const result = sanitize(
|
|
`<a xlink:href="javascript:alert(1)"><text>x</text></a>`
|
|
);
|
|
assert.false(result.includes("javascript:"), "removes javascript scheme");
|
|
assert.true(result.includes("<text"), "keeps the inner content");
|
|
});
|
|
|
|
test("strips anchors case-insensitively", function (assert) {
|
|
const result = sanitize(
|
|
`<a xlink:href="JaVaScRiPt:alert(1)"><text>x</text></a>`
|
|
);
|
|
assert.false(/javascript:/i.test(result), "removes mixed-case javascript");
|
|
});
|
|
|
|
test("strips data:, vbscript:, file: and mailto: URLs", function (assert) {
|
|
for (const scheme of [
|
|
"data:text/html,alert(1)",
|
|
"vbscript:alert(1)",
|
|
"file:///etc/passwd",
|
|
"mailto:test@example.com",
|
|
]) {
|
|
const result = sanitize(`<a xlink:href="${scheme}"><text>x</text></a>`);
|
|
assert.true(
|
|
result.includes("<text"),
|
|
`unwraps anchor but keeps content for ${scheme}`
|
|
);
|
|
assert.false(result.includes("<a"), `removes the anchor for ${scheme}`);
|
|
}
|
|
});
|
|
|
|
test("preserves http and https URLs", function (assert) {
|
|
for (const url of ["http://example.com", "https://example.com"]) {
|
|
const result = sanitize(`<a xlink:href="${url}"><text>x</text></a>`);
|
|
assert.true(result.includes(url), `keeps ${url}`);
|
|
assert.true(result.includes("<a"), `keeps the anchor for ${url}`);
|
|
}
|
|
});
|
|
|
|
test("preserves relative URLs", function (assert) {
|
|
const result = sanitize(`<a xlink:href="/some/path"><text>x</text></a>`);
|
|
assert.true(result.includes("/some/path"), "keeps relative path");
|
|
assert.true(result.includes("<a"), "keeps the anchor");
|
|
});
|
|
|
|
test("removes script and foreignObject elements", function (assert) {
|
|
const result = sanitize(
|
|
`<script>alert(1)</script><foreignObject><div>x</div></foreignObject><text>ok</text>`
|
|
);
|
|
assert.false(result.includes("alert"), "removes script content");
|
|
assert.false(result.includes("foreignObject"), "removes foreignObject");
|
|
assert.true(result.includes("ok"), "keeps safe content");
|
|
});
|
|
|
|
test("strips on* event handler attributes", function (assert) {
|
|
const result = sanitize(`<rect onclick="alert(1)" width="10"></rect>`);
|
|
assert.false(result.includes("onclick"), "removes onclick attribute");
|
|
assert.true(result.includes("width"), "keeps benign attributes");
|
|
});
|
|
});
|