Lewati ke konten

Transformer

Transformer memungkinkan Anda mengubah bentuk keluaran yang disorot pada setiap tahap — dari string sumber mentah, melalui kisi token, hingga pohon HAST final dan HTML. shikiphp mengadaptasi model transformer Shiki hook demi hook, sehingga transformer berperilaku sama dengan padanannya di JavaScript.

Teruskan melalui opsi 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(),
    ],
]);

Pipeline

Setiap transformer adalah objek yang mengimplementasikan Shikiphp\Transformer\Transformer. Pipeline menjalankan hook secara berurutan saat membangun satu blok:

Hook Tanda tangan Kapan
preprocess (string $code, array &$options, $context): ?string sebelum tokenisasi; dapat mengubah sumber dan memodifikasi opsi
tokens (array $tokens, $context): ?array setelah tokenisasi, pada kisi 2D ThemedToken
root (Element $el, $context): ?Element pada akar HAST
pre (Element $el, $context): ?Element pada elemen <pre>
code (Element $el, $context): ?Element pada elemen <code>
line (Element $el, int $line, $context): ?Element untuk setiap elemen baris (indeks mulai dari 1)
span (Element $el, int $line, int $col, Element $lineEl, ThemedToken $token, $context): ?Element untuk setiap rentang token
postprocess (string $html, array $options, $context): ?string pada string HTML serialisasi final

Setiap hook bersifat opsional. Mengembalikan nilai akan mengganti input; mengembalikan null akan membiarkannya tetap sama.

enforce() mengatur urutan antar-transformer: 'pre' dijalankan pertama, 'post' dijalankan terakhir, dan null (default) dijalankan di antaranya sesuai urutan pendaftaran.

Menulis transformer

Perluas Shikiphp\Transformer\AbstractTransformer agar Anda hanya perlu mengganti hook yang diperlukan; sisanya tetap tanpa operasi. Konteks transformer menyediakan addClassToHast() untuk menambahkan kelas ke elemen.

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" …>

Transformer bawaan

Transformer notasi

Transformer ini membaca komentar // [!code …] khusus dalam sumber (sintaks komentar bahasa dideteksi secara otomatis) dan mengubahnya menjadi kelas, lalu menghapus komentarnya. Transformer ini merupakan adaptasi langsung dari kumpulan notasi @shikijs/transformers.

NotationHighlight

Shikiphp\Transformer\Notation\NotationHighlight — // [!code highlight] (atau // [!code hl]) menambahkan kelas highlighted ke barisnya.

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

NotationDiff

Shikiphp\Transformer\Notation\NotationDiff — // [!code ++] menandai baris sebagai ditambahkan (diff add), // [!code --] sebagai dihapus (diff remove).

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

NotationFocus

Shikiphp\Transformer\Notation\NotationFocus — // [!code focus] menambahkan kelas focused.

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

NotationErrorLevel

Shikiphp\Transformer\Notation\NotationErrorLevel — // [!code error], // [!code warning], dan // [!code info] menambahkan kelas highlighted beserta error / warning / info.

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

NotationWordHighlight

Shikiphp\Transformer\Notation\NotationWordHighlight — // [!code word:foo] (opsional // [!code word:foo:2] untuk membatasi hingga N baris berikutnya) membungkus setiap kemunculan foo dalam rentang yang memuat highlighted-word.

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

Transformer meta

Transformer ini membaca string meta code fence yang diberikan melalui opsi meta (meta['__raw']), seperti Shiki membaca teks setelah bahasa pada blok kode berpagar.

MetaHighlight

Shikiphp\Transformer\MetaHighlight — menyorot baris yang disebutkan dalam rentang meta seperti {1,3-5}, dengan menambahkan kelas 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 — menyorot kata yang disebutkan dalam string meta dengan sintaks /word/, dengan menambahkan highlighted-word.

Spasi dan struktur

RenderWhitespace

Shikiphp\Transformer\RenderWhitespace — membungkus karakter spasi dan tab dalam rentang (kelas space dan tab secara default) agar dapat ditampilkan secara visual. Konstruktor menerima (classSpace, classTab, position), dengan position berupa 'all' (default), 'boundary', 'trailing', atau 'leading'.

CompactLineOptions

Shikiphp\Transformer\CompactLineOptions — menerapkan kelas pada baris tertentu dari daftar entri {line, classes}.

PHP
use Shikiphp\Transformer\CompactLineOptions;

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

Nomor baris dimulai dari 1. Teruskan objek melalui opsi transformers seperti transformer lainnya.

RemoveNotationEscape

Shikiphp\Transformer\RemoveNotationEscape — menghapus escape pada bentuk [\!code …] yang digunakan untuk menulis komentar notasi literal tanpa memicu transformer notasi.

RemoveLineBreak

Shikiphp\Transformer\RemoveLineBreak — menghapus node teks pemisah baris di antara baris (Shiki milik transformerRemoveLineBreak).

StyleToClass

Shikiphp\Transformer\StyleToClass — memindahkan gaya inline ke dalam kelas yang dihasilkan dan mengumpulkan stylesheet yang dapat Anda ambil dengan getCSS(). Nama kelas menggunakan hash gaya dengan Shiki milik cyrb53, sehingga keluaran identik byte demi byte dengan @shikijs/transformers 4.2.0, termasuk cakupannya:

  • Gaya <pre> selalu menjadi kelas.
  • Rentang token hanya dikonversi jika memuat gaya yang telah dibuat sebelumnya, seperti pada peta themes. Dengan satu theme, rentang token tetap menggunakan gaya inline style="color:…", seperti pada 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

Konstruktor menerima (classPrefix, classSuffix, classReplacer); prefiks defaultnya adalah __shiki_.