monaco editor の機能でコードに色付けする
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ 色付け機能だけをロードするのは難しそうなのでエディタ全体をロード
◆ 機能としてはとてもいいんだけど 重いのが欠点
◆ 機能としてはとてもいいんだけど 重いのが欠点
ソースコードでキーワードなどに色を付けてくれるライブラリに highlight.js や prism.js があります
このブログでは今のところ highlight.js を使っています
highlight.js で基本的には悪くはないのですが ところどころ正しく色がつけられていないところがあります
途中で構文エラーとみなされたのか 途中までしか色がついてなかったりです
普段使ってる VSCode だと色付けで問題を感じたことはほぼないので VSCode で使われてる monaco-editor を試してみることにしました
monaco-editor のソースコードは monaco-editor のリポジトリにありますが ここは言語ごとのパースに必要な情報を管理しているリポジトリです
https://github.com/microsoft/monaco-editor
色付けだったり エディタとしての機能は monaco-editor-core というパッケージで VSCode のリポジトリ内にあります
https://github.com/microsoft/vscode/tree/main/src/vs/editor
vs/editor の中が monaco-editor-core になります
色付け機能のモジュールはこれです
https://github.com/microsoft/vscode/blob/main/src/vs/editor/standalone/browser/colorizer.ts
この Colorizer.colorize 関数を直接使えたら良かったのですが 引数に要求される languageService はエディタ機能の内部的なもので 対応している言語等を管理しているオブジェクトです
このモジュールだけを使う方法では この引数を渡すのは難しそうだったのでエディタ全体をロードすることにしました
こんな感じで エディタ全体をロードしてもコードは短く書けます
ページ全体としての例はこんな感じです
HTML 内の script タグや style タグ内も正しく色付けされています
色だけではなくタブサイズ調整も含まれるので ロード後に色や文字位置が少し変わります
気になるなら CSS で色付け後に表示するようにもできます
色付け完了後に対象の要素にテーマ名のクラスが追加されるのでこういう感じです
テーマを標準以外のものにしたい場合は 第二引数のオプションで指定できます
色付け後に setTheme 関数を呼び出して変更もできます
または
後から setTheme をする場合は要素に追加されたクラス名は変更されません
colorizeElement 関数で色が変わるのはコードの文字部分のみです
背景色は設定されないので ダークテーマにする場合の背景色は自分で設定が必要です
ダークテーマを使った例です
テーマはビルトインテーマの vs, vs-dark, hc-black が使えます
それ以外にも defineTheme 関数を使って自作も可能です
ビルトインテーマの設定はここにあるので これを参考に少し色を変えるだけという使い方もできます
https://github.com/microsoft/vscode/blob/main/src/vs/editor/standalone/common/themes.ts
monaco-editor は VSCode で使われてるだけあって highlight.js よりも高機能ですが その分ロードが遅いのが欠点です
色付けだけでエディタとしての機能は使わないのにエディタ全体をロードするので仕方ないのですけど
サイズは minify + br でも 500KB を超えています
このブログの highlight.js を置き換えるかは迷うところです
このブログでは今のところ highlight.js を使っています
highlight.js で基本的には悪くはないのですが ところどころ正しく色がつけられていないところがあります
途中で構文エラーとみなされたのか 途中までしか色がついてなかったりです
普段使ってる VSCode だと色付けで問題を感じたことはほぼないので VSCode で使われてる monaco-editor を試してみることにしました
monaco-editor のソースコードは monaco-editor のリポジトリにありますが ここは言語ごとのパースに必要な情報を管理しているリポジトリです
https://github.com/microsoft/monaco-editor
色付けだったり エディタとしての機能は monaco-editor-core というパッケージで VSCode のリポジトリ内にあります
https://github.com/microsoft/vscode/tree/main/src/vs/editor
vs/editor の中が monaco-editor-core になります
色付け機能のモジュールはこれです
https://github.com/microsoft/vscode/blob/main/src/vs/editor/standalone/browser/colorizer.ts
この Colorizer.colorize 関数を直接使えたら良かったのですが 引数に要求される languageService はエディタ機能の内部的なもので 対応している言語等を管理しているオブジェクトです
このモジュールだけを使う方法では この引数を渡すのは難しそうだったのでエディタ全体をロードすることにしました
こんな感じで エディタ全体をロードしてもコードは短く書けます
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs/loader.min.js"></script>
<script>
require.config({ paths: { "vs": "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs" } })
require(["vs/editor/editor.main"], () => {
monaco.editor.colorizeElement(element)
})
</script>
ページ全体としての例はこんな感じです
<!doctype html>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs/loader.min.js"></script>
<script>
require.config({ paths: { "vs": "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs" } })
require(["vs/editor/editor.main"], () => {
monaco.editor.colorizeElement(document.querySelector("code[data-lang]"))
})
</script>
<style>
pre {
border: 1px solid #888;
padding: 10px;
}
</style>
<pre><code data-lang="html"><script>
function f(a) {
const b = a + 1
for (let x = 0; x < 10; x++) {
continue
}
const c = html`
<div class="a">123</div>
`
return null
}
</script>
<style>
h1 {
color: red;
}
</style>
</div class="a b c">
<span>xyz<span>
</div></code></pre>
HTML 内の script タグや style タグ内も正しく色付けされています
色だけではなくタブサイズ調整も含まれるので ロード後に色や文字位置が少し変わります
気になるなら CSS で色付け後に表示するようにもできます
色付け完了後に対象の要素にテーマ名のクラスが追加されるのでこういう感じです
pre code {
opacity: 0;
transition: opacity .5s ease 0s;
}
pre code.vs {
opacity: 1;
}
テーマを標準以外のものにしたい場合は 第二引数のオプションで指定できます
色付け後に setTheme 関数を呼び出して変更もできます
monaco.editor.colorizeElement(element, { theme: "vs-dark" })
または
monaco.editor.colorizeElement(element)
monaco.editor.setTheme("vs-dark")
後から setTheme をする場合は要素に追加されたクラス名は変更されません
colorizeElement 関数で色が変わるのはコードの文字部分のみです
背景色は設定されないので ダークテーマにする場合の背景色は自分で設定が必要です
ダークテーマを使った例です
<!doctype html>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs/loader.min.js"></script>
<script>
require.config({ paths: { "vs": "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.32.1/min/vs" } })
require(["vs/editor/editor.main"], () => {
monaco.editor.colorizeElement(document.querySelector("code[data-lang]"), { theme: "vs-dark" })
})
</script>
<style>
pre {
border: 1px solid #888;
background: #1E1E1E;
padding: 10px;
}
pre code {
opacity: 0;
transition: opacity .5s ease 0s;
}
pre code.vs-dark {
opacity: 1;
}
</style>
<pre><code data-lang="html"><script>
function f(a) {
const b = a + 1
for (let x = 0; x < 10; x++) {
continue
}
const c = html`
<div class="a">123</div>
`
return null
}
</script>
<style>
h1 {
color: red;
}
</style>
</div class="a b c">
<span>xyz<span>
</div></code></pre>
テーマはビルトインテーマの vs, vs-dark, hc-black が使えます
それ以外にも defineTheme 関数を使って自作も可能です
ビルトインテーマの設定はここにあるので これを参考に少し色を変えるだけという使い方もできます
https://github.com/microsoft/vscode/blob/main/src/vs/editor/standalone/common/themes.ts
monaco-editor は VSCode で使われてるだけあって highlight.js よりも高機能ですが その分ロードが遅いのが欠点です
色付けだけでエディタとしての機能は使わないのにエディタ全体をロードするので仕方ないのですけど
サイズは minify + br でも 500KB を超えています
このブログの highlight.js を置き換えるかは迷うところです