@shikijs/monaco を使って Monaco Editor で JSX や Vue をお手軽シンタックスハイライト
Markuplint Playground の JSX (React), Vue, Svelte コードにシンタックスハイライトを追加したので、そこで使った @shikijs/monaco
について紹介します。
Shiki とは
Shiki は今年(2024 年)の 2 月に v1 がリリースされたばかりの、比較的新しいシンタックスハイライトライブラリです。
内部では TextMate(VSCode と同じ文法)を使っているのが特徴です。
シンタックスハイライトライブラリとしては Prism (npm)や highlight.js (npm) などが有名ですが、これらのアップデートが停滞気味(Prism の最終更新が 2 年前、highlight.js は 8 ヶ月前(2024 年 5 月現在))なのに対し、Shiki は毎週ペースでアップデートが続いており、期待のライブラリです。
他の方のわかりやすい紹介記事も貼ってきおきます。
Monaco Editor とは
Monaco Editor は、VSCode に使われているコアパッケージです。
このパッケージを使用することで Web 上で VSCode のようなエディタを実装できます。
Monaco Editor でのシンタックスハイライト
Monaco Editor では、 HTML, CSS, JavaScript, JSON あたりの言語にはシンタックスハイライトがデフォルトでサポートされていますが、それ以外の JSX, Vue などの言語はシンタックスハイライトがサポートされていません。
自前で追加するのも結構面倒で、JSX ハイライトのライブラリはあったりしますが JSX 専用なので汎用的ではなかったり、VSCode 用の TextMate ファイルを読み込ませることはできるけどそもそも VSCode 向けに配布されている URL を探す必要があったり、記述量がやや多かったりと、どの方法もいまいちでした。
@shikijs/monaco
そこで出てくるのが @shikijs/monaco
です。
Shiki が提供しているライブラリで、Shiki のシンタックスハイライトを Monaco Editor で使えるようにしてくれます。
ちなみに、「Shiki は VSCode と同じ TextMate を使っている」「Monaco Editor は VSCode のコア」と聞くとはじめから互換がありそうに聞こえますが、実は Monaco Editor のシンタックスハイライトは VSCode とは全く異なる実装になっているらしく [1] 、変換が必要です。
その変換をやってくれるのが @shikijs/monaco
というわけです。
ありがてえ~~。
これを使うとなんともお手軽に Monaco Editor にシンタックスハイライトを追加できます。
実装方法はドキュメントを参照されたし。なんですが、今回のケースでは @monaco-editor/react
を使っているので、その実装を紹介しておきます。
Monaco Editor がマウントされたタイミングで shikiToMonaco
を実行しています。
※以下のサンプルは関係する部分のみ抜き出して適当に省略しているのでイメージ程度に見てください。
import MonacoEditor from "@monaco-editor/react";
import { shikiToMonaco } from "@shikijs/monaco";
import { getHighlighter } from "shiki/bundle/web";
export const Editor = ({
language,
}: {
language: "jsx" | "tsx" | "vue" | "svelte";
}) => (
<MonacoEditor
language={language}
theme="vs-dark"
onMount={(editor, monaco) => {
(async () => {
const highlighter = await getHighlighter({
theme: "dark-plus",
langs: ["jsx", "tsx", "vue", "svelte"],
});
monaco.languages.register({ id: "jsx" });
monaco.languages.register({ id: "tsx" });
monaco.languages.register({ id: "vue" });
monaco.languages.register({ id: "svelte" });
shikiToMonaco(highlighter, monaco);
})();
}}
/>
);
まとめ
@shikijs/monaco
を使うことで、Monaco Editor に JSX, Vue, Svelte などのシンタックスハイライトをお手軽に追加できました。
Shiki には他にも @shikijs/markdown-it
(markdown-it で使えるようにするプラグイン)や @shikijs/twoslash
(TypeScript の拡張コメント記法に対応するプラグイン)などのプラグインが用意されており、拡張性も高く、他のライブラリとの連携もしやすくなっています。
今後の発展にも期待です 🤩
Discussion