المحوّلات
تتيح لك المحوّلات إعادة تشكيل المخرجات المظللة في كل مرحلة — من السلسلة المصدرية الخام، مرورًا بشبكة الرموز، وصولًا إلى شجرة HAST النهائية وHTML. ينقل shikiphp نموذج المحوّلات في Shiki بخطافاته كما هي، لذا تعمل المحوّلات بالطريقة نفسها التي تعمل بها نظيراتها في JavaScript.
مرّرها عبر الخيار 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(),
],
]);
مسار المعالجة
كل محوّل كائن يطبّق Shikiphp\Transformer\Transformer.
ينفّذ المسار الخطافات بالترتيب أثناء بناء كتلة واحدة:
| الخطاف | التوقيع | التوقيت |
|---|---|---|
preprocess |
(string $code, array &$options, $context): ?string |
قبل تقسيم النص إلى رموز؛ وقد يعيد كتابة المصدر ويعدّل الخيارات |
tokens |
(array $tokens, $context): ?array |
بعد تقسيم النص إلى رموز، على شبكة 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() لإضافة أصناف إلى العناصر.
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 إلى السطر.
console.log('kept plain')
console.log('this line is highlighted') // [!code highlight]
NotationDiff
Shikiphp\Transformer\Notation\NotationDiff — يحدد // [!code ++] السطر بوصفه
مضافًا (diff add)، ويحدده // [!code --] بوصفه محذوفًا (diff remove).
console.log('old line') // [!code --]
console.log('new line') // [!code ++]
NotationFocus
Shikiphp\Transformer\Notation\NotationFocus — يضيف // [!code focus] الصنف
focused.
console.log('focus on me') // [!code focus]
NotationErrorLevel
Shikiphp\Transformer\Notation\NotationErrorLevel — تضيف // [!code error] و// [!code warning] و// [!code info] الصنف highlighted بالإضافة إلى
error / warning / info.
throwSomething() // [!code error]
maybeRisky() // [!code warning]
NotationWordHighlight
Shikiphp\Transformer\Notation\NotationWordHighlight — // [!code word:foo]
(اختياريًا // [!code word:foo:2] للحد من ذلك إلى الأسطر N التالية) يغلّف كل
ظهور لـ foo في عنصر span يحمل highlighted-word.
// [!code word:config]
const config = loadConfig()
محوّلات البيانات الوصفية
تقرأ هذه المحوّلات سلسلة البيانات الوصفية الخاصة بسياج الشيفرة، والممررة عبر الخيار
meta (meta['__raw'])، كما يقرأ Shiki
النص الذي يلي لغة كتلة شيفرة محاطة بسياج.
MetaHighlight
Shikiphp\Transformer\MetaHighlight — يبرز الأسطر المذكورة في نطاق بيانات وصفية
مثل {1,3-5}، ويضيف الصنف 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 — يبرز الكلمات المذكورة في سلسلة البيانات الوصفية
بصيغة /word/، ويضيف highlighted-word.
المسافات البيضاء والبنية
RenderWhitespace
Shikiphp\Transformer\RenderWhitespace — يغلّف محارف المسافة وعلامة الجدولة في
عناصر span (الصنفان space وtab افتراضيًا) لعرضها بوضوح.
يقبل المُنشئ (classSpace, classTab, position) حيث تكون القيمة position هي
'all' (افتراضيًا) أو 'boundary' أو 'trailing' أو 'leading'.
CompactLineOptions
Shikiphp\Transformer\CompactLineOptions — يطبّق أصنافًا على أسطر محددة
من قائمة تضم عناصر {line, classes}.
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.
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_.