
# Arkkitehtuuri

shikiphp muuntaa lähdekoodin teeman mukaiseksi korostetuksi HTML-sisällöksi käyttäen TextMate-kielioppeja ja VS Code-teemoja. Se ei tarvitse PHP-laajennuksia `json`/`mbstring`-tuen lisäksi, Node-ajoympäristöä eikä natiivisidontaa kohteeseen Oniguruma. Tämä sivu tiivistää käsittelyputken; koko normatiivinen sopimus on arkiston tiedostossa `ARCHITECTURE.md`.

## Käsittelyputki

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

Kaikki toimii **UTF-16-koodiyksiköiden** siirtymäavaruudessa — samassa kuin JS-regex-moottori ja Shiki-jäsennin. ASCII-merkistössä tämä vastaa tavusiirtymiä.

## Regex-ajoympäristö

Alimpana on `Shikiphp\Regex`, täydellinen puhdas-PHP ECMAScript-regex-moottori, joka on **toimittajan mukana [`inline0/phasis`](https://github.com/inline0/phasis)** (puhdas-PHP JavaScript-moottori). Se jäsentää JS-RegExp-lähdekoodin ja liput sekä suorittaa eteenpäin suuntautuvia hakuja semantiikalla Oniguruma `onig_search`.

## Muunnos Oniguruma → JS

TextMate-kieliopit kirjoitetaan Oniguruma-kielellä. `Shikiphp\Oniguruma\PatternConverter`
on PHP-porttaus
[`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es)-kirjastosta: se muuntaa
Oniguruma-mallin JS-RegExp-yhteensopivaksi lähdekoodiksi ja lippumerkkijonoksi, jonka regex-moottori hyväksyy. Tämä on sama Oniguruma → RegExp-polku, jota Shiki:n JavaScript-regex-moottori käyttää. Siksi shikiphp voi täsmätä moottorin tulokseen tavu tavulta. Muunnin käsittelee kieliopeissa käytetyt todelliset rakenteet: POSIX-luokat, ahneet kvantifioijat ja atomiset ryhmät, rivinsisäiset liput, nimetyt ryhmät ja takautuvat viittaukset, Unicode-ominaisuudet ja paljon muuta.

## Jäsennin ja sen PCRE-pikapolku

`Shikiphp\Oniguruma\OnigScanner` vastaa `vscode-oniguruma`n jäsennintä: se luodaan kerran kutakin sääntöä varten malliluettelosta, ja se etsii vasemmanpuoleisimman osuman aloituskohdasta tai sen jälkeen.

Puurakennetta läpikäyvä täsmääjä on oikea mutta hidas, joten jäsentimessä on **vastaavuuden varmistava PCRE-pikapolku**, jossa on kaksi tasoa. `PcreTranslator` muuntaa muuntimen JS-lähdekoodin natiiviksi PCRE-malliksi vain, kun tuloksen oikeellisuus voidaan todistaa:

- **Täysi osuma.** Kun käännös toimii samalla tavalla kuin täsmääjä, kaikki kaappaukset mukaan lukien, malli suoritetaan suoraan PCRE:llä. Nimetyt ryhmät, takaviittaukset, `\p{}`, `\b`, `\G`, atomisten ryhmien emulointi sekä kaappaukset, joiden JavaScript-semantiikka eroaa PCRE:stä (kvantifioidun ryhmän sisällä tai takautuvassa haussa), eivät kelpaa tälle tasolle.
- **Vain sijainti.** Kun vain kaappaukset voivat erota, toinen käännös sallii nämä rakenteet (`\b` ja `\B` täsmällisinä ASCII-hakuina, atomiset ryhmät natiivina `(?>…)`-rakenteena, `\p{…}` jos PCRE kääntää sen). PCRE etsii tällöin vain seuraavan osuman sijainnin, ja täsmääjä suoritetaan uudelleen kyseisestä kohdasta oikeiden kaappausten tuottamiseksi. Takaviittaukset ja `\G` eivät kelpaa tällekään tasolle.

Kaikki muu suoritetaan vain täsmääjällä. Mukana toimitettavista kieliopeista kohdassa Shiki 3.23.0 noin 39 % 14,234 erillisestä mallista suoritetaan kokonaan PCRE:llä, noin 57 % käyttää sijaintitasoa ja noin 4 % jää täsmääjän varaan. Luokittelun tarkistaa kehitystyökalu repositoriossa (`bin/.oracle-tools/pcre-equivalence.php`), joka vertaa pikapolkua täsmääjään — indeksin, lopun ja ensimmäisellä tasolla kaikkien kaappausten jänteet — skenaarioiden syötteillä ja synteettisten merkkijonojen joukolla. Eroja ei sallita.

## Kielioppi ja teema

- **Kielioppi** (`Shikiphp\Grammar`) on uskollinen porttaus lähteestä `vscode-textmate`: `Registry` selvittää kieliopit laajuusnimen perusteella (mukaan lukien `include`-viittaukset, upotetut kielet ja injektiot), ja `Tokenizer` ylläpitää sääntö- ja laajuuspinoja rivi riviltä.
- **Teema** (`Shikiphp\Theme`) porttaa lähteen `vscode-textmate` teemojen täsmäytyksen: etualan väri ja fonttityyli määräytyvät laajuusvalitsimen tarkkuuden ja ylälaajuuden täsmäytyksen perusteella.

## Renderöinti

`Shikiphp\Render\HtmlRenderer` rakentaa täsmälleen saman HAST-puun, jonka `pre.shiki > code > span.line >
span`Shiki rakentaa, ja sarjallistaa sen sitten. Yhden teeman tila kirjoittaa tavalliset värit; kahden teeman tila kirjoittaa `--shiki-light` / `--shiki-dark` CSS-muuttujat.

## Varmennettu lähteeseen Shiki nähden

Shiki on itse vertailukohta, joka on lukittu versioon `shiki` 3.23.0 sen JavaScript-regex-moottorilla. `scenarios/`-hakemisto sisältää **214** testitapausta, joista kukin on yksi syöte yhdellä kielellä ja yhdellä teemalla; yhdessä ne kattavat 167 253 mukana toimitetusta kieliopista, `lang: 'ansi'` ja kaikki 65 teemaa. `bin/test-regression` korostaa kunkin molemmilla moottoreilla ja varmistaa, että HTML on identtinen, kun alun ja lopun välilyönnit on poistettu. Asetukset ja muuntimet tarkistetaan saman Shiki- ja `@shikijs/transformers`-version 4.2.0-tuloksista kerättyjen tulosten kanssa parity-testeillä. Ehdoton sääntö on, ettei korostustulos saa heikentyä suhteessa versioon Shiki.
