diff --git a/packages/gatsby-remark-prismjs/README.md b/packages/gatsby-remark-prismjs/README.md index b8f69c0bfe823..d572012e37089 100644 --- a/packages/gatsby-remark-prismjs/README.md +++ b/packages/gatsby-remark-prismjs/README.md @@ -16,7 +16,19 @@ plugins: [ resolve: `gatsby-transformer-remark`, options: { plugins: [ - `gatsby-remark-prismjs`, + { + resolve: `gatsby-remark-prismjs`, + options: { + // Class prefix for
tags containing syntax highlighting; + // defaults to 'language-' (eg). + // If your site loads Prism into the browser at runtime, + // (eg for use with libraries like react-live), + // you may use this to prevent Prism from re-processing syntax. + // This is an uncommon use-case though; + // If you're unsure, it's best to use the default value. + classPrefix: 'language-', + }, + }, ] } } diff --git a/packages/gatsby-remark-prismjs/package.json b/packages/gatsby-remark-prismjs/package.json index d0bdb9fbaaa60..22de6066d5e42 100644 --- a/packages/gatsby-remark-prismjs/package.json +++ b/packages/gatsby-remark-prismjs/package.json @@ -9,7 +9,8 @@ "unist-util-visit": "^1.1.1" }, "devDependencies": { - "babel-cli": "^6.24.1" + "babel-cli": "^6.24.1", + "remark": "^7.0.1" }, "keywords": [ "gatsby", diff --git a/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap new file mode 100644 index 0000000000000..5b2e7c22e5abb --- /dev/null +++ b/packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`remark prism plugin generates atag with a custom class prefix if configured 1`] = ` +Object { + "children": Array [ + Object { + "lang": "js", + "position": Position { + "end": Object { + "column": 4, + "line": 3, + "offset": 17, + }, + "indent": Array [ + 1, + 1, + ], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "html", + "value": "+", + }, + ], + "position": Object { + "end": Object { + "column": 4, + "line": 3, + "offset": 17, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", +} +`; + +exports[`remark prism plugin generates a+// Fake +
tag with class="language-*" prefix by default 1`] = ` +Object { + "children": Array [ + Object { + "lang": "js", + "position": Position { + "end": Object { + "column": 4, + "line": 3, + "offset": 17, + }, + "indent": Array [ + 1, + 1, + ], + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "html", + "value": "+", + }, + ], + "position": Object { + "end": Object { + "column": 4, + "line": 3, + "offset": 17, + }, + "start": Object { + "column": 1, + "line": 1, + "offset": 0, + }, + }, + "type": "root", +} +`; diff --git a/packages/gatsby-remark-prismjs/src/__tests__/index.js b/packages/gatsby-remark-prismjs/src/__tests__/index.js new file mode 100644 index 0000000000000..ffe04b638c80a --- /dev/null +++ b/packages/gatsby-remark-prismjs/src/__tests__/index.js @@ -0,0 +1,18 @@ +const remark = require(`remark`) +const plugin = require(`../index`) + +describe(`remark prism plugin`, () => { + it(`generates a+// Fake +
tag with class="language-*" prefix by default`, () => { + const code = '```js\n// Fake\n```' + const markdownAST = remark.parse(code) + plugin({ markdownAST }) + expect(markdownAST).toMatchSnapshot() + }) + + it(`generates atag with a custom class prefix if configured`, () => { + const code = '```js\n// Fake\n```' + const markdownAST = remark.parse(code) + plugin({ markdownAST }, { classPrefix: 'custom-' }) + expect(markdownAST).toMatchSnapshot() + }) +}) diff --git a/packages/gatsby-remark-prismjs/src/index.js b/packages/gatsby-remark-prismjs/src/index.js index 175f37474914b..29cdfa266e3f9 100644 --- a/packages/gatsby-remark-prismjs/src/index.js +++ b/packages/gatsby-remark-prismjs/src/index.js @@ -3,7 +3,7 @@ const visit = require(`unist-util-visit`) const parseLineNumberRange = require(`./parse-line-number-range`) const highlightCode = require(`./highlight-code`) -module.exports = ({ markdownAST }) => { +module.exports = ({ markdownAST }, { classPrefix = 'language-' } = {}) => { visit(markdownAST, `code`, node => { let language = node.lang let { splitLanguage, highlightLines } = parseLineNumberRange(language) @@ -15,17 +15,24 @@ module.exports = ({ markdownAST }) => { // outcome without any additional CSS. // // @see https://github.com/PrismJS/prism/blob/1d5047df37aacc900f8270b1c6215028f6988eb1/themes/prism.css#L49-L54 - let preCssClassLanguage = `none` + let languageName = `none` if (language) { language = language.toLowerCase() - preCssClassLanguage = language + languageName = language } + // Allow users to specify a custom class prefix to avoid breaking + // line highlights if Prism is required by any other code. + // This supports custom user styling without causing Prism to + // re-process our already-highlighted markup. + // @see https://github.com/gatsbyjs/gatsby/issues/1486 + const className = `${classPrefix}${languageName}` + // Replace the node with the markup we need to make // 100% width highlighted code lines work node.type = `html` node.value = `-${highlightCode( +
${highlightCode( language, node.value, highlightLines