تخطَّ إلى المحتوى

عقود طبقات محرك HTML‏ (ADR-010)

يفصل النظام الفرعي لـ ⁨HTML⁩ بين تحليل ⁨CSS⁩، وحالة النمط، والتخطيط، والطلاء ضمن أربع طبقات. تتحرك البيانات في اتجاه واحد عبر هذه الطبقات. يحدد سجل قرار المعمارية 010‏ (⁨ADR-010⁩) الحدود وقواعد التوسعة.

Terminal window
composer require nextpdf/core:^3

يضفي سجل قرار المعمارية 010‏ (⁨ADR-010⁩) (“عقود طبقات المحرك، وملكية المسار الساخن، وقواعد التوسعة”، المعتمد 2026-04-12) الصفة الرسمية على طريقة تقسيم النظام الفرعي لـ ⁨HTML⁩ إلى طبقات. يتكوّن عقد التصيير الأساسي من أربع طبقات: تحليل ⁨CSS⁩ والمُطبِّقات، وحالة النمط، والتخطيط والتنسيق، والطلاء. ويوثّق ⁨ADR-010⁩ أيضًا طبقتين ملحقتين: الوسائط المُصفَّحة وحزمة القياس. تلتف هاتان الطبقتان حول النواة رباعية الطبقات دون تغيير تدفق بياناتها. المصطلح المعتمد لهذه النواة في المسرد هو “⁨HTML pipeline⁩”، أي خط معالجة رباعي الطبقات.

تتدفق البيانات في اتجاه واحد. يتحوّل نص ⁨CSS⁩ إلى قيم مُحدَّدة النوع في الطبقة 1. تكتب الطبقة 1 هذه القيم في حقول HtmlStyleState داخل الطبقة 2. تقرأ الطبقة 3 حقول حالة النمط وتحسب الهندسة. وتقرأ الطبقة 4 لقطة ComputedStyle غير القابلة للتغيير مع الهندسة، ثم تُصدر مُعاملات ⁨PDF.⁩ لا تقرأ أي طبقة من طبقة لاحقة.

الفصل رباعي الطبقات ليس مجرد توثيق. يسجّل ⁨ADR-010⁩ عمليتَي إعادة هيكلة محدودتين طُبِّقتا في ⁨v1.2.0⁩ ونقلتا الشيفرة إلى الطبقة الصحيحة. استُخرج PageBorderPainter من HtmlParser، لذلك لم تعد مُعاملات الطلاء موجودة داخل المُنسِّق. ويحمل تعليق فئة HtmlStyleState الآن عقد الطبقات الرسمي، ويبيّن الحقول التي يجوز لكل طبقة الكتابة فيها أو القراءة منها.

يوجد حدّ صريح واحد. لا يزال FormattingContextFactory::startTable() يقرأ خمسة مفاتيح ⁨CSS⁩ خام مباشرةً. يسجّل ⁨ADR-010⁩ ذلك بوصفه دَينًا تقنيًا معروفًا ومؤجَّلًا إلى TableApplicator مستقبلي، لا بوصفه العقد المقصود. توثيق هذا الاستثناء جزء من العقد.

الطبقةالملفات (تمثيلية)تكتبتقرأيجب ألا
1 — تحليل ⁨CSS⁩ والمُطبِّقاتCssValueParser، CssResolver، HtmlCssApplicator، src/Html/Applicator/*حقول ⁨CSS⁩ في HtmlStyleStateنص ⁨CSS⁩ الخامحساب الهندسة؛ إصدار المُعاملات
2 — حالة النمطHtmlStyleState، State/ComputedStyle، State/LayoutState— (حقيبة قيم خاملة)تحليل ⁨CSS⁩؛ تحديد التخطيط؛ إصدار المُعاملات
3 — التخطيط والتنسيقFormattingContextFactory، HtmlBlockHandler، FlexLayoutEngine، TableParser، FloatContextهندسة المؤشرحقول HtmlStyleStateقراءة $css[...] الخام؛ إصدار مُعاملات الطلاء
4 — الطلاء والتصييرBorderRenderer، BackgroundImageRenderer، src/Html/Paint/*، src/Html/Gradient/*دفق مُعاملات ⁨PDF⁩ComputedStyle (غير قابل للتغيير) + الهندسةحساب الهندسة؛ تحليل ⁨CSS⁩؛ تحديد فواصل الصفحات
الطبقةالملفات (تمثيلية)الدور
5 — الوسائط المُصفَّحةPageBreakController، PageBorderPainter، PageRule، PageRuleParser، ParserConfiguratorحلّ قواعد @page؛ تقييم قيود الفصل و⁨orphan/widow⁩؛ تفويض زخرفة الصفحة إلى الطلاء.
6 — القياس وحزمة الاختبارسكربتات مُصنِّف ⁨Web Platform Tests⁩‏ (⁨WPT⁩)، tests/Support/*تصنيف نتائج الاختبارات؛ إنتاج لقطات الانحدار؛ توفير مساعِدات التحقق. لا تحمل هذه الطبقة أي منطق تصيير.

يُفرَض العقد من خلال موضع الفئة وتعليق HtmlStyleState. تحقّق منه مقابل src/Html/.

الرمزالطبقةدور العقد
PropertyApplicatorInterface1واجهة الاستراتيجية؛ الموضع الوحيد الذي يكتب حقول ⁨CSS⁩ المحسوبة.
ParserConfigurator::buildCssApplicator()1 (التوصيل)يسجّل كل مُطبِّق. تُسجَّل أي خاصية ⁨CSS⁩ جديدة هنا.
HtmlStyleState2حقيبة بمجموعتين؛ يبيّن تعليق الفئة الطبقة المالكة لكل حقل.
HtmlStyleState::toComputedStyle()2يُنتج ComputedStyle غير القابل للتغيير لطبقة الطلاء.
FormattingContextFactory::dispatchOpenTag()3نقطة توجيه واحدة لسلوك التخطيط الجديد.
PageBorderPainter::buildStream()4زخرفة الصفحة؛ يُستدعى من الطبقة 5، وليس مضمَّنًا داخل HtmlParser.

لا تتعامل مع الطبقات مباشرةً إطلاقًا. يجري تدفق الطبقات الأربع داخل استدعاء واحد.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->addPage();
$doc->writeHtml('<p style="color:#1E3A8A;border:1px solid #999;">Layered render.</p>');
$doc->save(__DIR__ . '/output/layers.pdf');

يهمّ العقد عند المساهمة، لا عند استدعاء المكتبة. لإضافة خاصية ⁨CSS⁩، استخدم نقطة توسعة الطبقة 1: أنشئ مُطبِّقًا، وأضِف حقل HtmlStyleState مُحدَّد النوع مع تعليق طبقة، وسجّل المُطبِّق في ParserConfigurator. يوضّح المثال أدناه شكل عقد المُطبِّق. استخدم src/Html/Applicator/ نموذجًا لفئة فعلية.

<?php
declare(strict_types=1);
// Layer 1 extension contract (see ADR-010 §C "New CSS property").
// A new property group ships as a PropertyApplicatorInterface
// implementation registered in ParserConfigurator::buildCssApplicator().
// It writes a typed HtmlStyleState field and never computes geometry
// or emits PDF operators — those belong to Layers 3 and 4.
  • FormattingContextFactory::startTable() يقرأ ⁨CSS⁩ الخام. هذا هو الاستثناء الوحيد الموثَّق في العقد، وهو مؤجَّل إلى TableApplicator مستقبلي. لا تنسخ هذا النمط.
  • ست طبقات، ونواة رباعية الطبقات. يرقّم ⁨ADR-010⁩ ست طبقات. عقد تدفق البيانات هو النواة رباعية الطبقات؛ أما الوسائط المُصفَّحة والقياس فهما ملحقان.
  • HtmlStyleState ثنائي المجموعات. فهو يحمل حقول ⁨CSS⁩ المحسوبة وحقول تتبّع التخطيط. المُطبِّقات وحدها تكتب مجموعة ⁨CSS.⁩ يقرأ الطلاء ComputedStyle، ولا يقرأ أبدًا حقول تتبّع التخطيط.
  • HtmlParser ليس له طبقة. فهو المُنسِّق. يجب ألا يحتوي على تحليل ⁨CSS⁩، أو حسابات الهندسة، أو إصدار الطلاء.

عقد الطبقات بنيوي، لذلك لا يضيف أي تكلفة وقت تشغيل. يُنتج HtmlStyleState::toComputedStyle() لقطة واحدة غير قابلة للتغيير لكل عنصر يحتاج إلى طلاء. تتيح هذه اللقطة لشيفرة الطلاء تجنّب حقيبة الحالة القابلة للتغيير. يحكم نموذج التدفق تكلفة التصيير، لا التقسيم إلى طبقات. يظل performance_budget لكل صفحة (wall_ms: 1500، peak_mb: 64) هو السقف التشغيلي.

يدعم فصل الطبقات نموذج الأمان. تحلّل الطبقة 1 قيم ⁨CSS⁩ وتُرشِّحها وفق السياسة قبل أن تراها شيفرة التخطيط أو الطلاء، فيبقى DefaultHtmlSecurityPolicy::isCssPropertyAllowed() البوابة الوحيدة. لا يقرأ الطلاء أبدًا ⁨CSS⁩ خامًا يتحكّم فيه مهاجم. راجع نموذج أمان وحدة ⁨HTML⁩.

لا تستشهد هذه الصفحة بأي معيار خارجي. تأتي حدود الطبقات من ⁨ADR-010⁩ وتعليق فئة HtmlStyleState، الذي يرمّز العقد في الشيفرة المصدرية. المطابقة السلوكية لـ ⁨CSS⁩ موثَّقة في ⁨css-resolver⁩.

قدرة للمؤسسات. تستخدم ميزات ⁨CSS⁩ في ⁨Premium⁩ الطبقات الأربع نفسها عبر نقاط التوسعة الموثَّقة. لا يوجد خط معالجة منفصل لـ ⁨Premium.⁩ راجع مصفوفة دعم ⁨CSS⁩.