Skip to content

Instantly share code, notes, and snippets.

@u1f992
Created April 25, 2024 13:47
Show Gist options
  • Save u1f992/0ba609e779585f15cc94c9f37c7b72f9 to your computer and use it in GitHub Desktop.
Save u1f992/0ba609e779585f15cc94c9f37c7b72f9 to your computer and use it in GitHub Desktop.
import fs from "node:fs";
import vm from "node:vm";
import jsdom from "jsdom";
type PrismContext = vm.Context & { PrismContext: never };
type PrismPlugin = "autolinker"
| "autoloader"
| "command-line"
| "copy-to-clipboard"
| "custom-class"
| "data-uri-highlight"
| "diff-highlight"
| "download-button"
| "file-highlight"
| "filter-highlight-all"
| "highlight-keywords"
| "inline-color"
| "jsonp-highlight"
| "keep-markup"
| "line-highlight"
| "line-numbers"
| "match-braces"
| "normalize-whitespace"
| "previewers"
| "remove-initial-line-feed"
| "show-invisibles"
| "show-language"
| "toolbar"
| "treeview"
| "unescaped-markup"
| "wpd";
function createContext() {
const path = require.resolve("prismjs");
const src = fs.readFileSync(path, { encoding: "utf-8" });
const dom = new jsdom.JSDOM("", { runScripts: "dangerously" });
const ctx = dom.getInternalVMContext();
vm.runInContext(src, ctx);
return ctx as PrismContext;
}
function loadPlugin(ctx: PrismContext, plugin: PrismPlugin) {
const path = require.resolve(`prismjs/plugins/${plugin}/prism-${plugin}.js`);
const src = fs.readFileSync(path, { encoding: "utf-8" });
vm.runInContext(src, ctx);
}
function highlight(
code: string,
lang: string,
plugin: {
diffHighlight?: boolean,
lineHighlight?: string,
lineNumbers?: boolean
} = {}
) {
const ctx = createContext();
const attr: { [key: string]: unknown } = {
"class": `language-${lang}`
};
if (plugin.diffHighlight) {
loadPlugin(ctx, "diff-highlight");
attr["class"] += " diff-highlight";
}
if (plugin.lineHighlight !== undefined) {
loadPlugin(ctx, "line-highlight");
attr["data-line"] = plugin.lineHighlight;
}
if (plugin.lineNumbers) {
loadPlugin(ctx, "line-numbers");
attr["class"] += " line-numbers";
}
ctx["code"] = code;
ctx["attr"] = attr;
return vm.runInContext(`
{
let ret = "";
const pre = document.createElement("pre");
try {
const code_ = document.createElement("code");
try {
pre.appendChild(code_);
code_.textContent = code;
for (const key of Object.keys(attr)) {
pre.setAttribute(key, attr[key]);
}
Prism.highlightElement(code_);
ret = pre.outerHTML;
} finally {
code_.remove();
}
} finally {
pre.remove();
}
ret;
}
`, ctx);
}
const code = `function hello() {
console.log("hello");
}
hello();`;
console.log(highlight(code, "js"));
console.log("----------------------");
console.log(highlight(code, "javascript", {
lineNumbers: true,
lineHighlight: "2-3"
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment