Към съдържанието

Трансформатори

Трансформаторите ви позволяват да преобразувате откроения изход на всеки етап — от суровия низ с изходния код, през мрежата от токени до крайното HAST дърво и HTML. shikiphp възпроизвежда модела на трансформаторите на Shiki кукичка по кукичка, така че трансформаторите се държат по същия начин като съответните си варианти за JavaScript.

Подайте ги чрез опцията transformers:

PHP
use Shikiphp\Shikiphp;
use Shikiphp\Transformer\Notation\NotationHighlight;
use Shikiphp\Transformer\Notation\NotationDiff;

$code = <<<'JS'
console.log('this line is highlighted') // [!code highlight]
console.log('old line') // [!code --]
console.log('new line') // [!code ++]
JS;

echo Shikiphp::codeToHtml($code, [
    'lang'         => 'js',
    'theme'        => 'vitesse-dark',
    'transformers' => [
        new NotationHighlight(),
        new NotationDiff(),
    ],
]);

Конвейерът

Всеки трансформатор е обект, който реализира Shikiphp\Transformer\Transformer. Конвейерът изпълнява кукичките последователно при изграждането на един блок:

Кукичка Сигнатура Кога
preprocess (string $code, array &$options, $context): ?string преди токенизацията; може да пренапише изходния код и да промени опциите
tokens (array $tokens, $context): ?array след токенизацията, върху 2D мрежата от ThemedToken
root (Element $el, $context): ?Element върху корена на HAST
pre (Element $el, $context): ?Element върху елемента <pre>
code (Element $el, $context): ?Element върху елемента <code>
line (Element $el, int $line, $context): ?Element за всеки елемент на ред (от 1)
span (Element $el, int $line, int $col, Element $lineEl, ThemedToken $token, $context): ?Element за всеки обхват на токен
postprocess (string $html, array $options, $context): ?string върху крайния сериализиран низ HTML

Всички кукички са незадължителни. Връщането на стойност заменя входа; връщането на null го оставя непроменен.

enforce() управлява реда на трансформаторите: 'pre' се изпълнява първо, 'post' се изпълнява последно, а null (по подразбиране) се изпълнява между тях според реда на регистрация.

Написване на трансформатор

Разширете Shikiphp\Transformer\AbstractTransformer, за да заменяте само нужните ви кукички; останалите не правят нищо. Контекстът на трансформатора предоставя addClassToHast() за добавяне на класове към елементите.

PHP
use Shikiphp\Hast\Element;
use Shikiphp\Shikiphp;
use Shikiphp\Transformer\AbstractTransformer;
use Shikiphp\Transformer\TransformerContext;

final class AddLanguageClass extends AbstractTransformer
{
    public function pre(Element $element, TransformerContext $context): ?Element
    {
        if ($context->lang !== null) {
            $context->addClassToHast($element, 'language-' . $context->lang);
        }

        return $element;
    }
}

echo Shikiphp::codeToHtml('const answer = 42', [
    'lang'         => 'js',
    'theme'        => 'nord',
    'transformers' => [new AddLanguageClass()],
]);
// <pre class="shiki nord language-js" …>

Вградени трансформатори

Трансформатори за нотация

Те прочитат специални коментари // [!code …] в изходния код (синтаксисът за коментари на езика се открива автоматично) и ги преобразуват в класове, като премахват самия коментар. Това са директни портове на набора от обозначения @shikijs/transformers.

NotationHighlight

Shikiphp\Transformer\Notation\NotationHighlight — // [!code highlight] (или // [!code hl]) добавя класа highlighted към реда.

JavaScript
console.log('kept plain')
console.log('this line is highlighted') // [!code highlight]

NotationDiff

Shikiphp\Transformer\Notation\NotationDiff — // [!code ++] маркира ред като добавен (diff add), а // [!code --] — като премахнат (diff remove).

JavaScript
console.log('old line') // [!code --]
console.log('new line') // [!code ++]

NotationFocus

Shikiphp\Transformer\Notation\NotationFocus — // [!code focus] добавя класа focused.

JavaScript
console.log('focus on me') // [!code focus]

NotationErrorLevel

Shikiphp\Transformer\Notation\NotationErrorLevel — // [!code error], // [!code warning] и // [!code info] добавят класа highlighted плюс error / warning / info.

JavaScript
throwSomething() // [!code error]
maybeRisky()     // [!code warning]

NotationWordHighlight

Shikiphp\Transformer\Notation\NotationWordHighlight — // [!code word:foo] (по избор // [!code word:foo:2] за ограничаване до следващите N реда) обгръща всяко срещане на foo в span с highlighted-word.

JavaScript
// [!code word:config]
const config = loadConfig()

Метатрансформатори

Те прочитат метаниза на ограден блок с код, подаден чрез опцията meta (meta['__raw']), подобно на начина, по който Shiki прочита текста след езика на ограден блок с код.

MetaHighlight

Shikiphp\Transformer\MetaHighlight — откроява редовете, посочени в метадиапазон, например {1,3-5}, като добавя класа highlighted.

PHP
use Shikiphp\Shikiphp;
use Shikiphp\Transformer\MetaHighlight;

$code = "const a = 1\nconst b = 2\nconst c = 3\nconst d = 4\nconst e = 5";

echo Shikiphp::codeToHtml($code, [
    'lang'         => 'js',
    'theme'        => 'nord',
    'meta'         => ['__raw' => '{1,3-5}'],
    'transformers' => [new MetaHighlight()],
]);

MetaWordHighlight

Shikiphp\Transformer\MetaWordHighlight — откроява думите, посочени в метаниза с помощта на синтаксиса /word/, като добавя highlighted-word.

Интервали и структура

RenderWhitespace

Shikiphp\Transformer\RenderWhitespace — обгръща интервалите и табулациите в span елементи (по подразбиране с класове space и tab), за да могат да се визуализират. Конструкторът приема (classSpace, classTab, position), където position е 'all' (по подразбиране), 'boundary', 'trailing' или 'leading'.

CompactLineOptions

Shikiphp\Transformer\CompactLineOptions — прилага класове към конкретни редове от списък с елементи {line, classes}.

PHP
use Shikiphp\Transformer\CompactLineOptions;

$transformer = new CompactLineOptions([
    ['line' => 1, 'classes' => 'highlighted'],
    ['line' => 3, 'classes' => ['highlighted', 'error']],
]);

Номерата на редовете започват от 1. Подайте обекта в опцията transformers като всеки друг трансформатор.

RemoveNotationEscape

Shikiphp\Transformer\RemoveNotationEscape — премахва екранирането на формата [\!code …], използвана за записване на буквален коментар с обозначение, без да задейства трансформатор за обозначения.

RemoveLineBreak

Shikiphp\Transformer\RemoveLineBreak — премахва текстовите възли за нов ред между редовете (transformerRemoveLineBreak на Shiki).

StyleToClass

Shikiphp\Transformer\StyleToClass — премества вградените стилове в генерирани класове и събира таблица със стилове, която се извлича с getCSS(). Имената на класовете са хеширани от стила чрез cyrb53 на Shiki, така че изходът е байт по байт идентичен с @shikijs/transformers 4.2.0, включително обхвата му:

  • Стилът <pre> винаги става клас.
  • Обхватите на токените се преобразуват само когато имат предварително създаден стил, какъвто е случаят с карта themes. При единичен theme обхватите на токените запазват вградения си style="color:…", както в Shiki.
PHP
use Shikiphp\Shikiphp;
use Shikiphp\Transformer\StyleToClass;

$code = 'const answer = 42';
$styleToClass = new StyleToClass();

$html = Shikiphp::codeToHtml($code, [
    'lang'         => 'js',
    'themes'       => ['light' => 'github-light', 'dark' => 'github-dark'],
    'transformers' => [$styleToClass],
]);

$css = $styleToClass->getCSS(); // collected stylesheet for the classes above

Конструкторът приема (classPrefix, classSuffix, classReplacer); префиксът по подразбиране е __shiki_.