Skip to content

shikiphp

shikiphp is a pure-PHP port of Shiki, the syntax highlighter that colors code with the same TextMate grammars and themes as VS Code. It tokenizes code with the same TextMate grammars and paints it with the same VS Code themes Shiki uses, producing the same HTML as Shiki 3.23.0 — entirely in PHP.

No Node runtime. No PHP extensions beyond json and mbstring. No native Oniguruma binding. No shelling out to a JavaScript process, and no hosted API.

PHP
use Shikiphp\Shikiphp;

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

Why shikiphp

Server-rendered syntax highlighting in PHP usually means one of three compromises: shelling out to Node, calling a hosted API, or settling for a regex-based highlighter that does not actually understand the language. None of those fit cleanly into a Laravel, WordPress, or static-site build step.

shikiphp removes the compromise by porting Shiki's real pipeline to PHP:

  • a TextMate grammar tokenizer (a faithful port of vscode-textmate), including embedded languages, injections, and nested repositories
  • VS Code theme resolution with scope-selector specificity and parent-scope matching
  • Shiki-compatible HTML: dual light/dark themes via CSS variables, codeToHast, transformers (every hook), decorations, colorReplacements, structure: 'inline', and ANSI (lang: 'ansi') highlighting
  • the full Shiki bundle — every tm-grammars language (235, plus 18 helper grammars they embed) and every tm-themes theme (65)

Matched against Shiki 3.23.0

The output is not "close enough": it is checked against a pinned Shiki release.

Package Version Used for
shiki 3.23.0 the oracle, run with its JavaScript regex engine
tm-grammars 1.31.15 the bundled grammars
tm-themes 1.12.2 the bundled themes
@shikijs/transformers 4.2.0 the transformer parity tests

Shiki itself is the oracle. The regression harness holds 214 scenarios, each one sample in one language and one theme with default options. Every scenario is highlighted by Shiki and by shikiphp, and the two HTML strings must be identical once leading and trailing whitespace is trimmed. Together the scenarios cover 167 of the 253 bundled grammars, lang: 'ansi', and all 65 themes. The options (structure, tabindex, colorReplacements, dual themes, defaultColor and the rest), codeToTokensWithThemes, and the built-in transformers are covered by separate parity tests whose expected output was captured from the same Shiki versions.

Two limits follow from that. Shiki's default engine is Oniguruma compiled to WebAssembly, and the oracle uses Shiki's JavaScript regex engine instead, which is the engine shikiphp ports. And later Shiki releases (the 4.x line) have not been checked.

How it works

shikiphp is built on a vendored pure-PHP JavaScript regex engine from inline0/phasis, fed by a PHP port of oniguruma-to-es. Shiki's JavaScript regex engine converts the Oniguruma patterns in TextMate grammars to JavaScript RegExp, so a JS regex engine is the natural substrate — it lets shikiphp match that engine's output offset-for-offset.

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

See Architecture for the full pipeline.

Requirements

  • PHP 8.2 or later (CI runs the test suite on PHP 8.4)
  • ext-json and ext-mbstring (both ship with virtually every PHP build)

Where to next

  • Getting Started — install and render your first block.
  • API — the full method surface.
  • Options — every option codeToHtml accepts.
  • Transformers — the hook pipeline and the built-ins.
  • CLI — bin/shikiphp highlight, langs, and themes.

License

MIT, copyright inline0. Bundled TextMate grammars and themes retain their upstream licenses.