Skip to content

Commit c484c04

Browse files
patricksimonianGatsbyJS Bot
andcommitted
feat(gatsby-remark-prism-js): add additional html escapes (#20156)
* add feature to provide additional html escape sequences address test failures * modify escapehtml routine to combine the functionality of lodash.escape * add test for base html escapes being used with additional escapes Co-authored-by: GatsbyJS Bot <[email protected]>
1 parent 11fe33f commit c484c04

File tree

6 files changed

+70
-10
lines changed

6 files changed

+70
-10
lines changed

packages/gatsby-remark-prismjs/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ plugins: [
7575
host: "localhost",
7676
global: false,
7777
},
78+
// By default the HTML entities <>&'" are escaped.
79+
// Add additional HTML escapes by providing a mapping
80+
// of HTML entities and their escape value IE: { '}': '&#123;' }
81+
escapeEntities: {},
7882
},
7983
},
8084
],
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const escapeHtml = require(`../escape-html`)
2+
3+
describe(`escaping html entities`, () => {
4+
it(`escapes base html when no additional escapes are passed in`, () => {
5+
const code = `hello world&><"'`
6+
expect(escapeHtml(code)).toBe(`hello world&amp;&gt;&lt;&quot;&#39;`)
7+
})
8+
9+
it(`escapes additional html entities when passed in`, () => {
10+
const code = `hello world{`
11+
const mapping = {
12+
"{": `&#123;`,
13+
}
14+
expect(escapeHtml(code, mapping)).toBe(`hello world&#123;`)
15+
})
16+
17+
it(`escapes base html entities and additional html entities`, () => {
18+
const code = `hello world&><"'{`
19+
const mapping = {
20+
"{": `&#123;`,
21+
}
22+
expect(escapeHtml(code, mapping)).toBe(
23+
`hello world&amp;&gt;&lt;&quot;&#39;&#123;`
24+
)
25+
})
26+
})

packages/gatsby-remark-prismjs/src/__tests__/highlight-code.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ int sum(a, b) {
1313
}
1414
`
1515
expect(
16-
highlightCode(language, code, lineNumbersHighlight)
16+
highlightCode(language, code, {}, lineNumbersHighlight)
1717
).toMatchSnapshot()
1818
})
1919

@@ -48,7 +48,7 @@ class Counter extends React.Component {
4848
4949
export default Counter
5050
`
51-
const processed = highlightCode(language, code, lineNumbersHighlight)
51+
const processed = highlightCode(language, code, {}, lineNumbersHighlight)
5252

5353
expect(processed).toMatchSnapshot()
5454
// expect spans to not contain \n as it would break line highlighting
@@ -62,7 +62,7 @@ export default Counter
6262
const highlightCode = require(`../highlight-code`)
6363
const language = `text`
6464
const code = `<button />`
65-
expect(highlightCode(language, code, [], true)).toMatch(
65+
expect(highlightCode(language, code, {}, [], true)).toMatch(
6666
`&lt;button /&gt;`
6767
)
6868
expect(console.warn).toHaveBeenCalledWith(
@@ -141,15 +141,17 @@ export default Counter
141141
const language = `javascript`
142142
const linesToHighlight = [1]
143143
const code = `const a = 1\nconst b = 2`
144-
expect(highlightCode(language, code, linesToHighlight)).not.toMatch(/\n$/)
144+
expect(highlightCode(language, code, {}, linesToHighlight)).not.toMatch(
145+
/\n$/
146+
)
145147
})
146148

147149
it(`a trailing newline is preserved`, () => {
148150
const highlightCode = require(`../highlight-code`)
149151
const language = `javascript`
150152
const linesToHighlight = [1]
151153
const code = `const a = 1\nconst b = 2\n`
152-
expect(highlightCode(language, code, linesToHighlight)).toMatch(
154+
expect(highlightCode(language, code, {}, linesToHighlight)).toMatch(
153155
/[^\n]\n$/
154156
)
155157
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = (code, additionalHtmlEscapes = {}) => {
2+
const baseHTMLEscapes = {
3+
"&": `&amp;`,
4+
">": `&gt;`,
5+
"<": `&lt;`,
6+
'"': `&quot;`,
7+
"'": `&#39;`,
8+
}
9+
10+
const htmlEscapes = {
11+
...additionalHtmlEscapes,
12+
...baseHTMLEscapes,
13+
}
14+
15+
const escapedChars = char => htmlEscapes[char]
16+
17+
const chars = Object.keys(htmlEscapes)
18+
19+
const charsRe = new RegExp(`[${chars.join()}]`, `g`)
20+
21+
const rehasUnescapedChars = new RegExp(charsRe.source)
22+
23+
return code && rehasUnescapedChars.test(code)
24+
? code.replace(charsRe, escapedChars)
25+
: code
26+
}

packages/gatsby-remark-prismjs/src/highlight-code.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
const Prism = require(`prismjs`)
2-
const _ = require(`lodash`)
32
const loadPrismLanguage = require(`./load-prism-language`)
43
const handleDirectives = require(`./directives`)
4+
const escapeHTML = require(`./escape-html`)
55
const unsupportedLanguages = new Set()
66

77
module.exports = (
88
language,
99
code,
10+
additionalEscapeCharacters = {},
1011
lineNumbersHighlight = [],
1112
noInlineHighlight = false
1213
) => {
@@ -34,7 +35,7 @@ module.exports = (
3435
console.warn(message, `applying generic code block`)
3536
unsupportedLanguages.add(lang)
3637
}
37-
return _.escape(code)
38+
return escapeHTML(code, additionalEscapeCharacters)
3839
}
3940
}
4041

packages/gatsby-remark-prismjs/src/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const visit = require(`unist-util-visit`)
2-
32
const parseOptions = require(`./parse-options`)
43
const loadLanguageExtension = require(`./load-prism-language-extension`)
54
const highlightCode = require(`./highlight-code`)
@@ -20,6 +19,7 @@ module.exports = (
2019
host: `localhost`,
2120
global: false,
2221
},
22+
escapeEntities = {},
2323
} = {}
2424
) => {
2525
const normalizeLanguage = lang => {
@@ -94,7 +94,7 @@ module.exports = (
9494
+ `<pre${numLinesStyle} class="${className}${numLinesClass}">`
9595
+ `<code class="${className}">`
9696
+ `${useCommandLine ? commandLine(node.value, outputLines, promptUser, promptHost) : ``}`
97-
+ `${highlightCode(languageName, node.value, highlightLines, noInlineHighlight)}`
97+
+ `${highlightCode(languageName, node.value, escapeEntities, highlightLines, noInlineHighlight)}`
9898
+ `</code>`
9999
+ `${numLinesNumber}`
100100
+ `</pre>`
@@ -118,7 +118,8 @@ module.exports = (
118118
node.type = `html`
119119
node.value = `<code class="${className}">${highlightCode(
120120
languageName,
121-
node.value
121+
node.value,
122+
escapeEntities
122123
)}</code>`
123124
})
124125
}

0 commit comments

Comments
 (0)