Gå til indhold

shikiphp

shikiphp er en ren-PHP-portering af Shiki, syntaksfremhævningsværktøjet, der farvelægger kode med de samme TextMate-grammatikker og temaer som VS Code. Det opdeler kode i tokens med de samme TextMate-grammatikker og farvelægger den med de samme VS Code-temaer, som Shiki bruger, og producerer dermed samme HTML som Shiki 3.23.0 — udelukkende i PHP.

Ingen Node-runtime. Ingen PHP-udvidelser ud over json og mbstring. Ingen indbygget Oniguruma-binding. Ingen start af en separat JavaScript-proces og ingen hostet API.

PHP
use Shikiphp\Shikiphp;

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

Hvorfor shikiphp

Syntaksfremhævning på serversiden i PHP indebærer normalt et af tre kompromiser: at starte Node, kalde en hostet API eller nøjes med et regexbaseret fremhævningsværktøj, der ikke reelt forstår sproget. Ingen af delene passer godt ind i et Laravel-, WordPress- eller statisk webstedsbyggetrin.

shikiphp fjerner kompromiset ved at portere Shikis rigtige pipeline til PHP:

  • en TextMate-grammatiktokenizer (en trofast portering af vscode-textmate), inklusive indlejrede sprog, injektioner og indlejrede repositories
  • VS Code-temaopløsning med specificitet for scopevælgere og matchning af overordnede scopes
  • Shiki-kompatibelt HTML: lyse/mørke dobbelte temaer via CSS-variabler, codeToHast, transformers (alle hooks), dekorationer, colorReplacements, structure: 'inline' og ANSI-fremhævning (lang: 'ansi')
  • den fulde Shiki-pakke — hvert tm-grammars-sprog (235 plus 18 hjælpegrammatikker, som de indlejrer) og hvert tm-themes-tema (65)

Sammenlignet med Shiki 3.23.0

Outputtet er ikke "godt nok": det kontrolleres mod en fastlåst Shiki-udgivelse.

Pakke Version Anvendelse
shiki 3.23.0 facit, kørt med dens JavaScript-regexmotor
tm-grammars 1.31.15 de inkluderede grammatikker
tm-themes 1.12.2 de inkluderede temaer
@shikijs/transformers 4.2.0 tests af transformer-paritet

Shiki er selv facit. Regressionstestsamlingen indeholder 214 scenarier, hvor hvert scenarie er en prøve i ét sprog og ét tema med standardindstillinger. Hvert scenarie fremhæves af Shiki og shikiphp, og de to HTML-strenge skal være identiske, når indledende og afsluttende mellemrum er fjernet. Tilsammen dækker scenarierne 167 af de 253 inkluderede grammatikker, lang: 'ansi' og alle 65 temaer. Indstillingerne (structure, tabindex, colorReplacements, dobbelte temaer, defaultColor og resten), codeToTokensWithThemes og de indbyggede transformers dækkes af separate paritetstests, hvis forventede output blev registreret fra de samme Shiki-versioner.

Det medfører to begrænsninger. Standardmotoren i Shiki er Oniguruma kompileret til WebAssembly, mens facit bruger Shikis JavaScript-regexmotor, som er den motor, shikiphp porter. Senere Shiki-udgivelser (4.x-serien) er ikke blevet kontrolleret.

Sådan fungerer det

shikiphp er bygget på en indlejret, ren-PHP JavaScript-regexmotor fra inline0/phasis, baseret på en portering af PHP af oniguruma-to-es. Shikis JavaScript-regexmotor omdanner Oniguruma-mønstrene i TextMate-grammatikker til JavaScript RegExp, så en JS-regexmotor er et naturligt grundlag — den lader shikiphp matche motorens output præcist, forskydning for forskydning.

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

Se Arkitektur for hele pipelinen.

Krav

  • PHP 8.2 eller nyere (CI kører testpakken på PHP 8.4)
  • ext-json og ext-mbstring (begge følger med stort set alle PHP-versioner)

Hvad nu?

  • Kom godt i gang — installer, og gengiv din første blok.
  • API — hele metodeoversigten.
  • Indstillinger — alle indstillinger, som codeToHtml accepterer.
  • Transformers — hook-pipelinen og de indbyggede transformers.
  • CLI — bin/shikiphp highlight, langs og themes.

Licens

MIT, copyright inline0. Inkluderede TextMate-grammatikker og temaer beholder deres oprindelige licenser.