Ugrás a tartalomhoz

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

Kód
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 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 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.