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;
};