以下の内容はhttps://ytyaru.hatenablog.com/entry/2025/01/09/000000より取得しました。


構文強調ライブラリの調査

 知らない子も生まれたようですが、いつもの奴に行き着きました。

構文強調

 構文強調とは、以下のようにプログラミング言語のキーワードを装飾することです。

<p>HTML</p>
css { color:red; }
console.log('Hello JavaScript !!');

 カラフルで見やすいですね。これは複雑なHTMLとCSSで実装されています。でも、それを手作業で書くのは大変です。そこで自動化するライブラリが欲しくなります。

 構文強調ライブラリシンタックス・ハイライターとは、構文強調に必要なHTMLとCSSのコードを自動生成してくれるJavaScriptライブラリです。

既存ライブラリ

ライブラリ 概要
highlight.js 昔からある使いやすいライブラリ。テーマも豊富。
shiki 新しいライブラリで高機能。でも私の要件に合わず。
CSS Custom Highlight API 新しい標準API。でも私の環境に未実装。

 他にも色々なライブラリがありますが、有名なものは上記です。今も更新されており、高機能で使いやすい等の理由でしょう。

CSS Custom Highlight API

 CSS Custom Highlight APIは標準APIです。外部ライブラリをインストールする必要がありません。ぜひとも使いたかったのですが、私の環境では未実装でした。

 Chrome 105以降で使えるそうですが、私の環境は92と古すぎました。残念。

 更新作業が大変すぎるので避けています。私のマシンはラズパイです。ブラウザの更新にはOSの更新が必要です。ダウンロード、SDカード焼き、ブート設定ファイル作成、クリーンインストール、データコピー、アプリのインストール等の工程が必要で、数日がかりの大作業となり、憂鬱すぎて避けること早数年。だれか代わりにやってください。以下にそのあたりの膨大な情報を記録してあります。

 本題から遠ざかること山の如し。やってられません。

shiki

 shikiは現状で最高の構文強調ライブラリです。

  • 高パフォーマンス
    • 分割インポートできる
    • wasmで実装されている
  • 高機能
    • ダークモードに対応している
    • TypeScriptの型情報からコード注釈をポップアップできる

 ただ、私の要件には合いませんでした。

  • オフラインでも実行できる
  • Node.js, TypeScriptが不要である

 Node.js, TypeScriptをインストールしてビルドすれば、オフラインでも実行できるコードを生成できるでしょう。ただし、私はその環境を使いたくありません。

 ブラウザだけで開発したかったのです。shikiのJSとCSSを全部ダウンロードし、<script><link>タグをローカルのHTMLに書くだけで動作するように実装したかったのです。これができませんでした。

 CDNなら動作しました。しかしオフラインでは使えません。リンク先を辿りコードを追いましたが、内部で大量のimport文があり、それらをすべて手動でダウンロードしてローカルに再配置するのは無謀だと諦めました。

highlight.js

 highlight.jsは昔からある構文強調ライブラリです。業界で最も有名かつ情報も多く、今尚、更新が続けられていたので安心して利用できそうです。

 APIは旧版から多少変化しているようですが、API Referenceを見れば判るでしょう。あるいは古いですが日本語情報も豊富です。

 ただ、私の要件的に、次のような問題があります。

  1. 分割インポートできない
  2. ダークモードに対応していない
  3. 行数表示がない
  4. コピーボタンがない
  5. ダウンロードボタンがない
  6. JsDocによるコード注釈ポップアップ表示できない

 実際には1さえ解決できれば、あとはプラグインを実装することで実現可能だと思われます。尤も、16はすべて自分で実装することになるでしょうが。(shikiであれば2までは裸の状態で使えるのになぁ)

 他者が開発したプラグインもあるようです。しかし細かい所で不満が出そうなので、自分でイチから作ることになりそうな気がします。

1. 分割インポートできない

 これを説明すると少々長くなります。

 構文強調は多数のプログラミング言語に対応していますが、それぞれの言語用に異なるライブラリをインポートする必要があります。そのせいで読込に時間がかかり応答速度が遅くなってユーザ体験が悪くなってしまいます。

 応答速度の低下を回避するには、分割インポートが有効です。つまり構文強調したい言語のライブラリだけをインポートすれば、応答速度の低下を最小限に抑えられます。

 構文強調したい言語のライブラリだけをインポートする。それは当たり前のことです。でも、事前にどの言語を強調したいか判らない場合もあります。たとえばブログを書くツール等です。ユーザに自由な入力を許すため、事前にどの言語を強調したいか判りません。

 事前にどの言語を強調したいか判らない場合、それが判明した時点で、判明した言語のライブラリだけを動的インポートしたいのです。たとえば言語名を文字列の変数で渡せば動的インポートしてくれるようなAPIが欲しいです。

 実際には存在しませんが、以下hljs.loadLanguage(...langNames)のようなAPIが欲しかったのです。

hljs.loadLanguage('html', 'css', 'js'); // 任意の言語名
hljs.highlightAll(); // 構文強調する

1-1. EMS版コードならimportできる

 highlight.jsをダウンロードして展開した中に、esディレクトリがあります。その中にあるコード一式を使います。これはES Moduleと呼ばれる比較的新しい標準APIを用いて実装されたコードです。

 次のようにすると、js,json,yaml,markdownの言語ライブラリを動的インポートします。

import hljs from 'highlight.js/lib/core';
import js from 'highlight.js/lib/languages/javascript';
import json from 'highlight.js/lib/languages/json';
import yml from 'highlight.js/lib/languages/yaml';
import md from 'highlight.js/lib/languages/markdown';

hljs.registerLanguage('javascript', js);
hljs.registerLanguage('json', json);
hljs.registerLanguage('yaml', yml);
hljs.registerLanguage('markdown', md);

 ただ、この場合、次のような問題があります。

  • EMS版コードはES6(ES2015)以前の環境では動作しない
  • hljs.registerLanguage()だけでなくimport文も必要だが、それを文字列変数で渡せない(文書の先頭に書く必要有)
  • 動的import APIがあるが、ES6(ES2015)以前の環境では動作しない

 GitHubIssueにも私が挙げた問題の一部がやり玉に挙がっていますが、モチベーションは低いようです。それは理解できます。費用対効果は薄いでしょうから。新しい環境なら動的import APIを使えばいいだけですし、わざわざ古い環境に対応するのも面倒な上に、ファイルサイズが無駄に肥大化します。未来を見据えると全員が不幸になるでしょう。

1-2. EMSを使いたくない(ES5以前でも使用できるよう実装したい)

 昔から使える<script><link>でJSとCSSを参照する方法です。これなら環境を選ばず、どこでも動作します。ビルド環境を用意する必要もありません。ブラウザとテキストエディタだけで開発できます。

 さしずめNo-Module版とでも仮名しておきます。

 index.htmlファイルに以下を追記することで外部にあるJSやCSSのファイルを参照します。

<link rel="stylesheet" href="参照したいCSSファイルのURLやパス">
<script src="参照したいJSファイルのURLやパス">

 ここで本題です。参照するファイルを動的に決定したいです。構文強調したい言語毎に参照したいJSファイルが違います。また、使用したいテーマ毎に参照したいCSSファイルが違います。これをユーザが自由に選んで、必要なファイルだけを動的に参照したいのです。

 残念ながら、それを実行する直接的なAPIはありませんでした。先述の通り、ESMを使用したインポートは対応していますが、それだと後方互換に問題があります。

 後方互換の問題を解決するには、古いコードで動作する動的インポートを実装する方法があります。さしずめscriptタグ挿入式動的インポートとでも仮名しましょう。これを自分で実装すれば、私の求める古い環境における動的インポートが実現できるでしょう。

 とりあえず技術的に可能であるかを軽く調べると、以下のような記事がありました。

 たぶん実現可能でしょう。今更欲しがる人は居ないかもしれません。ES6(ES2015)以降なら動的import APIが使えますからね。でも私は欲しいのです。誰もやらないだろうから、私が作るしかないでしょう。時代に取り残されたガラパゴス化石人間の末路……。

所感

 調査だけで大変だった。

 使用ライブラリはhighlight.jsに決まるも、不足が6つもあり、そのうちの1つ目の調査だけでもう大変。

 やりたいことを実現するまでが遠すぎる。コツコツやるしかないが、途中で挫折するのが目に浮かぶようだ。

 とりあえず最初はscriptタグ挿入式動的インポートの汎用ライブラリだけでも仮作成してみるか。

対象環境

$ uname -a
Linux raspberrypi 5.10.103-v8+ #1529 SMP PREEMPT Tue Mar 8 12:26:46 GMT 2022 aarch64 GNU/Linux



以上の内容はhttps://ytyaru.hatenablog.com/entry/2025/01/09/000000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14