
# Teisendajad

Teisendajad võimaldavad esiletõstetud väljundit igas etapis kujundada — alates algsest lähtekoodistringist läbi märgendite ruudustiku kuni lõpliku HAST-puu ja HTML-ni. shikiphp järgib Shiki teisendajate mudelit konks konksu haaval, nii et teisendajad toimivad samamoodi nagu nende JavaScript vasted.

Anna need edasi valikuga [`transformers`](https://shikiphp.inline0.dev/et/docs/options#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(),
    ],
]);
```

## Töötlusahel

Iga teisendaja on objekt, mis rakendab liidest `Shikiphp\Transformer\Transformer`. Torujuhe käivitab konksud järjest ühe ploki koostamisel:

| Konks | Signatuur | Millal |
| --- | --- | --- |
| `preprocess` | `(string $code, array &$options, $context): ?string` | enne märgendamist; võib lähtekoodi ümber kirjutada ja valikuid muuta |
| `tokens` | `(array $tokens, $context): ?array` | pärast märgendamist 2D `ThemedToken` ruudustikul |
| `root` | `(Element $el, $context): ?Element` | HAST-i juurelemendil |
| `pre` | `(Element $el, $context): ?Element` | elemendil `<pre>` |
| `code` | `(Element $el, $context): ?Element` | elemendil `<code>` |
| `line` | `(Element $el, int $line, $context): ?Element` | iga rea elemendil (alates 1-st) |
| `span` | `(Element $el, int $line, int $col, Element $lineEl, ThemedToken $token, $context): ?Element` | iga märgendi ulatuses |
| `postprocess` | `(string $html, array $options, $context): ?string` | lõpliku serialiseeritud HTML stringi puhul |

Kõik konksud on valikulised. Väärtuse tagastamine asendab sisendi; `null` tagastamine jätab selle muutmata.

`enforce()` juhib teisendajate järjestust: `'pre'` käivitatakse esimesena, `'post'` viimasena ja `null` (vaikeväärtus) nende vahel registreerimise järjekorras.

## Teisendaja kirjutamine

Laienda `Shikiphp\Transformer\AbstractTransformer`, et peaksid üle kirjutama ainult vajalikud konksud; ülejäänud ei tee midagi. Teisendaja kontekstis on `addClassToHast()`, millega elementidele klasse lisada.

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

## Sisseehitatud teisendajad

### Märgistus teisendajad

Need loevad lähtekoodi erilisi `// [!code …]` kommentaare (kommentaari süntaks tuvastatakse automaatselt) ja teisendavad need klassideks, eemaldades kommentaari enda. Need on `@shikijs/transformers` märgistuskomplekti otsesed teisendused.

#### `NotationHighlight`

`Shikiphp\Transformer\Notation\NotationHighlight` — `// [!code highlight]` (või `// [!code hl]`) lisab reale klassi `highlighted`.

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

#### `NotationDiff`

`Shikiphp\Transformer\Notation\NotationDiff` — `// [!code ++]` märgib rea lisatuks (`diff add`) ja `// [!code --]` eemaldatuks (`diff remove`).

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

#### `NotationFocus`

`Shikiphp\Transformer\Notation\NotationFocus` — `// [!code focus]` lisab klassi `focused`.

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

#### `NotationErrorLevel`

`Shikiphp\Transformer\Notation\NotationErrorLevel` — `// [!code error]`, `// [!code warning]` ja `// [!code info]` lisavad klassi `highlighted` ning `error` / `warning` / `info`.

```js
throwSomething() // [!code error]
maybeRisky()     // [!code warning]
```

#### `NotationWordHighlight`

`Shikiphp\Transformer\Notation\NotationWordHighlight` — `// [!code word:foo]` (valikuliselt `// [!code word:foo:2]`, et piirata mõju järgmise N reaga) ümbritseb iga `foo` esinemiskorra späniga, millel on `highlighted-word`.

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

### Meta teisendajad

Need loevad koodipiirde **meta-stringi**, mis antakse edasi valikuga [`meta`](https://shikiphp.inline0.dev/et/docs/options#meta) (`meta['__raw']`); samamoodi loeb Shiki tarastatud koodiploki keele järel olevat teksti.

#### `MetaHighlight`

`Shikiphp\Transformer\MetaHighlight` — tõstab esile meta-vahemikus nimetatud read, näiteks `{1,3-5}`, lisades klassi `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` — tõstab metastringis nimetatud sõnad esile süntaksiga `/word/`, lisades `highlighted-word`.

### Tühimärgid ja struktuur

#### `RenderWhitespace`

`Shikiphp\Transformer\RenderWhitespace` — ümbritseb tühiku- ja tabeldusmärke spännidega (vaikeklassid `space` ja `tab`), et neid saaks nähtavalt kuvada. Konstruktorile antakse `(classSpace, classTab, position)`, kus `position` on `'all'` (vaikeväärtus), `'boundary'`, `'trailing'` või `'leading'`.

#### `CompactLineOptions`

`Shikiphp\Transformer\CompactLineOptions` — rakendab kindlatele ridadele klasse `{line, classes}` kirjete loendist.

```php
use Shikiphp\Transformer\CompactLineOptions;

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

Reanumbrid algavad ühest. Anna objekt edasi valikuga `transformers`, nagu iga teisendaja puhul.

#### `RemoveNotationEscape`

`Shikiphp\Transformer\RemoveNotationEscape` — eemaldab paomärgid vormilt `[\!code …]`, mida kasutatakse sõnasõnalise märgistuskommentaari kirjutamiseks ilma märgistuse teisendajat käivitamata.

#### `RemoveLineBreak`

`Shikiphp\Transformer\RemoveLineBreak` — eemaldab ridade vahelt reavahetuse tekstisõlmed (Shiki omad `transformerRemoveLineBreak`).

### `StyleToClass`

`Shikiphp\Transformer\StyleToClass` — viib tekstisisesed stiilid genereeritud klassidesse ja kogub laaditabeli, mille saad kätte funktsiooniga `getCSS()`. Klasside nimed räsitakse stiili ja Shiki elemendi `cyrb53` põhjal, nii et väljund on bait-baidilt identne elemendi `@shikijs/transformers` 4.2.0-iga, sealhulgas selle skoobiga:

- `<pre>` stiil muutub alati klassiks.
- Märgendite spännid teisendatakse ainult siis, kui neil on eelehitatud stiil, nagu `themes` kaardi puhul. Ühe `theme` korral säilitavad märgendite spännid tekstisisese `style="color:…"`, nagu Shiki puhul.

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

Konstruktori argument on `(classPrefix, classSuffix, classReplacer)`; eesliite vaikeväärtus on `__shiki_`.
