
# Architektura

shikiphp převádí zdrojový kód na zvýrazněné HTML podle motivu pomocí gramatik TextMate a motivů VS Code, bez rozšíření PHP mimo `json`/`mbstring`, bez běhového prostředí Node a bez nativní vazby Oniguruma. Tato stránka shrnuje postup; úplná závazná specifikace je v souboru `ARCHITECTURE.md` v repozitáři.

## Postup zpracování

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

Vše probíhá v prostoru offsetů **UTF-16 kódových jednotek** — stejném jako v regulárním výrazovém modulu JS a tokenizeru Shiki. U znaků ASCII se shoduje s bajtovými offsety.

## Běhové prostředí regulárních výrazů

Na nejnižší vrstvě je `Shikiphp\Regex`, kompletní čistě PHP engine regulárních výrazů ECMAScriptu, **převzatý z [`inline0/phasis`](https://github.com/inline0/phasis)** (engine čistě PHP JavaScript). Zpracovává zdrojový kód JS-RegExp spolu s příznaky a provádí vyhledávání dopředu se sémantikou Oniguruma `onig_search`.

## Převod Oniguruma → JS

Gramatiky TextMate jsou napsány v Oniguruma. `Shikiphp\Oniguruma\PatternConverter` je port PHP nástroje [`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es): převádí vzor Oniguruma na zdrojový kód a řetězec příznaků kompatibilní s JS-RegExp, které engine regulárních výrazů přijímá. Jde o stejnou cestu Oniguruma → RegExp, kterou používá engine regulárních výrazů ShikiJavaScript, a díky tomu může shikiphp porovnávat svůj výstup s výstupem tohoto enginu offset po offsetu. Převodník podporuje konstrukce používané v reálných gramatikách: třídy POSIX, hladové kvantifikátory a atomické skupiny, vložené příznaky, pojmenované skupiny a zpětné odkazy, vlastnosti Unicode a další.

## Skener a jeho rychlá cesta PCRE

`Shikiphp\Oniguruma\OnigScanner` kopíruje skener `vscode-oniguruma`: pro každé pravidlo se jednou sestaví ze seznamu vzorů a hledá nejlevější shodu na zadané pozici nebo za ní.

Matcher procházející strom je správný, ale pomalý, proto má skener rychlou cestu PCRE ověřenou ekvivalencí ve dvou úrovních. `PcreTranslator` přepisuje zdrojový kód JS z převodníku na nativní vzor PCRE jen tehdy, když může dokázat výsledek:

- **Úplná shoda.** Pokud se překlad chová stejně jako porovnávač, včetně všech zachycených skupin, vzor se spustí přímo v PCRE. Pojmenované skupiny, zpětné odkazy, `\p{}`, `\b`, `\G`, emulace atomických skupin a zachycené skupiny, jejichž sémantika JavaScript se liší od PCRE (uvnitř kvantifikované skupiny nebo v lookbehind), jsou z této úrovně vyloučeny.
- **Pouze pozice.** Pokud se mohou lišit jen zachycené skupiny, druhý překlad připouští tyto konstrukce (`\b` a `\B` jako přesné ASCII lookaroundy, atomické skupiny jako nativní `(?>…)`, `\p{…}`, pokud je PCRE zkompiluje). PCRE pak pouze najde pozici další shody a porovnávač spustí znovu na tomto offsetu, aby vytvořil skutečné zachycené skupiny. Zpětné odkazy a `\G` jsou i zde vyloučeny.

Vše ostatní zpracovává pouze matcher. U sdružených gramatik v Shiki 3.23.0 běží přibližně 39 % z 14,234 jedinečných vzorů plně v PCRE, přibližně 57 % používá úroveň určující pouze pozici a přibližně 4 % zůstávají u matcheru. Klasifikaci ověřuje vývojářský nástroj v repozitáři (`bin/.oracle-tools/pcre-equivalence.php`), který porovnává rychlou cestu s matcherem — index, konec a u první úrovně i rozsah každé zachycené skupiny — na scénářových vstupech a sadě syntetických řetězců; povoleny nejsou žádné rozdíly.

## Gramatika a motiv

- **Gramatika** (`Shikiphp\Grammar`) je přesný port `vscode-textmate`: `Registry` vyhledává gramatiky podle názvu oboru (včetně odkazů `include`, vložených jazyků a injekcí) a `Tokenizer` udržuje zásobník pravidel a oborů po jednotlivých řádcích.
- **Motiv** (`Shikiphp\Theme`) přenáší způsob přiřazování motivů z `vscode-textmate`: barva popředí a styl písma se určují podle konkrétnosti selektoru oboru a shody s nadřazenými obory.

## Vykreslování

`Shikiphp\Render\HtmlRenderer` vytvoří přesně takový strom HAST `pre.shiki > code > span.line >
span`, jaký vytváří Shiki, a poté jej serializuje. Režim jednoho motivu zapisuje běžné barvy; režim dvou motivů zapisuje proměnné `--shiki-light` / `--shiki-dark` CSS.

## Ověřeno vůči Shiki

Shiki samo slouží jako referenční zdroj a je připnuté k verzi `shiki` 3.23.0 s jeho modulem regulárních výrazů JavaScript. Adresář `scenarios/` obsahuje **214** testovacích podkladů, přičemž každý představuje jeden vstup v jednom jazyce a jednom motivu; dohromady pokrývají 167 z 253 přibalených gramatik, `lang: 'ansi'` a všech 65 motivů. `bin/test-regression` zvýrazní každý podklad oběma enginy a ověří, že HTML jsou po oříznutí počátečních a koncových mezer totožné. Možnosti a transformátory se kontrolují testy shody s výstupem zachyceným ze stejného Shiki a `@shikijs/transformers` 4.2.0. Nepřekročitelným pravidlem je, že se výstup zvýrazňování nesmí oproti Shiki zhoršit.
