diff --git a/package.json b/package.json index cdeffd635..df74d8e45 100755 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "cross-spawn": "^7.0.3", "debug": "^4.3.6", "dependency-graph": "^1.0.0", + "entities": "^5.0.0", "fast-glob": "^3.3.2", "filesize": "^10.1.4", "graceful-fs": "^4.2.11", diff --git a/src/Plugins/IdAttributePlugin.js b/src/Plugins/IdAttributePlugin.js index 3afc03339..df5e2a2fe 100644 --- a/src/Plugins/IdAttributePlugin.js +++ b/src/Plugins/IdAttributePlugin.js @@ -1,4 +1,5 @@ import matchHelper from "posthtml-match-helper"; +import { decodeHTML } from "entities"; import slugifyFilter from "../Filters/Slugify.js"; import MemoizeUtil from "../Util/MemoizeFunction.js"; @@ -28,6 +29,7 @@ function IdAttributePlugin(eleventyConfig, options = {}) { if (!options.selector) { options.selector = "h1,h2,h3,h4,h5,h6"; } + options.decodeEntities = options.decodeEntities ?? true; eleventyConfig.htmlTransformer.addPosthtmlPlugin( "html", @@ -39,7 +41,11 @@ function IdAttributePlugin(eleventyConfig, options = {}) { tree.match(matchHelper(options.selector), function (node) { if (!node.attrs?.id && node.content) { node.attrs = node.attrs || {}; - let id = options.slugify(getTextNodeContent(node)); + let textContent = getTextNodeContent(node); + if (options.decodeEntities) { + textContent = decodeHTML(textContent); + } + let id = options.slugify(textContent); if (conflictCheck[id]) { conflictCheck[id]++; id = `${id}-${conflictCheck[id]}`; diff --git a/test/IdAttributePluginTest.js b/test/IdAttributePluginTest.js index 3d1f9f3c5..6e969f9ca 100644 --- a/test/IdAttributePluginTest.js +++ b/test/IdAttributePluginTest.js @@ -17,3 +17,18 @@ test("Using the IdAttribute plugin #3356", async (t) => { let results = await elev.toJSON(); t.is(results[0].content, `

This is a heading

This is another heading

This is another heading

This is another heading

`); }); + +test("Using the IdAttribute plugin with escaped quoted text", async (t) => { + let elev = new Eleventy("./test/stubs-virtual/", "./test/stubs-virtual/_site", { + config: function (eleventyConfig) { + eleventyConfig.addPlugin(IdAttributePlugin); + + eleventyConfig.addTemplate("test.md", `# This is a \`"heading"\``, {}); + }, + }); + + elev.disableLogger(); + + let results = await elev.toJSON(); + t.is(results[0].content.trim(), `

This is a "heading"

`); +});