İçeriğe geç

Mimari

shikiphp, kaynak kodu, TextMate dilbilgileri ve VS Code temaları kullanarak temalı ve vurgulanmış HTML biçimine dönüştürür. json/mbstring dışındaki PHP uzantıları, Node çalışma zamanı ve yerel Oniguruma bağlaması gerekmez. Bu sayfa işlem hattını özetler; tüm bağlayıcı sözleşme depodaki ARCHITECTURE.md içinde yer alır.

İşlem hattı

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

Her şey UTF-16 kod birimi ofset alanında çalışır; bu, JS regex motorunun ve Shiki belirteç ayırıcısının kullandığı alanla aynıdır. ASCII için bu, bayt ofsetlerine eşittir.

Regex çalışma zamanı

En altta, eksiksiz ve saf-PHP ECMAScript regex motoru olan Shikiphp\Regex bulunur; inline0/phasis kaynağından satıcıdan alınmıştır (saf-PHP JavaScript motoru). Bir JS RegExp kaynağını ve bayrakları ayrıştırır, ardından Oniguruma onig_search anlamlarıyla ileri yönde aramalar yapar.

Oniguruma → JS dönüşümü

TextMate dilbilgileri Oniguruma ile yazılır. Shikiphp\Oniguruma\PatternConverter, oniguruma-to-es için bir PHP uyarlamasıdır: bir Oniguruma desenini, regex motorunun kabul ettiği JS uyumlu RegExp kaynak koduna ve bayrak dizgesine dönüştürür. Bu, aynı regex motorunun izlediği Oniguruma → RegExp yoludur; Shiki'ın JavaScript motoru da bu yolu izler. Böylece shikiphp, motorun çıktısıyla her ofsette eşleşebilir. Dönüştürücü, dilbilgilerinde kullanılan gerçek dünya yapılarını destekler: POSIX sınıfları, sahiplenici niceleyiciler ve atomik gruplar, satır içi bayraklar, adlandırılmış gruplar ve geri başvurular, Unicode özellikleri ve daha fazlası.

Tarayıcı ve PCRE hızlı yolu

Shikiphp\Oniguruma\OnigScanner, vscode-oniguruma tarayıcısını yansıtır: her kural için desen listesinden bir kez oluşturulur ve başlangıç konumunda veya sonrasında en soldaki eşleşmeyi bulur.

Ağaçta dolaşan eşleştirici doğrudur ancak yavaştır; bu nedenle tarayıcıda, eşdeğerliği koşul olarak kullanan iki katmanlı bir PCRE hızlı yolu bulunur. PcreTranslator, dönüştürücünün JS kaynağını yalnızca sonucu kanıtlayabildiği durumlarda yerel bir PCRE desenine dönüştürür:

  • Tam eşleşme. Her yakalama dâhil olmak üzere dönüşüm, eşleştiriciyle aynı şekilde davrandığında desen doğrudan PCRE üzerinde çalışır. Adlandırılmış gruplar, geriye başvurular, \p{}, \b, \G, atomik öykünme ve JavaScript anlamları PCRE'den farklı olan yakalamalar (nicelenmiş bir grubun içinde veya geriye dönük bakışta) bu katmana alınmaz.
  • Yalnızca konum. Yalnızca yakalamaların farklı olabileceği durumlarda ikinci bir dönüşüm, bu yapıları kabul eder (\b ve \B tam ASCII bakışları olarak, atomik gruplar yerel (?>…) olarak; PCRE derleyebilirse \p{…}). PCRE yalnızca sonraki eşleşmenin konumunu bulur; gerçek yakalamaları üretmek için eşleştirici o ofsette yeniden çalışır. Geriye başvurular ve \G burada da kabul edilmez.

Diğer her şey yalnızca eşleştiriciyle çalışır. Shiki 3.23.0 sürümündeki paketlenmiş dilbilgiler için 14,234 farklı desenin yaklaşık %39'u tamamen PCRE üzerinde, yaklaşık %57'si konum katmanında çalışır ve yaklaşık %4'ü eşleştiricide kalır. Sınıflandırma, depodaki bir geliştirme aracı (bin/.oracle-tools/pcre-equivalence.php) tarafından denetlenir. Bu araç hızlı yolu eşleştiriciyle karşılaştırır: senaryo girdileri ve sentetik dizeler kümesi üzerinde dizin, bitiş ve ilk katmanda her yakalama aralığını denetler; hiçbir farklılığa izin verilmez.

Dilbilgisi ve tema

  • Dilbilgisi (Shikiphp\Grammar), vscode-textmate için aslına sadık bir uyarlamadır: Registry, dilbilgilerini kapsam adına göre çözümler (include başvuruları, gömülü diller ve enjeksiyonlar dâhil); Tokenizer ise kural ve kapsam yığınlarını satır satır tutar.
  • Tema (Shikiphp\Theme), vscode-textmate tema eşleştirmesini uyarlar: ön plan ve yazı tipi stili, üst kapsam eşleştirmesiyle kapsam seçicisinin özgüllüğüne göre çözümlenir.

İşleme

Shikiphp\Render\HtmlRenderer, Shiki'ın oluşturduğu pre.shiki > code > span.line > span HAST ağacını birebir oluşturur, ardından serileştirir. Tek tema kipinde düz renkler; çift tema kipinde ise --shiki-light / --shiki-dark CSS değişkenleri yazılır.

Shiki ile doğrulandı

Shiki, shiki 3.23.0 sürümüne ve onun JavaScript regex motoruna sabitlenmiş doğruluk kaynağıdır. scenarios/ dizini, her biri bir dil ve temada tek bir girdi olan 214 test fikstürü içerir; bunlar birlikte paketlenmiş dilbilgilerinin 253 167 kadarını, lang: 'ansi''i ve 65 temanın tümünü kapsar. bin/test-regression, her birini iki motorla vurgular ve baştaki ve sondaki boşluklar kırpıldıktan sonra HTML değerinin aynı olduğunu doğrular. Seçenekler ve dönüştürücüler, aynı Shiki ve @shikijs/transformers 4.2.0 üzerinden yakalanan çıktıyla eşitlik testleri kullanılarak denetlenir. Vazgeçilmez kural, vurgulama çıktısının Shiki karşısında gerilememesidir.