const Prism = require('prismjs'); const PrismLoader = require('prismjs/components/index.js'); PrismLoader('diff'); PrismLoader.silent = true; /** Highlights a code string. */ function highlight(code, language) { const alias = language.replace(/^diff-/, ''); const isDiff = /^diff-/i.test(language); // Auto-load the target language if (!Prism.languages[alias]) { PrismLoader(alias); if (!Prism.languages[alias]) { throw new Error(`Unsupported language for code highlighting: "${language}"`); } } // Register diff-* languages to use the diff grammar if (isDiff) { Prism.languages[language] = Prism.languages.diff; } return Prism.highlight(code, Prism.languages[language], language); } /** * Highlights all code fields that have a language parameter. If the language has a colon in its name, the first chunk * will be the language used and additional chunks will be applied as classes to the `
`. For example, a code field
* tagged with "html:preview" will be rendered as ``.
*
* The provided doc should be a document object provided by JSDOM. The same document will be returned with the
* appropriate DOM manipulations.
*/
module.exports = function (doc) {
doc.querySelectorAll('pre > code[class]').forEach(code => {
// Look for class="language-*" and split colons into separate classes
code.classList.forEach(className => {
if (className.startsWith('language-')) {
//
// We use certain suffixes to indicate code previews, expanded states, etc. The class might look something like
// this:
//
// class="language-html:preview:expanded"
//
// The language will always come first, so we need to drop the "language-" prefix and everything after the first
// color to get the highlighter language.
//
const language = className.replace(/^language-/, '').split(':')[0];
try {
code.innerHTML = highlight(code.textContent ?? '', language);
} catch (err) {
// Language not found, skip it
}
}
});
});
return doc;
};