Arkitektur
shikiphp omdanner kildekode til fremhævet HTML med tema ved hjælp af TextMate-grammatikker og VS Code-temaer uden PHP-udvidelser ud over json/mbstring, uden Node-runtime og uden native Oniguruma-binding. Denne side opsummerer pipelineforløbet; den fulde normative specifikation findes i ARCHITECTURE.md i repositoryet.
Pipelineforløbet
source code
└─ Highlighter::codeToTokens()
├─ Grammar\Registry loads the grammar (+ its includes / embedded langs)
├─ Grammar\Tokenizer line by line, driving an OnigScanner per rule state
│ └─ Oniguruma\OnigScanner.findNextMatch()
│ └─ Oniguruma\PatternConverter Oniguruma pattern → JS regex
│ └─ Shikiphp\Regex (Parser + Matcher) JS RegExp runtime
├─ Theme\Theme.match(scopeStack) → StyleAttributes per token
└─ Render\ThemedToken[] (text + style) per line
└─ Render\HtmlRenderer → <pre class="shiki">…</pre>
Alt arbejder med offset i UTF-16-kodeenheder — samme område som regexmotoren JS og tokenizeren i Shiki. For ASCII svarer det til byteoffset.
Regex-runtime
Nederst ligger Shikiphp\Regex, en komplet ECMAScript-regexmotor skrevet udelukkende i PHP, medtaget fra inline0/phasis (en PHP-motor skrevet udelukkende i JavaScript). Den fortolker en JS-RegExp-kilde med flag og udfører fremadrettede søgninger med semantik for Oniguruma onig_search.
Konvertering fra Oniguruma til JS
TextMate-grammatikker er skrevet i Oniguruma. Shikiphp\Oniguruma\PatternConverter
er en PHP-port af
oniguruma-to-es: den konverterer et
Oniguruma-mønster til en JS-RegExp-kompatibel kilde og flagstreng, som regex-
motoren accepterer. Det er den samme sti fra Oniguruma til RegExp, som Shikis JavaScript-
regexmotor bruger, hvilket lader shikiphp matche motorens output
offset for offset. Konverteren
håndterer de konstruktioner, grammatikker bruger i praksis: POSIX-klasser, possessive
kvantifikatorer og atomare grupper, inline-flag, navngivne grupper og backreferencer,
Unicode-egenskaber og mere.
Scanneren og dens PCRE-hurtigsti
Shikiphp\Oniguruma\OnigScanner efterligner scanneren i vscode-oniguruma: Den bygges én gang pr. regel ud fra en liste af mønstre og finder det længst venstre match ved eller efter en startposition.
Træmatcherens resultater er korrekte, men den er langsom, så scanneren har en PCRE-hurtigsti med ækvivalenskontrol i to trin. En PcreTranslator omskriver konverterens JS-kilde til et indbygget PCRE-mønster, men kun når resultatet kan bevises:
- Fuldt match. Når oversættelsen opfører sig identisk med matcheren, inklusive alle captures, køres mønsteret direkte i PCRE. Navngivne grupper, backreferencer,
\p{},\b,\G, atomar emulering og captures, hvis JavaScript-semantik afviger fra PCRE (i en kvantificeret gruppe eller et lookbehind), afvises på dette trin. - Kun position. Når kun captures kan afvige, tillader en anden oversættelse disse konstruktioner (
\bog\Bsom præcise ASCII-lookarounds, atomare grupper som indbyggede(?>…),\p{…}hvis PCRE kompilerer det). PCRE finder kun placeringen af det næste match, og matcheren kører igen ved den position for at producere de faktiske captures. Backreferencer og\Gafvises også her.
Alt andet køres udelukkende af matcheren. For de medfølgende grammatikker ved Shiki 3.23.0 køres omkring 39 % af de 14,234 forskellige mønstre fuldt ud i PCRE, omkring 57 % bruger positionstrinnet, og omkring 4 % forbliver hos matcheren. Klassificeringen kontrolleres af et udviklingsværktøj i repositoryet (bin/.oracle-tools/pcre-equivalence.php), som sammenligner hurtigstien med matcheren — indeks, slutning og for første trin hvert capture-interval — for scenarieinput og en række syntetiske strenge, uden tilladte afvigelser.
Grammatik og tema
- Grammatik (
Shikiphp\Grammar) er en trofast portering afvscode-textmate: enRegistryfinder grammatikker ud fra scope-navn (inklusive referencer tilinclude, indlejrede sprog og injectioner), og enTokenizervedligeholder regel- og scope-stakke linje for linje. - Tema (
Shikiphp\Theme) porterer temamatchningen fravscode-textmate: forgrund og skrifttypografi fastlægges ud fra scope-vælgerens specificitet med matchning af overordnede scopes.
Gengivelse
Shikiphp\Render\HtmlRenderer bygger præcis det pre.shiki > code > span.line > span HAST-træ, som Shiki bygger, og serialiserer det derefter. Tilstand med ét tema skriver almindelige farver; tilstand med to temaer skriver --shiki-light / --shiki-dark-variabler for CSS.
Valideret mod Shiki
Shiki er selv facit, fastlåst til shiki 3.23.0 med sin JavaScript-regexmotor. Mappen scenarios/ indeholder 214 fixtures, hver med ét input i ét sprog og ét tema; tilsammen dækker de 167 af de 253 medfølgende grammatikker, lang: 'ansi' og alle 65 temaer. bin/test-regression fremhæver hver fixture med begge motorer og fastslår, at HTML er identisk, når indledende og afsluttende mellemrum er fjernet. Indstillinger og transformere kontrolleres med paritetstests mod output optaget fra samme Shiki og @shikijs/transformers 4.2.0. Den ufravigelige regel er, at fremhævningsoutput ikke må blive dårligere end Shiki.