Skip to content

Commit

Permalink
remark-prismjs: add aliases for languages (#4688)
Browse files Browse the repository at this point in the history
* remark-prismjs: refactor tests into pre and code

* remark-prismjs: add aliases for languages

This allows specifying aliases for languages when using prismjs.

Fixes #4549
  • Loading branch information
docwhat authored and KyleAMathews committed Mar 24, 2018
1 parent 827deb9 commit efdef90
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 50 deletions.
5 changes: 5 additions & 0 deletions packages/gatsby-remark-prismjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ plugins: [
// A suggested value for English speakers is the non-ascii
// character '›'.
inlineCodeMarker: null,
// This lets you set up language aliases. For example,
// setting this to '{ sh: "bash" }' will let you use
// the language "sh" which will highlight using the
// bash highlighter.
aliases: {},
},
},
],
Expand Down
135 changes: 117 additions & 18 deletions packages/gatsby-remark-prismjs/src/__tests__/__snapshots__/index.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,49 @@ Object {
}
`;
exports[`remark prism plugin generates a <pre> tag with aliases applied 1`] = `
Object {
"children": Array [
Object {
"lang": "foobar",
"position": Position {
"end": Object {
"column": 4,
"line": 3,
"offset": 21,
},
"indent": Array [
1,
1,
],
"start": Object {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "html",
"value": "<div class=\\"gatsby-highlight\\">
<pre class=\\"language-javascript\\"><code class=\\"language-javascript\\">// Fake</code></pre>
</div>",
},
],
"position": Object {
"end": Object {
"column": 4,
"line": 3,
"offset": 21,
},
"start": Object {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "root",
}
`;
exports[`remark prism plugin generates a <pre> tag with class="language-*" prefix by default 1`] = `
Object {
"children": Array [
Expand Down Expand Up @@ -88,17 +131,17 @@ Object {
}
`;
exports[`remark prism plugin generates inline <code> tag with a custom class prefix if configured 1`] = `
exports[`remark prism plugin generates an inline <code> tag that handles language specifiers 1`] = `
Object {
"children": Array [
Object {
"children": Array [
Object {
"position": Position {
"end": Object {
"column": 10,
"column": 29,
"line": 1,
"offset": 9,
"offset": 28,
},
"indent": Array [],
"start": Object {
Expand All @@ -108,14 +151,15 @@ Object {
},
},
"type": "html",
"value": "<code class=\\"custom-text\\">foo bar</code>",
"value": "<code class=\\"language-css\\"><span class=\\"token selector\\">.foo</span> <span class=\\"token punctuation\\">{</span> <span class=\\"token property\\">color</span><span class=\\"token punctuation\\">:</span> red <span class=\\"token punctuation\\">}</span>
</code>",
},
],
"position": Position {
"end": Object {
"column": 10,
"column": 29,
"line": 1,
"offset": 9,
"offset": 28,
},
"indent": Array [],
"start": Object {
Expand All @@ -129,9 +173,9 @@ Object {
],
"position": Object {
"end": Object {
"column": 10,
"column": 29,
"line": 1,
"offset": 9,
"offset": 28,
},
"start": Object {
"column": 1,
Expand All @@ -143,7 +187,7 @@ Object {
}
`;
exports[`remark prism plugin generates inline <code> tag with class="language-*" prefix by default 1`] = `
exports[`remark prism plugin generates an inline <code> tag with a custom class prefix if configured 1`] = `
Object {
"children": Array [
Object {
Expand All @@ -163,7 +207,7 @@ Object {
},
},
"type": "html",
"value": "<code class=\\"language-text\\">foo bar</code>",
"value": "<code class=\\"custom-text\\">foo bar</code>",
},
],
"position": Position {
Expand Down Expand Up @@ -198,17 +242,17 @@ Object {
}
`;
exports[`remark prism plugin inlineCode handles language specifiers 1`] = `
exports[`remark prism plugin generates an inline <code> tag with aliases applied 1`] = `
Object {
"children": Array [
Object {
"children": Array [
Object {
"position": Position {
"end": Object {
"column": 29,
"column": 16,
"line": 1,
"offset": 28,
"offset": 15,
},
"indent": Array [],
"start": Object {
Expand All @@ -218,15 +262,15 @@ Object {
},
},
"type": "html",
"value": "<code class=\\"language-css\\"><span class=\\"token selector\\">.foo</span> <span class=\\"token punctuation\\">{</span> <span class=\\"token property\\">color</span><span class=\\"token punctuation\\">:</span> red <span class=\\"token punctuation\\">}</span>
"value": "<code class=\\"language-javascript\\">Fake
</code>",
},
],
"position": Position {
"end": Object {
"column": 29,
"column": 16,
"line": 1,
"offset": 28,
"offset": 15,
},
"indent": Array [],
"start": Object {
Expand All @@ -240,9 +284,64 @@ Object {
],
"position": Object {
"end": Object {
"column": 29,
"column": 16,
"line": 1,
"offset": 28,
"offset": 15,
},
"start": Object {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "root",
}
`;
exports[`remark prism plugin generates an inline <code> tag with class="language-*" prefix by default 1`] = `
Object {
"children": Array [
Object {
"children": Array [
Object {
"position": Position {
"end": Object {
"column": 10,
"line": 1,
"offset": 9,
},
"indent": Array [],
"start": Object {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "html",
"value": "<code class=\\"language-text\\">foo bar</code>",
},
],
"position": Position {
"end": Object {
"column": 10,
"line": 1,
"offset": 9,
},
"indent": Array [],
"start": Object {
"column": 1,
"line": 1,
"offset": 0,
},
},
"type": "paragraph",
},
],
"position": Object {
"end": Object {
"column": 10,
"line": 1,
"offset": 9,
},
"start": Object {
"column": 1,
Expand Down
77 changes: 49 additions & 28 deletions packages/gatsby-remark-prismjs/src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,59 @@ const remark = require(`remark`)
const plugin = require(`../index`)

describe(`remark prism plugin`, () => {
it(`generates a <pre> tag with class="language-*" prefix by default`, () => {
const code = `\`\`\`js\n// Fake\n\`\`\``
const markdownAST = remark.parse(code)
plugin({ markdownAST })
expect(markdownAST).toMatchSnapshot()
})
describe(`generates a <pre> tag`, () => {
it(`with class="language-*" prefix by default`, () => {
const code = `\`\`\`js\n// Fake\n\`\`\``
const markdownAST = remark.parse(code)
plugin({ markdownAST })
expect(markdownAST).toMatchSnapshot()
})

it(`generates a <pre> tag 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()
})
it(`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()
})

it(`generates inline <code> tag with class="language-*" prefix by default`, () => {
const code = `\`foo bar\``
const markdownAST = remark.parse(code)
plugin({ markdownAST })
expect(markdownAST).toMatchSnapshot()
it(`with aliases applied`, () => {
const code = `\`\`\`foobar\n// Fake\n\`\`\``
const markdownAST = remark.parse(code)
plugin({ markdownAST }, { aliases: { foobar: `javascript` } })
expect(markdownAST).toMatchSnapshot()
})
})

it(`generates inline <code> tag with a custom class prefix if configured`, () => {
const code = `\`foo bar\``
const markdownAST = remark.parse(code)
plugin({ markdownAST }, { classPrefix: `custom-` })
expect(markdownAST).toMatchSnapshot()
})
describe(`generates an inline <code> tag`, () => {
it(`with class="language-*" prefix by default`, () => {
const code = `\`foo bar\``
const markdownAST = remark.parse(code)
plugin({ markdownAST })
expect(markdownAST).toMatchSnapshot()
})

it(`with a custom class prefix if configured`, () => {
const code = `\`foo bar\``
const markdownAST = remark.parse(code)
plugin({ markdownAST }, { classPrefix: `custom-` })
expect(markdownAST).toMatchSnapshot()
})

it(`that handles language specifiers`, () => {
const code = `\`css🍺 .foo { color: red }\``
const markdownAST = remark.parse(code)
plugin({ markdownAST }, { inlineCodeMarker: `🍺 ` })
expect(markdownAST).toMatchSnapshot()
})

it(`inlineCode handles language specifiers`, () => {
const code = `\`css🍺 .foo { color: red }\``
const markdownAST = remark.parse(code)
plugin({ markdownAST }, { inlineCodeMarker: `🍺 ` })
expect(markdownAST).toMatchSnapshot()
it(`with aliases applied`, () => {
const code = `\`foobar : Fake\``
const markdownAST = remark.parse(code)
plugin(
{ markdownAST },
{ inlineCodeMarker: ` : `, aliases: { foobar: `javascript` } }
)
expect(markdownAST).toMatchSnapshot()
})
})
})
12 changes: 8 additions & 4 deletions packages/gatsby-remark-prismjs/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ const highlightCode = require(`./highlight-code`)

module.exports = (
{ markdownAST },
{ classPrefix = `language-`, inlineCodeMarker = null } = {}
{ classPrefix = `language-`, inlineCodeMarker = null, aliases = {} } = {}
) => {
const normalizeLanguage = lang => {
const lower = lang.toLowerCase()
return aliases[lower] || lower
}

visit(markdownAST, `code`, node => {
let language = node.lang
let { splitLanguage, highlightLines } = parseLineNumberRange(language)
Expand All @@ -20,8 +25,7 @@ module.exports = (
// @see https://github.com/PrismJS/prism/blob/1d5047df37aacc900f8270b1c6215028f6988eb1/themes/prism.css#L49-L54
let languageName = `text`
if (language) {
language = language.toLowerCase()
languageName = language
languageName = normalizeLanguage(language)
}

// Allow users to specify a custom class prefix to avoid breaking
Expand Down Expand Up @@ -49,7 +53,7 @@ module.exports = (
if (inlineCodeMarker) {
let [language, restOfValue] = node.value.split(`${inlineCodeMarker}`, 2)
if (language && restOfValue) {
languageName = language.toLowerCase()
languageName = normalizeLanguage(language)
node.value = restOfValue
}
}
Expand Down

0 comments on commit efdef90

Please sign in to comment.