Transformatoare
Transformatoarele vă permit să remodelați rezultatul evidențiat în fiecare etapă — de la șirul sursă brut, prin grila de tokenuri, până la arborele HAST final și HTML. shikiphp preia modelul de transformatoare al Shiki hook cu hook, astfel încât transformatoarele se comportă la fel ca omoloagele lor JavaScript.
Transmiteți-le prin opțiunea transformers:
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(),
],
]);
Procesul de lucru
Fiecare transformator este un obiect care implementează Shikiphp\Transformer\Transformer.
Fluxul execută hook-urile în ordine, pe parcursul construirii unui singur bloc:
| Hook | Semnătură | Când |
|---|---|---|
preprocess |
(string $code, array &$options, $context): ?string |
înainte de tokenizare; poate rescrie sursa și modifica opțiunile |
tokens |
(array $tokens, $context): ?array |
după tokenizare, asupra grilei 2D ThemedToken |
root |
(Element $el, $context): ?Element |
asupra rădăcinii HAST |
pre |
(Element $el, $context): ?Element |
asupra elementului <pre> |
code |
(Element $el, $context): ?Element |
asupra elementului <code> |
line |
(Element $el, int $line, $context): ?Element |
pentru fiecare element de linie (începând de la 1) |
span |
(Element $el, int $line, int $col, Element $lineEl, ThemedToken $token, $context): ?Element |
pentru fiecare interval de token |
postprocess |
(string $html, array $options, $context): ?string |
asupra șirului HTML serializat final |
Toate hook-urile sunt opționale. Returnarea unei valori înlocuiește intrarea; returnarea lui null
o păstrează neschimbată.
enforce() controlează ordinea transformatoarelor: 'pre' rulează primul, 'post'
rulează ultimul, iar null (valoarea implicită) rulează între acestea, în ordinea înregistrării.
Scrierea unui transformator
Extindeți Shikiphp\Transformer\AbstractTransformer pentru a suprascrie doar hook-urile
necesare; restul nu fac nimic. Contextul transformatorului expune
addClassToHast() pentru adăugarea claselor la elemente.
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" …>
Transformatoare incluse
Transformatoare de notație
Acestea citesc comentarii speciale // [!code …] din sursă (sintaxa comentariilor
limbii este detectată automat) și le transformă în clase,
eliminând comentariul propriu-zis. Sunt portări directe ale setului de
notație @shikijs/transformers.
NotationHighlight
Shikiphp\Transformer\Notation\NotationHighlight — // [!code highlight] (sau
// [!code hl]) adaugă clasa highlighted liniei respective.
console.log('kept plain')
console.log('this line is highlighted') // [!code highlight]
NotationDiff
Shikiphp\Transformer\Notation\NotationDiff — // [!code ++] marchează o linie ca
adăugată (diff add), iar // [!code --] ca ștearsă (diff remove).
console.log('old line') // [!code --]
console.log('new line') // [!code ++]
NotationFocus
Shikiphp\Transformer\Notation\NotationFocus — // [!code focus] adaugă clasa
focused.
console.log('focus on me') // [!code focus]
NotationErrorLevel
Shikiphp\Transformer\Notation\NotationErrorLevel — // [!code error],
// [!code warning] și // [!code info] adaugă clasa highlighted plus
error / warning / info.
throwSomething() // [!code error]
maybeRisky() // [!code warning]
NotationWordHighlight
Shikiphp\Transformer\Notation\NotationWordHighlight — // [!code word:foo]
(opțional // [!code word:foo:2] pentru a limita la următoarele N linii) încadrează fiecare
apariție a foo într-un span care conține highlighted-word.
// [!code word:config]
const config = loadConfig()
Transformatoare meta
Acestea citesc șirul meta al blocului de cod, furnizat prin opțiunea
meta (meta['__raw']), așa cum Shiki citește
textul de după limbajul unui bloc de cod delimitat.
MetaHighlight
Shikiphp\Transformer\MetaHighlight — evidențiază liniile specificate într-un interval meta
precum {1,3-5}, adăugând clasa highlighted.
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 — evidențiază cuvintele specificate în șirul meta
cu sintaxa /word/, adăugând highlighted-word.
Spații albe și structură
RenderWhitespace
Shikiphp\Transformer\RenderWhitespace — încadrează caracterele spațiu și tabulație în
span-uri (clasele space și tab în mod implicit), astfel încât să poată fi redate vizibil.
Constructorul primește (classSpace, classTab, position), unde position este
'all' (implicit), 'boundary', 'trailing' sau 'leading'.
CompactLineOptions
Shikiphp\Transformer\CompactLineOptions — aplică clase unor linii specifice
dintr-o listă de intrări {line, classes}.
use Shikiphp\Transformer\CompactLineOptions;
$transformer = new CompactLineOptions([
['line' => 1, 'classes' => 'highlighted'],
['line' => 3, 'classes' => ['highlighted', 'error']],
]);
Numerotarea liniilor începe de la 1. Transmiteți obiectul în opțiunea transformers, ca orice
alt transformator.
RemoveNotationEscape
Shikiphp\Transformer\RemoveNotationEscape — elimină escape-ul din forma [\!code …]
folosită pentru a scrie un comentariu de notație literală fără a declanșa un transformator
de notație.
RemoveLineBreak
Shikiphp\Transformer\RemoveLineBreak — elimină nodurile text cu întrerupere de linie
dintre linii (transformerRemoveLineBreak din Shiki).
StyleToClass
Shikiphp\Transformer\StyleToClass — mută stilurile inline în clase generate
și colectează o foaie de stiluri pe care o preluați cu getCSS(). Numele claselor hash-uiesc stilul
cu Shiki al cyrb53, astfel încât rezultatul este identic la nivel de octeți cu 4.2.0
@shikijs/transformers, inclusiv domeniul său de aplicare:
- Stilul
<pre>devine întotdeauna o clasă. - Span-urile tokenurilor sunt convertite doar când au un stil predefinit, ceea ce se
întâmplă cu o mapare
themes. Cu un singurtheme, span-urile tokenurilor își păstrează stilul inlinestyle="color:…", la fel ca în Shiki.
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
Constructorul primește (classPrefix, classSuffix, classReplacer); prefixul implicit
este __shiki_.