Перейти до вмісту

shikiphp

shikiphp — порт Shiki на чистому PHP: підсвічувача синтаксису, який розфарбовує код за тими самими граматиками TextMate і темами, що й VS Code. Він токенізує код за тими самими граматиками TextMate і розфарбовує його тими самими темами VS Code, які використовує Shiki, створюючи той самий HTML, що й Shiki 3.23.0, — усе в PHP.

Без середовища виконання Node. Без розширень PHP, окрім json та mbstring. Без нативного прив’язування Oniguruma. Без запуску окремого процесу JavaScript і без розміщеного API.

PHP
use Shikiphp\Shikiphp;

echo Shikiphp::codeToHtml(<<<'PHP'
<?php
function greet(string $name): string {
    return "Hello, {$name}!";
}
PHP, [
    'lang'  => 'php',
    'theme' => 'github-dark',
]);

Чому shikiphp

Підсвічування синтаксису під час рендерингу на сервері в PHP зазвичай вимагає одного з трьох компромісів: запуску Node, виклику розміщеного API або використання підсвічувача на регулярних виразах, який насправді не розуміє мову. Жоден із цих варіантів не підходить для кроку збірки Laravel, WordPress чи статичного сайту.

shikiphp усуває компроміс, переносячи справжній конвеєр Shiki до PHP:

  • токенізатор граматик TextMate (точний порт vscode-textmate), зокрема для вбудованих мов, ін’єкцій і вкладених репозиторіїв
  • визначення тем VS Code зі специфічністю селекторів областей і зіставленням батьківських областей
  • Shiki-сумісний HTML: світла й темна теми через змінні CSS, codeToHast, трансформери (усі хуки), декорації, colorReplacements, structure: 'inline' і підсвічування ANSI (lang: 'ansi')
  • повний пакет Shiki — кожна мова tm-grammars (235 і 18 допоміжних граматик, вбудованих у них) і кожна тема tm-themes (65)

Зіставлено з Shiki 3.23.0

Результат не просто «достатньо близький»: його звірено з конкретним випуском Shiki.

Пакет Версія Використання
shiki 3.23.0 еталон із рушієм регулярних виразів JavaScript
tm-grammars 1.31.15 вбудовані граматики
tm-themes 1.12.2 вбудовані теми
@shikijs/transformers 4.2.0 тести на відповідність трансформерів

Shiki сама є еталоном. Набір регресійних тестів містить 214 сценаріїв, кожен із яких — приклад однією мовою та в одній темі зі стандартними параметрами. Кожен сценарій підсвічується за допомогою Shiki і shikiphp, а два рядки HTML мають збігатися після видалення пробілів на початку та в кінці. Разом сценарії охоплюють 167 із 253 вбудованих граматик, lang: 'ansi' і всі 65 тем. Параметри (structure, tabindex, colorReplacements, подвійні теми, defaultColor та решта), codeToTokensWithThemes і вбудовані перетворювачі перевіряються окремими тестами на відповідність, очікувані результати яких отримано з тих самих версій Shiki.

Звідси випливають два обмеження. Стандартний рушій Shiki — це Oniguruma, скомпільований у WebAssembly, а еталон використовує інший рушій регулярних виразів — JavaScript від Shiki; саме цей рушій переносять порти shikiphp. Також пізніші випуски Shiki (гілка 4.x) не перевірялися.

Як це працює

shikiphp побудовано на включеному до його складу чистому PHP-рушії регулярних виразів JavaScript із inline0/phasis, який отримує шаблони від PHP-порту oniguruma-to-es. Рушій регулярних виразів JavaScript у Shiki перетворює шаблони Oniguruma у граматиках TextMate на RegExp JavaScript, тому рушій регулярних виразів JS є природною основою — він дає shikiphp змогу відтворювати результат того рушія з точністю до кожного зміщення.

Код
code → grammar tokenizer → theme resolver → themed tokens → HTML
              │
              └─ OnigScanner → PatternConverter (oniguruma-to-es) → Shikiphp\Regex (JS RegExp engine)

Див. Архітектура, щоб ознайомитися з повним конвеєром.

Вимоги

  • PHP 8.2 або новіша версія (CI запускає набір тестів на PHP 8.4)
  • ext-json і ext-mbstring (постачаються майже з кожною збіркою PHP)

Що далі

  • Початок роботи — встановіть і відобразіть свій перший блок.
  • API — повний перелік методів.
  • Параметри — усі параметри, які приймає codeToHtml.
  • Перетворювачі — конвеєр хуків і вбудовані перетворювачі.
  • CLI — bin/shikiphp highlight, langs і themes.

Ліцензія

MIT, авторські права належать inline0. Вбудовані граматики та теми TextMate зберігають ліцензії своїх початкових проєктів.