
# Architektúra

A shikiphp a forráskódot témával kiemelt HTML formátumba alakítja a TextMate nyelvtanok és VS Code témák használatával; a `json`/`mbstring` eszközökön kívül nincs szükség PHP bővítményekre, Node.js-futtatókörnyezetre vagy natív Oniguruma-kötésre. Ez az oldal összefoglalja a folyamatot; a teljes, normatív szerződés a tárházbeli `ARCHITECTURE.md` fájlban található.

## A folyamat

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

Minden művelet **UTF-16 kódegység**-eltolásokkal dolgozik — ugyanabban a tartományban, mint a JS regexmotor és a Shiki tokenizálója. ASCII esetén ez megegyezik a bájteltolásokkal.

## A regex futtatókörnyezete

Az alján található a `Shikiphp\Regex`, egy teljes, tisztán PHP ECMAScript regexmotor, **a [`inline0/phasis`](https://github.com/inline0/phasis) forrásából átvéve** (tisztán PHP JavaScript motor). Egy JS-RegExp forrást és flagjeit elemzi, majd előre irányuló kereséseket futtat Oniguruma `onig_search` szemantikával.

## Oniguruma → JS átalakítás

A TextMate grammatikák Oniguruma nyelven íródnak. A `Shikiphp\Oniguruma\PatternConverter` a PHP [`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es) portja: egy Oniguruma mintát a JS-RegExp-kompatibilis forrássá és a regexmotor által elfogadott flag-karakterlánccá alakít. Ugyanezt az Oniguruma → RegExp útvonalat használja a Shiki JavaScript regexmotorja is, így a shikiphp eltolásonként képes egyeztetni a motor kimenetével. Az átalakító kezeli a grammatikákban használt valós konstrukciókat: POSIX-osztályokat, mohó kvantorokat és atomcsoportokat, inline flageket, elnevezett csoportokat és visszahivatkozásokat, Unicode tulajdonságokat és másokat.

## A szkenner és a PCRE gyorsútvonala

A `Shikiphp\Oniguruma\OnigScanner` a `vscode-oniguruma` szkennerét utánozza: szabályonként egyszer épül fel minták listájából, és a kezdőpozíciónál vagy utána található legbaloldalibb egyezést keresi.

A fa bejárásán alapuló illesztő helyes, de lassú, ezért a szkennernek van egy **egyezés-ellenőrzéshez kötött PCRE gyorsútvonala**, két szinttel. Egy `PcreTranslator` a konverter JS forrását csak akkor írja át natív PCRE-mintává, ha bizonyítani tudja az eredményt:

- **Teljes egyezés.** Ha az átalakítás az összes rögzítést is beleértve pontosan úgy viselkedik, mint az illesztő, a minta közvetlenül PCRE-n fut. A névvel ellátott csoportokat, visszahivatkozásokat, `\p{}`, `\b`, `\G` elemeket, az atomi emulációt, valamint azokat a rögzítéseket, amelyek JavaScript szemantikája eltér a PCRE-étől (kvantált csoporton vagy visszatekintő állításon belül), ez a szint elutasítja.
- **Csak pozíció.** Ha csak a rögzítések térhetnek el, egy második átalakítás engedélyezi ezeket a szerkezeteket (a `\b` és `\B` elemeket pontos ASCII lookaroundként, az atomi csoportokat natív `(?>…)` formában, `\p{…}` esetén, ha a PCRE le tudja fordítani). A PCRE ekkor csak a következő egyezés helyét keresi meg; az illesztő ezen az eltoláson újra lefut, hogy előállítsa a tényleges rögzítéseket. A visszahivatkozások és a `\G` ebben a szintben is tiltottak.

Minden más csak az illesztőt használja. A Shiki 3.23.0 helyen található csomagolt nyelvtanoknál a 14,234 különböző minták körülbelül 39%-a teljes egészében PCRE-n fut, körülbelül 57% a pozíciószintet használja, 4% pedig az illesztőn marad. A besorolást egy tárházbeli fejlesztői eszköz (`bin/.oracle-tools/pcre-equivalence.php`) ellenőrzi: összeveti a gyorsútvonalat az illesztővel a forgatókönyvek bemenetein és egy sor szintetikus karakterláncon — az indexet, a véget és az első szintnél minden rögzítési tartományt is —, és nem enged meg eltérést.

## Nyelvtan és téma

- **Nyelvtan** (`Shikiphp\Grammar`): a `vscode-textmate` hű portja. Egy `Registry` hatókörnév alapján oldja fel a nyelvtanokat (beleértve a `include` hivatkozásokat, a beágyazott nyelveket és a beszúrásokat), egy `Tokenizer` pedig sorról sorra karbantartja a szabály- és hatókörvermet.
- **Téma** (`Shikiphp\Theme`): a `vscode-textmate` témakezelésének portja. Az előtér és a betűstílus a hatókörválasztó specifikussága és a szülőhatókörök illesztése alapján oldódik fel.

## Megjelenítés

A `Shikiphp\Render\HtmlRenderer` létrehozza a Shiki által készített pontos `pre.shiki > code > span.line >
span` HAST-fát, majd szerializálja. Egytémás módban egyszerű színeket ír ki; kéttémás módban `--shiki-light` / `--shiki-dark` CSS változókat ír ki.

## Ellenőrzés a Shiki alapján

Maga az Shiki a mérvadó forrás, az `shiki` 3.23.0 verziójához rögzítve, a saját JavaScript reguláriskifejezés-motorjával. Az `scenarios/` könyvtár 214 tesztpéldát tartalmaz; mindegyik egy bemenet egy nyelven és egy témával. Együtt az 253 csomagban található nyelvtanok 167-át, az `lang: 'ansi'`-t és mind a 65 témát fedik le. Az `bin/test-regression` mindkét motorral kiemeli ezeket, majd ellenőrzi, hogy az HTML a kezdő és záró szóközök eltávolítása után azonos-e. Az opciók és az átalakítók paritástesztjei ugyanabból az Shiki-ből és az `@shikijs/transformers` 4.2.0-ből rögzített kimenettel való egyezést ellenőrzik. Az alapvető szabály: a kiemelés kimenete nem romolhat az Shiki-hoz képest.
