HTML-weergavepijplijn
In één oogopslag
Sectie met titel “In één oogopslag”Bij een aanroep van writeHtml() wordt één voorwaartse doorgang over HyperText Markup Language (HTML) uitgevoerd: invoer tokeniseren, @page en stijlen oplossen, inhoud opmaken en Portable Document Format (PDF)-operatoren weergeven. Tussen de fasen wordt geen elementenboom bewaard.
Installatie
Sectie met titel “Installatie”composer require nextpdf/core:^3Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”De HTML-weergavepijplijn zet HTML+CSS, oftewel HTML plus Cascading Style Sheets (CSS), in één voorwaartse doorgang om naar PDF-contentstreamoperatoren. Er wordt geen blijvende documentboom opgebouwd. De onderstaande fasen weerspiegelen HtmlParser::parse() op main.
Fase 1 — Opschonen en normaliseren. HtmlParser::parse() weigert invoer groter dan 10 MB, verwijdert stuurtekens en normaliseert regeleinden: zowel CRLF als losse CR worden LF, conform de HTML-regeleindenormalisatie in de bron. Vervolgens worden alle instantievelden teruggezet, zodat status uit een eerdere aanroep niet kan doorwerken.
Fase 2 — @page- en stijlblokken extraheren. De parser extraheert eerst <style>-blokken en past daarna de gevonden @page-regels toe om de paginageometrie opnieuw in te stellen. Dit gebeurt voordat er tokens worden verwerkt, omdat de paginagrootte elke latere lay-outbeslissing beïnvloedt.
Fase 3 — Tokeniseren. HtmlTokenizer::cleanHtml() normaliseert witruimte, maar behoudt <pre>-inhoud. tokenize() produceert vervolgens een platte list<HtmlToken>. Dit is een tokenlijst, geen knooppuntgraaf. De pijplijn verwijdert teksttokens die alleen uit witruimte bestaan meteen. HtmlChildScanner::scan() bouwt indexmappen (aantallen onderliggende elementen, aantallen tags, leegheid) over de platte lijst, zodat structurele selectors geen boom nodig hebben.
Fase 4 — Optionele :has()-voorscan. Wanneer de experimentele functie css.has is ingeschakeld, voert CssResolver::resolveHasSelectors() één begrensde voorscan over de tokenlijst uit om de relationele selector op te lossen. Deze gedocumenteerde, begrensde stap is de uitzondering op de regel van één doorgang.
Fase 5 — Tokens verwerken (stijl, lay-out, weergave). HtmlParser::processTokens() doorloopt de tokenlijst eenmaal. Voor elk element lost het de cascade op (applicators van Laag 1 schrijven naar HtmlStyleState), berekent het de geometrie (lay-out van Laag 3) en zendt het PDF-operatoren uit (weergave van Laag 4). Stijlovererving gebruikt een HtmlStyleState-stack met push en pop. De cursor (x, y, marges, streamoffset) wordt tussen handlers verplaatst via HtmlBlockCursor-momentopnamen.
Fase 6 — Het resultaat retourneren. parse() retourneert een onveranderlijke HtmlRenderResult met de uitgezonden contentstream, de eindpositie van de cursor en de gebruikte lettertypesleutels. De aanroeper (writeHtml()) zet de cursor terug naar het paginacoördinatenstelsel.
Zie voor de scheiding in vier lagen binnen Fase 5 de pagina laagcontracten. Zie voor de eigenschap zonder bewaarde boom en de bijbehorende limieten de pagina streamingbeperkingen.
API-oppervlak
Sectie met titel “API-oppervlak”| Symbool | Locatie | Fase |
|---|---|---|
Document::writeHtml(string $html): static | src/Core/Concerns/HasTextOutput.php | Openbaar toegangspunt |
HtmlParser::parse(string $html): HtmlRenderResult | src/Html/HtmlParser.php | Orkestreert alle fasen |
HtmlTokenizer::cleanHtml() / tokenize() | src/Html/HtmlTokenizer.php | Fase 3 |
HtmlChildScanner::scan() | src/Html/HtmlChildScanner.php | Indexmappen van Fase 3 |
CssResolver::resolveHasSelectors() | src/Html/CssResolver.php | Fase 4 (afgeschermd) |
HtmlRenderResult (stream, endX, endY, usedFontKeys) | src/Html/HtmlRenderResult.php | Fase 6 |
Codevoorbeeld — Snelstart
Sectie met titel “Codevoorbeeld — Snelstart”Afkomstig uit examples/08-html-basic.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();$doc->writeHtml('<h1 style="color:#1E3A8A;">HTML Rendering</h1><p>One pass.</p>');$doc->save(__DIR__ . '/output/08-html-basic.pdf');Codevoorbeeld — Productie
Sectie met titel “Codevoorbeeld — Productie”Geef een opgemaakt rapport weer met een ingesloten <style>-blok. De pijplijn extraheert het stijlblok en past het toe voordat er tokens worden verwerkt.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Exception\HtmlParsingException;
function renderInvoice(string $bodyHtml, string $out): void{ $doc = Document::createStandalone(); $doc->setTitle('Invoice'); $doc->addPage();
$html = '<style>@page { margin: 20mm; } ' . 'h1 { color: #1E3A8A; } ' . 'table { width: 100%; }</style>' . $bodyHtml;
try { $doc->writeHtml($html); } catch (HtmlParsingException $e) { // Sanitize/cap failures surface here. Do not retry. throw $e; }
$doc->save($out);}Randgevallen en valkuilen
Sectie met titel “Randgevallen en valkuilen”@pagewordt vóór de tokens gelezen. Een@page-regel na de inhoud is nog steeds van toepassing, omdat stijlextractie vóór tokenisatie plaatsvindt. De paginageometrie ligt vóór Fase 5 vast.<pre>-witruimte blijft behouden.cleanHtml()beschermt<pre>-inhoud; de pijplijn laat witruimte elders ineenklappen.:has()is afgeschermd. Als de experimentele functiecss.hasniet is ingeschakeld, wordt Fase 4 niet uitgevoerd en komen:has()-selectors niet overeen.- Eén streambuffer. De pijplijn schrijft naar één stringbuffer. Reeds geschreven inhoud wordt nooit verplaatst. Er vindt geen herindeling plaats.
- Limieten gelden tijdens de doorgang. De element- en nestingslimieten werpen een uitzondering op tijdens Fase 5, niet ervoor. Een document kan halverwege mislukken.
Prestaties
Sectie met titel “Prestaties”De pijplijn doorloopt in O(aantal tokens). Het bepalen van de kolombreedte van tabellen voegt per tabel een begrensde rijscan toe (Fase 5, TableParser). Wanneer ingeschakeld, voegt de :has()-voorscan één begrensde doorgang over de tokenlijst toe (Fase 4). Het geheugen is O(nestingsdiepte) voor de stijlstack, niet O(aantal elementen); zie streamingbeperkingen. De prestatiebenchmark van de HTML-weergavepijplijn beschermt tegen regressies met een drempel van 5% (samengevoegd werk, PR #564). Het performance_budget per pagina (wall_ms: 1500, peak_mb: 64) is het operationele plafond.
Beveiligingsopmerkingen
Sectie met titel “Beveiligingsopmerkingen”Fase 1 is de eerste beveiligingsgrens: de invoerlimiet van 10 MB, het verwijderen van stuurtekens en de regeleindenormalisatie worden alle vóór tokenisatie uitgevoerd. Tijdens Fase 5 schermt DefaultHtmlSecurityPolicy de toegestane tags, attributen, CSS-eigenschappen en URL-schema’s af. Zie het beveiligingsmodel van de HTML-module.
Conformiteit
Sectie met titel “Conformiteit”De regeleindenormalisatie volgt de regeleindeafhandeling van de HTML-standaard: CRLF en losse CR worden LF. CSS-conformiteit per eigenschap is gedocumenteerd in de CSS-ondersteuningsmatrix, en cascadegedrag is gedocumenteerd op css-resolver. Deze pagina herhaalt de ondersteuning per eigenschap niet.
Commerciële context
Sectie met titel “Commerciële context”Enterprise-mogelijkheid. Premium verbreedt de CSS-dekking op dezelfde pijplijn. De volgorde van zes fasen verandert niet tussen edities. Zie de CSS-ondersteuningsmatrix.