Skip to content

Commit

Permalink
feat(gatsby-remark-prismjs): add show invisibles plugin (#21439)
Browse files Browse the repository at this point in the history
* 20642 Prism show invisibles plugin

* feat(gatsby-remark-prismjs): add show invisibles tests

* feat(gatsby-remark-prismjs): fixes eslint no-redeclare

* feat(gatsby-remark-prismjs): fixes eslint no-redeclare

* feat(gatsby-remark-prismjs): fix eslint no-redeclare

* Revert "Merge branch 'topics/20642-remark-prismjs-plugin' of https://github.com/rbelow/gatsby into topics/20642-remark-prismjs-plugin"

This reverts commit eaf1691, reversing
changes made to a6b52bb.
  • Loading branch information
rbelow committed Mar 2, 2020
1 parent 47b05fc commit 5b523bd
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/gatsby-remark-prismjs/.gitignore
@@ -1 +1,2 @@
/*.js
/plugins
@@ -0,0 +1,11 @@
const loadPrismShowInvisibles = require(`../../plugins/prism-show-invisibles`)

describe(`prism-show-invisibles`, () => {
test(`should export a function`, () => {
expect(typeof loadPrismShowInvisibles).toBe(`function`)
})

test(`should not return`, () => {
expect(loadPrismShowInvisibles()).toBeUndefined()
})
})
7 changes: 7 additions & 0 deletions packages/gatsby-remark-prismjs/src/index.js
Expand Up @@ -4,6 +4,7 @@ const loadLanguageExtension = require(`./load-prism-language-extension`)
const highlightCode = require(`./highlight-code`)
const addLineNumbers = require(`./add-line-numbers`)
const commandLine = require(`./command-line`)
const loadPrismShowInvisibles = require(`./plugins/prism-show-invisibles`)

module.exports = (
{ markdownAST },
Expand All @@ -13,6 +14,7 @@ module.exports = (
aliases = {},
noInlineHighlight = false,
showLineNumbers: showLineNumbersGlobal = false,
showInvisibles = false,
languageExtensions = [],
prompt = {
user: `root`,
Expand Down Expand Up @@ -61,6 +63,7 @@ module.exports = (
// 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}`

Expand All @@ -73,6 +76,10 @@ module.exports = (
numLinesNumber = addLineNumbers(node.value)
}

if (showInvisibles) {
loadPrismShowInvisibles(languageName)
}

// Replace the node with the markup we need to make
// 100% width highlighted code lines work
node.type = `html`
Expand Down
110 changes: 110 additions & 0 deletions packages/gatsby-remark-prismjs/src/plugins/prism-show-invisibles.js
@@ -0,0 +1,110 @@
const Prism = require(`prismjs`)

const env = {
grammar: undefined,
}

function loadEnv(language) {
env.grammar = Prism.languages[language]
if (!env.grammar) return
}

module.exports = (language = `javascript`) => {
loadEnv(language)

// Gatsby Prism Show Invisibles Plugin
//
// This file serves as an adapter module
// for the original Prism Show Invisibles
// implementation. The ported plugin code
// is from npm's prismjs@1.17.1.
//
// @see https://github.com/PrismJS/prism/blob/v1.17.1/plugins/show-invisibles/prism-show-invisibles.js
//
// prism-show-invisibles.js:start
if (
(typeof self !== `undefined` && !self.Prism) ||
(typeof global !== `undefined` && !global.Prism)
) {
return
}

var invisibles = {
tab: /\t/,
crlf: /\r\n/,
lf: /\n/,
cr: /\r/,
space: / /,
}

/**
* Handles the recursive calling of `addInvisibles` for one token.
*
* @param {Object|Array} tokens The grammar or array which contains the token.
* @param {string|number} name The name or index of the token in `tokens`.
*/
function handleToken(tokens, name) {
var value = tokens[name]

var type = Prism.util.type(value)
switch (type) {
case `RegExp`:
var inside = {}
tokens[name] = {
pattern: value,
inside: inside,
}
addInvisibles(inside)
break

case `Array`:
for (var i = 0, l = value.length; i < l; i++) {
handleToken(value, i)
}
break

default:
// 'Object'
var inside = value.inside || (value.inside = {}) // eslint-disable-line no-redeclare
addInvisibles(inside)
break
}
}

/**
* Recursively adds patterns to match invisible characters to the given grammar (if not added already).
*
* @param {Object} grammar
*/
function addInvisibles(grammar) {
if (!grammar || grammar[`tab`]) {
return
}

// assign invisibles here to "mark" the grammar in case of self references
for (var name in invisibles) {
if (invisibles.hasOwnProperty(name)) {
grammar[name] = invisibles[name]
}
}

/* eslint-disable no-redeclare */
for (var name in grammar) {
/* eslint-enable no-redeclare */
if (grammar.hasOwnProperty(name) && !invisibles[name]) {
if (name === `rest`) {
addInvisibles(grammar[`rest`])
} else {
handleToken(grammar, name)
}
}
}
}

Prism.hooks.add(`before-highlight`, function(env) {
addInvisibles(env.grammar)
})
// prism-show-invisibles.js:end

addInvisibles(env.grammar)
}

0 comments on commit 5b523bd

Please sign in to comment.