Architektūra
shikiphp paverčia pirminį kodą teminiu, paryškintu HTML, naudodama TextMate gramatikas ir VS Code temas. Jai nereikia jokių PHP plėtinių, išskyrus json/mbstring, Node vykdymo aplinkos ar savųjų Oniguruma sąsajų. Šiame puslapyje apžvelgiamas procesas; visa norminė specifikacija yra saugyklos ARCHITECTURE.md.
Proceso eiga
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>
Viskas veikia UTF-16 kodo vienetų poslinkių erdvėje — tai ta pati erdvė, kurią naudoja JS regex sistema ir Shiki tokenizatorius. ASCII atveju ji sutampa su baitų poslinkiais.
Regex vykdymo aplinka
Pačiame pagrinde yra Shikiphp\Regex — išsami grynojo PHP ECMAScript regex sistema, įtraukta iš inline0/phasis (grynojo PHP JavaScript sistema). Ji analizuoja JS RegExp šaltinį su vėliavėlėmis ir atlieka paiešką į priekį pagal Oniguruma onig_search semantiką.
Oniguruma → JS konvertavimas
TextMate gramatikos rašomos Oniguruma kalba. Shikiphp\Oniguruma\PatternConverter yra PHP prievadas, perkeliantis oniguruma-to-es funkcionalumą: jis paverčia Oniguruma šabloną į JS RegExp suderinamą šaltinio eilutę ir vėliavėlių eilutę, kurią regex sistema gali priimti. Tai tas pats kelias Oniguruma → RegExp, kuriuo naudojasi Shiki regex sistema JavaScript; todėl shikiphp gali sutapdinti jos išvestį pagal kiekvieną poslinkį. Konverteris apdoroja realiose gramatikose naudojamas konstrukcijas: POSIX klases, godžius kiekybinius operatorius ir atomines grupes, eilutines vėliavėles, pavadintas grupes ir atgalines nuorodas, Unicode savybes ir daugiau.
Skeneris ir PCRE greitasis kelias
Shikiphp\Oniguruma\OnigScanner atkartoja vscode-oniguruma skenerio veikimą: kiekvienai taisyklei jis vieną kartą sudaromas iš šablonų sąrašo ir randa kairiausiai esantį atitikmenį nurodytoje pradinėje pozicijoje arba už jos.
Medžiu paremtas atitikmenų ieškiklis veikia teisingai, bet lėtai, todėl skeneris turi lygiavertiškumu patvirtintą PCRE greitąjį kelią su dviem lygiais. PcreTranslator perrašo konverterio JS šaltinio eilutę į savąjį PCRE šabloną tik tada, kai gali įrodyti, kad rezultatas:
- Visas atitikmuo. Jei vertimas veikia taip pat kaip atitikmenų ieškiklis, įskaitant kiekvieną fiksavimą, šablonas vykdomas tiesiogiai PCRE. Pavadintos grupės, atgalinės nuorodos,
\p{},\b,\G, atominių grupių imitavimas ir fiksavimai, kurių JavaScript semantika skiriasi nuo PCRE (kiekybiškai kartojamoje grupėje arba užnugaros patikroje), į šį lygį neįtraukiami. - Tik pozicija. Jei skirtis gali tik fiksavimai, antrasis vertimas leidžia naudoti šias konstrukcijas (
\bir\Bkaip tikslias ASCII užnugaros patikras, atomines grupes kaip savąsias(?>…)ir\p{…}, jei PCRE jas sukompiliuoja). Tada PCRE tik nustato kito atitikmens vietą, o atitikmenų ieškiklis iš naujo vykdomas tame poslinkyje, kad gautų tikruosius fiksavimus. Atgalinės nuorodos ir\Gčia taip pat neleidžiamos.
Visa kita vykdoma tik pagal šablonų atitikiklį. Susietose gramatikose, esančiose Shiki 3.23.0, apie 39 % iš 14,234 skirtingų šablonų visiškai apdorojami PCRE, apie 57 % naudoja pozicijų lygmenį, o apie 4 % lieka atitikiklyje. Klasifikaciją tikrina kūrimo įrankis saugykloje (bin/.oracle-tools/pcre-equivalence.php), kuris lygina spartųjį kelią su atitikikliu — indeksą, pabaigą ir, pirmajame lygmenyje, kiekvieno užfiksavimo intervalo pradžią bei pabaigą — pagal scenarijų įvestis ir sintetinių eilučių rinkinį; leidžiama nulis neatitikimų.
Gramatika ir tema
- Gramatika (
Shikiphp\Grammar) yra tikslusvscode-textmateperkėlimas:Registryparenka gramatikas pagal aprėpties pavadinimą (įskaitantincludenuorodas, įterptąsias kalbas ir įterpimus), oTokenizereilutė po eilutės tvarko taisyklių ir aprėpties stekus. - Tema (
Shikiphp\Theme) perkeliavscode-textmatetemų parinkimo veikimą: priekinio plano spalva ir šrifto stilius parenkami pagal aprėpties parinkiklio konkretumą, atsižvelgiant į tėvinės aprėpties atitikmenis.
Atvaizdavimas
Shikiphp\Render\HtmlRenderer sukuria tokį patį pre.shiki > code > span.line > span HAST medį kaip Shiki, tada jį serializuoja. Vienos temos režimu įrašomos paprastos spalvos; dviejų temų režimu įrašomi --shiki-light / --shiki-dark CSS kintamieji.
Patikrinta pagal Shiki
Pats Shiki yra etalonas; naudojama konkreti shiki 3.23.0 versija su jos JavaScript regex sistema. scenarios/ kataloge yra 214 pavyzdžių: kiekvienas jų yra vienos kalbos ir vienos temos įvestis. Kartu jie aprėpia 253 iš 167 įtrauktų gramatikų, lang: 'ansi' ir visas 65 temas. bin/test-regression paryškina kiekvieną pavyzdį abiem sistemomis ir patikrina, kad HTML sutampa apkarpius pradžios ir pabaigos tarpus. Parinktys ir transformatoriai tikrinami palyginimo testais su išvestimi, gauta iš tos pačios Shiki ir @shikijs/transformers 4.2.0. Pagrindinė taisyklė nekinta: paryškinimo išvestis negali nukrypti nuo Shiki.