
# Arhitektura

shikiphp pretvori izvorno kodo v označene HTML, obarvane s temami, z uporabo slovnic TextMate in tem VS Code, brez razširitev PHP razen `json`/`mbstring`, izvajalnega okolja Node in izvorne vezave Oniguruma. Ta stran povzema cevovod; celoten normativni dogovor je v repozitoriju v `ARCHITECTURE.md`.

## Cevovod

```
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>
```

Vse deluje v prostoru odmikov **kodnih enot UTF-16** — enakem kot v pogonu regularnih izrazov JS in tokenizatorju Shiki. Pri ASCII to ustreza odmikov bajtov.

## Izvajalno okolje za regularne izraze

Na najnižji ravni je `Shikiphp\Regex`, popoln čisti pogon ECMAScript za regularne izraze PHP, **priložen iz [`inline0/phasis`](https://github.com/inline0/phasis)** (čisti pogon PHP JavaScript). Razčleni vir JS-RegExp z zastavicami in izvede iskanje naprej s semantiko Oniguruma `onig_search`.

## Pretvorba Oniguruma → JS

Slovnice TextMate so zapisane v Oniguruma. `Shikiphp\Oniguruma\PatternConverter`
je prenos PHP za
[`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es): vzorec Oniguruma pretvori
v vir in niz zastavic, združljivih z JS-RegExp, ki ju sprejme pogon za regularne izraze. Po isti poti Oniguruma → RegExp, ki jo uporablja pogon regularnih izrazov ShikiJavaScript, lahko shikiphp ujema izhod tega pogona na vsakem odmiku. Pretvornik podpira konstrukte, ki jih slovnice uporabljajo v praksi: razrede POSIX, posesivne kvantifikatorje in atomske skupine, vgrajene zastavice, poimenovane skupine in povratne reference, lastnosti Unicode ter še več.

## Optični bralnik in hitra pot PCRE

`Shikiphp\Oniguruma\OnigScanner` posnema optični bralnik `vscode-oniguruma`: za vsako pravilo se enkrat zgradi iz seznama vzorcev in poišče najbolj levi ujemajoči se niz na začetnem položaju ali za njim.

Ujemanje s sprehodom po drevesu je pravilno, vendar počasno, zato ima optični bralnik hitro pot PCRE z dvema stopnjama, ki jo omogoča preverjanje enakovrednosti. `PcreTranslator` pretvori vir JS, ki ga ustvari pretvornik, v izvorni vzorec PCRE samo, kadar lahko dokaže rezultat:

- **Polno ujemanje.** Če se prevod vede enako kot ujemalnik, vključno z vsemi zajetimi nizi, se vzorec neposredno obdela s PCRE. Poimenovane skupine, povratne reference, `\p{}`, `\b`, `\G`, posnemanje atomskih skupin in zajemi, katerih semantika JavaScript se razlikuje od PCRE (znotraj ponavljajoče se skupine ali negativnega pogleda nazaj), so iz te stopnje izključeni.
- **Samo položaj.** Če se lahko razlikujejo samo zajemi, jih omogoča drugi prevod (`\b` in `\B` kot natančni pogledi ASCII, atomske skupine kot izvorni `(?>…)`, `\p{…}`, če ga PCRE prevede). PCRE nato poišče samo položaj naslednjega ujemanja, ujemalnik pa znova zažene ujemanje na tem odmiku, da ustvari prave zajeme. Povratne reference in `\G` so tudi tu izključeni.

Vse drugo obdeluje samo ujemalnik. Pri vgrajenih slovnicah Shiki 3.23.0 se približno 39 % od 14,234 različnih vzorcev v celoti izvede s PCRE, približno 57 % jih uporablja stopnjo položaja, približno 4 % pa jih obdela ujemalnik. Razvrstitev preverja razvojno orodje v repozitoriju (`bin/.oracle-tools/pcre-equivalence.php`), ki primerja hitro pot z ujemalnikom — indeks, konec in pri prvi stopnji vsak zajeti razpon — na vhodih iz scenarijev in naboru sintetičnih nizov; odstopanja niso dovoljena.

## Slovnica in tema

- **Slovnica** (`Shikiphp\Grammar`) je zvest prenos `vscode-textmate`: `Registry` razrešuje slovnice po imenu obsega (vključno s sklici `include`, vdelanimi jeziki in injekcijami), `Tokenizer` pa vzdržuje sklad pravil in obsegov po vrsticah.
- **Tema** (`Shikiphp\Theme`) prenaša ujemanje tem iz `vscode-textmate`: barva ospredja in slog pisave se razrešita glede na specifičnost izbirnika obsega in ujemanje nadrejenih obsegov.

## Izris

`Shikiphp\Render\HtmlRenderer` izdela popolnoma enako drevo `pre.shiki > code > span.line >
span` HAST Shiki, kot ga ustvarijo gradnje, nato pa ga serializira. Način z eno temo zapisuje navadne
barve; način z dvema temama zapisuje spremenljivke `--shiki-light` / `--shiki-dark` CSS.

## Preverjeno glede na Shiki

Sam Shiki je referenčni vir, pripet na `shiki` 3.23.0 z njegovim pogonom regularnih izrazov JavaScript. Imenik `scenarios/` vsebuje **214** testnih primerov, vsak z enim vhodom, jezikom in temo; skupaj pokrivajo 167 od 253 vgrajenih slovnic, `lang: 'ansi'` in vseh 65 tem. `bin/test-regression` vsakega označi z obema pogonoma in preveri, ali je HTML enak po odstranitvi začetnih in končnih presledkov. Možnosti in pretvorniki se preverjajo s testi enakovrednosti glede na izhod, zajet iz istih različic Shiki in `@shikijs/transformers` 4.2.0. Obvezujoče pravilo je, da se izhod označevanja ne sme poslabšati glede na Shiki.
