コンテンツへスキップ

shikiphp

shikiphpはShikiの純粋なPHP移植版です。ShikiはVS Codeと同じTextMate文法とテーマでコードを色付けする構文ハイライターです。同じTextMate文法でコードをトークン化し、Shikiと同じVS Codeテーマで色付けすることで、Shiki 3.23.0と同じHTMLを生成します。すべてPHPで動作します。

Nodeランタイムは不要です。jsonとmbstring以外のPHP拡張機能も不要です。ネイティブOnigurumaバインディングも、JavaScriptプロセスの起動やホスト型APIの利用も必要ありません。

PHP
use Shikiphp\Shikiphp;

echo Shikiphp::codeToHtml(<<<'PHP'
<?php
function greet(string $name): string {
    return "Hello, {$name}!";
}
PHP, [
    'lang'  => 'php',
    'theme' => 'github-dark',
]);

shikiphpを選ぶ理由

PHPでサーバー側構文ハイライトを行うには、通常3つの妥協が必要です。Nodeを起動する、ホスト型のAPIを呼び出す、または言語を実際には理解しない正規表現ベースのハイライターで済ませることです。いずれもLaravel、WordPress、静的サイトのビルド工程にはうまく適合しません。

shikiphpはShikiの実際の処理パイプラインをPHPに移植することで、こうした妥協をなくします。

  • TextMate文法トークナイザー(忠実な移植版はvscode-textmate)。埋め込み言語、インジェクション、ネストしたリポジトリにも対応
  • スコープセレクターの詳細度と親スコープの照合に対応したVS Codeテーマ解決
  • Shiki互換のHTML:CSS変数によるライト/ダーク両テーマ、codeToHast、トランスフォーマー(すべてのフック)、装飾、colorReplacements、structure: 'inline'、ANSI(lang: 'ansi')ハイライト
  • Shikiの全バンドル — tm-grammars言語すべて(235と、それらに埋め込まれた補助文法18種)、およびtm-themesテーマすべて(65種)

Shiki 3.23.0との照合

出力は「十分近い」ものではなく、固定したShikiのリリースと照合されています。

パッケージ バージョン 用途
shiki 3.23.0 JavaScript正規表現エンジンで実行する正解の基準
tm-grammars 1.31.15 同梱文法
tm-themes 1.12.2 同梱テーマ
@shikijs/transformers 4.2.0 トランスフォーマーの同等性テスト

Shiki自体を正解の基準としています。回帰テストハーネスには214のシナリオがあり、それぞれ既定オプションを使い、1つの言語とテーマで1つのサンプルを扱います。各シナリオをShikiとshikiphpでハイライトし、先頭と末尾の空白を取り除いた後の2つのHTML文字列が完全に一致することを確認します。シナリオ全体で、同梱されている253個の文法のうち167個、lang: 'ansi'、65個すべてのテーマをカバーします。オプション(structure、tabindex、colorReplacements、デュアルテーマ、defaultColorなど)、codeToTokensWithThemes、組み込みトランスフォーマーは個別の同等性テストで確認します。期待される出力は、同じバージョンのShikiから取得しています。

これに伴い、2つの制約があります。Shikiの既定エンジンはWebAssemblyにコンパイルされたOnigurumaですが、正解の基準には代わりにShikiのJavaScript正規表現エンジンを使っています。これはshikiphpが移植しているエンジンです。また、後発のShiki(4.x系)は検証されていません。

仕組み

shikiphpは、inline0/phasisの純粋PHPJavaScript正規表現エンジンを同梱し、oniguruma-to-esのPHP移植版を入力として使います。ShikiのJavaScript正規表現エンジンは、TextMate文法のOnigurumaパターンをJavaScriptRegExpに変換します。そのため、JS正規表現エンジンが自然な基盤となり、shikiphpはそのエンジンの出力とオフセット単位で一致できます。

コード
code → grammar tokenizer → theme resolver → themed tokens → HTML
              │
              └─ OnigScanner → PatternConverter (oniguruma-to-es) → Shikiphp\Regex (JS RegExp engine)

パイプライン全体についてはアーキテクチャを参照してください。

必要条件

  • PHP 8.2以降(CIではPHP 8.4でテストスイートを実行)
  • ext-jsonとext-mbstring(ほぼすべてのPHPビルドに同梱)

次に読むページ

  • はじめに — インストールして最初のブロックを描画します。
  • API — メソッドの全容。
  • オプション — codeToHtmlで使えるすべてのオプション。
  • トランスフォーマー — フックのパイプラインと組み込み機能。
  • CLI — bin/shikiphp highlight、langs、themes。

ライセンス

MIT、著作権はinline0。TextMate文法とテーマは、各上流プロジェクトのライセンスに従います。