Gå til indhold

Transformere

Transformere lader dig ændre det fremhævede output i hvert trin — fra rå kildestreng gennem tokengitteret til det endelige HAST-træ og HTML. shikiphp viderefører Shikis transformermodel med de samme hooks, så transformere opfører sig på samme måde som deres modstykker i JavaScript.

Angiv dem via indstillingen 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(),
    ],
]);

Pipelineforløbet

Hver transformer er et objekt, der implementerer Shikiphp\Transformer\Transformer. Forløbet kører hooksene i rækkefølge, mens en enkelt blok bygges:

Hook Signatur Tidspunkt
preprocess (string $code, array &$options, $context): ?string før tokenisering; kan omskrive kilden og ændre indstillinger
tokens (array $tokens, $context): ?array efter tokenisering i det 2D ThemedToken-gitter
root (Element $el, $context): ?Element på HAST-roden
pre (Element $el, $context): ?Element på elementet <pre>
code (Element $el, $context): ?Element på elementet <code>
line (Element $el, int $line, $context): ?Element for hvert linjeelement (starter ved 1)
span (Element $el, int $line, int $col, Element $lineEl, ThemedToken $token, $context): ?Element for hvert tokenområde
postprocess (string $html, array $options, $context): ?string på den endeligt serialiserede HTML-streng

Alle hooks er valgfrie. Hvis du returnerer en værdi, erstatter den inputtet; hvis du returnerer null, forbliver det uændret.

enforce() styrer rækkefølgen mellem transformere: 'pre' køres først, 'post' sidst, og null (standardværdien) køres imellem dem i registreringsrækkefølge.

Skriv en transformer

Udvid Shikiphp\Transformer\AbstractTransformer, så du kun behøver at tilsidesætte de hooks, du skal bruge; resten gør ingenting. Transformerens kontekst giver adgang til addClassToHast(), så du kan føje klasser til elementer.

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

Indbyggede transformere

Transformere til notation

Disse læser særlige // [!code …]-kommentarer i kilden (kommentarsyntaksen for sproget registreres automatisk) og oversætter dem til klasser, mens selve kommentaren fjernes. De er direkte porte af @shikijs/transformers-notationssættet.

NotationHighlight

Shikiphp\Transformer\Notation\NotationHighlight — // [!code highlight] (eller // [!code hl]) tilføjer klassen highlighted til linjen.

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

NotationDiff

Shikiphp\Transformer\Notation\NotationDiff — // [!code ++] markerer en linje som tilføjet (diff add), og // [!code --] som fjernet (diff remove).

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

NotationFocus

Shikiphp\Transformer\Notation\NotationFocus — // [!code focus] tilføjer klassen focused.

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

NotationErrorLevel

Shikiphp\Transformer\Notation\NotationErrorLevel — // [!code error], // [!code warning] og // [!code info] tilføjer klassen highlighted plus error / warning / info.

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

NotationWordHighlight

Shikiphp\Transformer\Notation\NotationWordHighlight — // [!code word:foo] (eventuelt // [!code word:foo:2] for at begrænse det til de næste N linjer) omslutter hver forekomst af foo i et span med highlighted-word.

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

Metatransformere

Disse læser kodeblokkens metastreng, som angives via indstillingen meta (meta['__raw']), på samme måde som Shiki læser teksten efter sproget i en indhegnet kodeblok.

MetaHighlight

Shikiphp\Transformer\MetaHighlight — fremhæver linjer angivet i et metainterval som {1,3-5} og tilføjer klassen 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 — fremhæver ord angivet i metastrengen med syntaksen /word/ og tilføjer highlighted-word.

Mellemrum og struktur

RenderWhitespace

Shikiphp\Transformer\RenderWhitespace — omslutter mellemrumstegn og tabulatortegn i spans (som standard med klasserne space og tab), så de kan vises tydeligt. Konstruktøren tager (classSpace, classTab, position), hvor position er 'all' (standard), 'boundary', 'trailing' eller 'leading'.

CompactLineOptions

Shikiphp\Transformer\CompactLineOptions — anvender klasser på bestemte linjer ud fra en liste med {line, classes}-elementer.

PHP
use Shikiphp\Transformer\CompactLineOptions;

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

Linjenumre starter ved 1. Send objektet i indstillingen transformers som enhver anden transformer.

RemoveNotationEscape

Shikiphp\Transformer\RemoveNotationEscape — fjerner escape-tegnet fra formen [\!code …], der bruges til at skrive en bogstavelig notationskommentar uden at aktivere en notationstransformer.

RemoveLineBreak

Shikiphp\Transformer\RemoveLineBreak — fjerner linjeskiftstekstnoderne mellem linjer (Shikis transformerRemoveLineBreak).

StyleToClass

Shikiphp\Transformer\StyleToClass — flytter inline-stile til genererede klasser og samler et stilark, som du henter med getCSS(). Klassenavne beregnes som hash af stilen med Shikis cyrb53, så outputtet er byteidentisk med @shikijs/transformers 4.2.0, inklusive dets scope:

  • Stilen <pre> bliver altid til en klasse.
  • Token-spans konverteres kun, når de har en forudbygget stil, hvilket er tilfældet med et themes-kort. Med et enkelt theme beholder token-spans deres inline-style="color:…", som i 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

Konstruktøren tager (classPrefix, classSuffix, classReplacer); standardpræfikset er __shiki_.