Pereiti prie turinio

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

Kodas
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 (\b ir \B kaip 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 tikslus vscode-textmate perkėlimas: Registry parenka gramatikas pagal aprėpties pavadinimą (įskaitant include nuorodas, įterptąsias kalbas ir įterpimus), o Tokenizer eilutė po eilutės tvarko taisyklių ir aprėpties stekus.
  • Tema (Shikiphp\Theme) perkelia vscode-textmate temų 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.