Hợp đồng tầng cho bộ máy HTML (ADR-010)
Tổng quan nhanh
Phần tiêu đề “Tổng quan nhanh”Hệ thống con Hypertext Markup Language (HTML) tách phần phân tích Cascading Style Sheets (CSS), trạng thái kiểu, bố cục và tô vẽ thành bốn tầng. Dữ liệu đi theo một hướng qua các tầng này. Architecture Decision Record 010 (ADR-010) định nghĩa các ranh giới và quy tắc mở rộng.
Cài đặt
Phần tiêu đề “Cài đặt”composer require nextpdf/core:^3Tổng quan khái niệm
Phần tiêu đề “Tổng quan khái niệm”Architecture Decision Record 010 (ADR-010) (“Engine Layer Contracts, Hot Path Ownership, and Extension Rules”, được chấp thuận vào 2026-04-12) chính thức hóa mô hình phân tầng của hệ thống con HTML. Hợp đồng kết xuất cốt lõi gồm bốn tầng: phân tích CSS và applicator, trạng thái kiểu, bố cục và định dạng, và tô vẽ. ADR-010 cũng ghi lại hai tầng phụ trợ: paged media và bộ khung đo lường. Hai tầng này bao quanh lõi bốn tầng mà không làm thay đổi luồng dữ liệu của lõi. Thuật ngữ chuẩn trong bảng chú giải cho lõi là “HTML pipeline”, tức một pipeline bốn tầng.
Dữ liệu chảy theo một hướng. Văn bản CSS trở thành các giá trị có kiểu ở Tầng 1. Tầng 1 ghi các giá trị đó vào các trường HtmlStyleState ở Tầng 2. Tầng 3 đọc các trường trạng thái kiểu và tính toán hình học. Tầng 4 đọc một ảnh chụp ComputedStyle bất biến cùng với hình học, rồi phát ra các toán tử Portable Document Format (PDF). Không tầng nào đọc dữ liệu từ tầng đứng sau nó.
Việc tách bốn tầng không chỉ tồn tại trên tài liệu. ADR-010 ghi lại hai lần tái cấu trúc có giới hạn được áp dụng trong v1.2.0 để đưa mã về đúng tầng. PageBorderPainter đã được tách khỏi HtmlParser, nên các toán tử tô vẽ không còn nằm trong bộ điều phối. Docblock của lớp HtmlStyleState hiện mang hợp đồng tầng chính thức và nêu rõ từng tầng được phép ghi hoặc đọc những trường nào.
Có một ranh giới được nêu rõ. FormattingContextFactory::startTable() vẫn đọc trực tiếp năm khóa CSS thô. ADR-010 ghi nhận đây là nợ kỹ thuật đã biết, được hoãn lại cho một TableApplicator trong tương lai, chứ không phải hợp đồng dự kiến. Việc ghi lại ngoại lệ này là một phần của hợp đồng.
Bốn tầng cốt lõi
Phần tiêu đề “Bốn tầng cốt lõi”| Tầng | Tệp (tiêu biểu) | Ghi | Đọc | Không được |
|---|---|---|---|---|
| 1 — Phân tích CSS & applicator | CssValueParser, CssResolver, HtmlCssApplicator, src/Html/Applicator/* | HtmlStyleState — các trường CSS | Văn bản CSS thô | Tính toán hình học; phát ra toán tử |
| 2 — Trạng thái kiểu | HtmlStyleState, State/ComputedStyle, State/LayoutState | — (túi giá trị thụ động) | — | Phân tích CSS; quyết định bố cục; phát ra toán tử |
| 3 — Bố cục & định dạng | FormattingContextFactory, HtmlBlockHandler, FlexLayoutEngine, TableParser, FloatContext | Hình học con trỏ | HtmlStyleState — các trường | Đọc $css[...] thô; phát ra toán tử tô vẽ |
| 4 — Tô vẽ & kết xuất | BorderRenderer, BackgroundImageRenderer, src/Html/Paint/*, src/Html/Gradient/* | Luồng toán tử PDF | ComputedStyle (bất biến) + hình học | Tính toán hình học; phân tích CSS; quyết định ngắt trang |
Hai tầng phụ trợ
Phần tiêu đề “Hai tầng phụ trợ”| Tầng | Tệp (tiêu biểu) | Vai trò |
|---|---|---|
| 5 — Paged media | PageBreakController, PageBorderPainter, PageRule, PageRuleParser, ParserConfigurator | Phân giải các quy tắc @page; đánh giá các ràng buộc ngắt trang và orphan/widow; ủy quyền phần trang trí trang cho tầng tô vẽ. |
| 6 — Đo lường & bộ khung | Các script phân loại Web Platform Tests (WPT), tests/Support/* | Phân loại kết quả kiểm thử; tạo ảnh chụp hồi quy; cung cấp các hàm hỗ trợ assertion. Không chứa logic kết xuất. |
Bề mặt API
Phần tiêu đề “Bề mặt API”Hợp đồng được thực thi qua cách bố trí lớp và docblock HtmlStyleState. Hãy kiểm chứng hợp đồng dựa trên src/Html/.
| Ký hiệu | Tầng | Vai trò hợp đồng |
|---|---|---|
PropertyApplicatorInterface | 1 | Interface chiến lược; nơi duy nhất ghi các trường CSS đã được tính toán. |
ParserConfigurator::buildCssApplicator() | 1 (đấu nối) | Đăng ký mọi applicator. Một thuộc tính CSS mới được đăng ký tại đây. |
HtmlStyleState | 2 | Túi gồm hai nhóm; docblock của lớp nêu rõ tầng sở hữu của từng trường. |
HtmlStyleState::toComputedStyle() | 2 | Tạo ra ComputedStyle bất biến cho tầng tô vẽ. |
FormattingContextFactory::dispatchOpenTag() | 3 | Điểm định tuyến duy nhất cho hành vi bố cục mới. |
PageBorderPainter::buildStream() | 4 | Trang trí trang; được gọi từ Tầng 5, không được nội tuyến trong HtmlParser. |
Mẫu mã — Bắt đầu nhanh
Phần tiêu đề “Mẫu mã — Bắt đầu nhanh”Bạn không bao giờ chạm trực tiếp vào các tầng. Luồng bốn tầng chạy bên trong một lệnh gọi duy nhất.
<?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');Mẫu mã — Sản xuất
Phần tiêu đề “Mẫu mã — Sản xuất”Hợp đồng này quan trọng khi bạn đóng góp mã, chứ không phải khi bạn gọi thư viện. Để thêm một thuộc tính CSS, hãy dùng điểm mở rộng của Tầng 1: tạo một applicator, thêm một trường HtmlStyleState có kiểu kèm docblock tầng, rồi đăng ký applicator trong ParserConfigurator. Minh họa bên dưới cho thấy hình dạng của hợp đồng applicator. Hãy dùng src/Html/Applicator/ làm mẫu cho một lớp cụ thể.
<?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.Trường hợp đặc biệt & điểm cần lưu ý
Phần tiêu đề “Trường hợp đặc biệt & điểm cần lưu ý”FormattingContextFactory::startTable()đọc CSS thô. Đây là ngoại lệ hợp đồng duy nhất được ghi lại, được hoãn lại cho mộtTableApplicatortrong tương lai. Đừng sao chép khuôn mẫu này.- Sáu tầng, lõi bốn tầng. ADR-010 đánh số sáu tầng. Hợp đồng luồng dữ liệu là lõi bốn tầng; paged media và đo lường là các tầng phụ trợ.
HtmlStyleStatecó hai nhóm. Nó mang các trường CSS đã được tính toán và các trường theo dõi bố cục. Chỉ các applicator mới ghi vào nhóm CSS. Tô vẽ đọcComputedStyle, không bao giờ đọc các trường theo dõi bố cục.HtmlParserkhông có tầng. Nó là bộ điều phối. Việc phân tích CSS, tính toán hình học và phát ra tô vẽ không được nằm trong nó.
Hiệu năng
Phần tiêu đề “Hiệu năng”Hợp đồng tầng mang tính cấu trúc, nên không làm tăng chi phí thời gian chạy. HtmlStyleState::toComputedStyle() tạo ra một ảnh chụp bất biến cho mỗi phần tử cần tô vẽ. Ảnh chụp đó giúp mã tô vẽ tránh túi trạng thái có thể thay đổi. Chi phí kết xuất do mô hình streaming chi phối, chứ không phải do việc phân tầng. performance_budget trên mỗi trang (wall_ms: 1500, peak_mb: 64) vẫn là trần vận hành.
Ghi chú bảo mật
Phần tiêu đề “Ghi chú bảo mật”Việc tách tầng hỗ trợ mô hình bảo mật. Tầng 1 phân tích và lọc các giá trị CSS theo chính sách trước khi mã bố cục hay tô vẽ nhìn thấy chúng, nên DefaultHtmlSecurityPolicy::isCssPropertyAllowed() vẫn là cổng duy nhất. Tô vẽ không bao giờ đọc CSS thô do kẻ tấn công kiểm soát. Xem mô hình bảo mật của module HTML.
Tuân thủ
Phần tiêu đề “Tuân thủ”Trang này không trích dẫn tiêu chuẩn bên ngoài nào. Các ranh giới tầng đến từ ADR-010 và docblock của lớp HtmlStyleState, nơi mã hóa hợp đồng trong mã nguồn. Mức tuân thủ hành vi CSS được ghi lại tại css-resolver.
Bối cảnh thương mại
Phần tiêu đề “Bối cảnh thương mại”Khả năng Enterprise. Các tính năng CSS của Premium sử dụng chính bốn tầng này thông qua các điểm mở rộng đã được ghi lại. Không có pipeline Premium riêng biệt. Xem ma trận hỗ trợ CSS.