From f80c215a283cd045d2a371403e6eba88b2911192 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Mon, 3 Oct 2022 21:10:05 +0200 Subject: [PATCH] SECURITY: Render TOC items as plain text (#44) --- about.json | 1 + .../discourse/initializers/disco-toc-main.js | 6 ++-- package.json | 2 +- test/acceptance/toc-test.js | 28 +++++++++++++++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/about.json b/about.json index 5c5090e..7cfcea2 100644 --- a/about.json +++ b/about.json @@ -3,6 +3,7 @@ "component": true, "about_url": "https://meta.discourse.org/t/discotoc-automatic-table-of-contents/111143", "license_url": "https://github.com/discourse/DiscoTOC/blob/main/LICENSE", + "theme_version": "2.1.0", "assets": { "icons-sprite": "/assets/sprite.svg" } diff --git a/javascripts/discourse/initializers/disco-toc-main.js b/javascripts/discourse/initializers/disco-toc-main.js index 4765b71..13fd7ce 100644 --- a/javascripts/discourse/initializers/disco-toc-main.js +++ b/javascripts/discourse/initializers/disco-toc-main.js @@ -286,9 +286,9 @@ export default { li.classList.add("d-toc-item"); li.classList.add(`d-toc-${clonedNode.tagName.toLowerCase()}`); - li.innerHTML = `${ - clonedNode.textContent - }`; + const id = clonedNode.getAttribute("id"); + li.innerHTML = ``; + li.querySelector("a").innerText = clonedNode.textContent.trim(); clonedNode.remove(); return li; diff --git a/package.json b/package.json index 421ab82..17f48ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "DiscoTOC", - "version": "2.0.0", + "version": "2.1.0", "repository": "https://github.com/discourse/DiscoTOC", "author": "Discourse", "license": "MIT", diff --git a/test/acceptance/toc-test.js b/test/acceptance/toc-test.js index be8e69a..0b38e69 100644 --- a/test/acceptance/toc-test.js +++ b/test/acceptance/toc-test.js @@ -122,3 +122,31 @@ acceptance("DiscoTOC - with categories", function (needs) { assert.ok(exists(".d-toc-wrapper #d-toc")); }); }); + +acceptance("DiscoTOC - non-text headings", function (needs) { + needs.pretender((server, helper) => { + const topicResponse = cloneJSON(topicFixtures["/t/280/1.json"]); + topicResponse.post_stream.posts[0].cooked = ` +

+ <span style="color: red">what about this</span>

+ +

test

+ ${TOC_MARKUP} + `; + + server.get("/t/280.json", () => helper.response(topicResponse)); + server.get("/t/280/:post_number.json", () => + helper.response(topicResponse) + ); + }); + + test("renders the TOC items as plain text", async function (assert) { + await visit("/t/internationalization-localization/280"); + + const item = query(`#d-toc [data-d-toc="toc-h3-span"]`); + assert.strictEqual( + item.innerHTML.trim(), + `<span style="color: red">what about this</span>` + ); + }); +});