Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9409

DOMやwindowに依存しているPrismのプラグインをNode.js上で動かす方法

$
0
0
Prism.jsのline-numbersプラグインなど、DOMやwindowに依存しているため、Node.jsでrequireしても動作しません。 解決策 ではどうやったら動くか?解決策は次の通りです。 DOMに依存している問題の解決策 DOMに依存しているコードが動くようにするために、jsdomを使います。 グローバルオブジェクトwindowに依存している問題の解決策 line-numbersプラグインなどは、window.Prismがundefinedだとプラグインのロードをやめてしまいます。この解決策としては、vmモジュールを使い、擬似的にグローバルオブジェクトとしてwindowがあるサンドボックス環境を作り、その中で、プラグインコードをevalしてやるようにします。 上の解決策を講じたコード 次が上の解決策を施したコードです。 loadPlugin.ts import fs from "fs"; import { JSDOM } from "jsdom"; import Prism from "prismjs"; import vm from "vm"; export function createLoadPlugin() { const { window } = new JSDOM(""); window.Prism = Prism; const ctx = vm.createContext(window); return function load(plugin: string): void { const filename = require.resolve( `prismjs/plugins/${plugin}/prism-${plugin}` ); const src = fs.readFileSync(filename, "utf-8"); vm.runInContext( // language=JavaScript ` try { const self = window; ${src}; } catch (err) { console.error(err); } `, ctx ); }; } 使い方は次の通り。 usage.ts import { createLoadPlugin } from "./loadPlugin"; const loadPlugin = createLoadPlugin(); loadPlugin("line-numbers"); loadPlugin("diff-highlight"); loadPlugin("autolinker"); loadPlugin("inline-color"); これで様々なプラグインがロードできるようになります。 ハイライトはPrism.highlightElementを用いる Node.jsでハイライトするにはPrism.highlightを用いるのが一般的ですが、DOM依存のプラグインはそのメソッドでは動かないので、Prism.highlightElementを使います。 実際にhighlightElementを使う場合は、DOMが必要なので次のようなユーティリティ関数を作っておくとよいです。 highlight.ts import { JSDOM } from "jsdom"; import Prism from "prismjs"; export function highlight( code: string, { language = "none", lineNumbers = false, }: { language?: string; lineNumbers?: boolean } = {} ): string { const { window } = new JSDOM(""); const pre = window.document.createElement("pre"); const codeElm = window.document.createElement("code"); pre.appendChild(codeElm); codeElm.textContent = code; codeElm.setAttribute( "class", [`language-${language}`] .concat(lineNumbers ? ["line-numbers"] : []) .join(" ") ); Prism.highlightElement(codeElm); return pre.outerHTML; } 最終的なコード 上で作った、loadPluginとhighlightを使った最終的なコードです。 main.ts import loadLanguages from "prismjs/components/index"; import { highlight } from "./highlight"; import { createLoadPlugin } from "./loadPlugin"; loadLanguages(); const loadPlugin = createLoadPlugin(); loadPlugin("line-numbers"); loadPlugin("diff-highlight"); loadPlugin("autolinker"); loadPlugin("inline-color"); const code = `span.foo { background-color: navy; color: #BFD; }`; const html = highlight(code, { language: "css", lineNumbers: true }); console.log(html); 上のhtml内容は次のようになります。 See the Pen Prism line-numbers inline-colors by suin (@suin) on CodePen.

Viewing all articles
Browse latest Browse all 9409

Trending Articles