
# 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`](https://github.com/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`](https://github.com/slevithan/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 (`\b` og `\B` som 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 `\G` afvises 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 af `vscode-textmate`: en `Registry` finder grammatikker ud fra scope-navn (inklusive referencer til `include`, indlejrede sprog og injectioner), og en `Tokenizer` vedligeholder regel- og scope-stakke linje for linje.
- **Tema** (`Shikiphp\Theme`) porterer temamatchningen fra `vscode-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.
