De HTML-pijplijn
Spec: CSS Cascade 5, §6.1 CSS Cascade 5 §6.1 Spec: CSS Display 3, §2 CSS Display 3 §2 Evidence: Code-backed
In één oogopslag
Sectie met titel “In één oogopslag”NextPDF rendert HTML en CSS naar PDF binnen je PHP-proces: standaard zonder browser en zonder subproces. Deze pagina legt uit door welke gelaagde fasen de conversie loopt, wat de CSS-engine daadwerkelijk dekt en wanneer delegatie naar een echte browser-renderer de eerlijke keuze is.
Waarom dit belangrijk is
Sectie met titel “Waarom dit belangrijk is”“HTML naar PDF” klinkt als één bewerking. In werkelijkheid bestaat het uit een cascade, een boxmodel, een lay-outfase en een paintfase. Elk daarvan is een goed gespecificeerd probleem met eigen manieren waarop het mis kan gaan. Een engine die ze samensmelt tot één procedure is broos. Een wijziging in het parsen van kleuren kan een box verplaatsen, en de enige manier om dat vast te stellen is renderen en kijken.
Het in-procesmodel heeft een reëel voordeel: geen browser om te installeren, geen sandbox om te beheren en geen procesgrens waarover je data moet marshalen. Maar dat betaalt zich alleen uit als de conversie schoon genoeg is opgedeeld om elke verantwoordelijkheid afzonderlijk te testen. Die architectuur maakt “HTML renderen in PHP” betrouwbaar in plaats van alleen mogelijk.
De korte versie
Sectie met titel “De korte versie”- HTML/CSS-conversie verloopt in-process via
writeHtml(). Het resultaat is native PDF-inhoud, niet een afbeelding van een pagina. - De verwerking gebeurt in één doorgang en streamend. De tokenizer produceert een tokenlijst. De parser verwerkt die van links naar rechts, en er wordt geen volledige DOM-boom bewaard (ADR-001). Harde limieten begrenzen het aantal elementen en de nestingdiepte.
- De engine is opgebouwd uit expliciete lagen: CSS-parsing en applicators, stijlstatus, lay-out en opmaak, paint en paged media — met strikte regels over welke laag wat mag doen (ADR-010).
- De CSS-engine dekt de cascade, het boxmodel en gangbare lay-out (block, inline, tabellen, floats en meer) — substantieel, maar een afgebakende subset van wat een moderne browser implementeert.
- Wanneer je exacte browsergetrouwheid nodig hebt voor willekeurige moderne CSS, kan NextPDF via een optionele extensie delegeren naar een headless browser-renderer — een bewuste, netwerkgeïsoleerde overgang, niet het standaardpad.
Hoe NextPDF dit aanpakt
Sectie met titel “Hoe NextPDF dit aanpakt”De conversie is een reeks fasen, waarbij elke fase de getypeerde uitvoer van de vorige fase verbruikt.
- Tokenize HTML becomes an ordered token list — no retained DOM tree.
- Resolve CSS Parse styles; the cascade and applicators compute typed values.
- Style state A push/pop style stack carries computed values per nesting level.
- Layout Block, inline, table, and float geometry computed; no paint here.
- Paint Borders, backgrounds, text, and decorations emit PDF operators.
- Paged media Page-break and @page rules applied as the cursor crosses page bounds.
Twee architecturale regels maken hiervan meer dan een stroom.
Lagen hebben contracten. CSS-tekst wordt uitsluitend binnen applicatorklassen gelezen. Lay-outcode berekent geometrie, maar geeft geen paint-operators uit. Paint-code leest een onveranderlijke momentopname van de computed style, nooit de veranderlijke lay-outtrackingstatus. Paged-media-code activeert onderbrekingen, maar delegeert paginadecoratie aan de paintlaag. Deze grenzen worden afgedwongen (ADR-010). Daarom is een nieuwe CSS-eigenschap een nieuwe applicator, in plaats van een wijziging die tegelijk door de parser, de lay-outdispatch en de painter golft.
Er is geen DOM. De pijplijn werkt door een ontwerpkeuze in één doorgang en streamend (ADR-001): hooguit één stijlstatus per nestingniveau plus de actieve cursor, niet één object per element. Enkele bewerkingen hebben echt look-ahead nodig — het bepalen van tabelkolombreedtes, :has(), :last-child. Deze worden afgehandeld door begrensde pre-scan-indexstructuren over de platte tokenlijst, niet door het bewaren van een boom. Het aantal elementen en de nestingdiepte zijn hard begrensd, zodat pathologische invoer snel faalt in plaats van het geheugen uit te putten.
De CSS-engine past echte CSS-semantiek toe, geen imitatie. Concurrerende declaraties worden teruggebracht tot één waarde per eigenschap op basis van origin, importance, layer, specificiteit en volgorde — de werkelijke cascade. De lay-out volgt het boxmodel. Het type van een box en de opmaakcontext die deze creëert, bepalen hoe de box en de naastliggende in-flow-elementen worden geplaatst. De broncode van de engine is precies rond deze verantwoordelijkheden georganiseerd (cascade, box/display, flex, float, tabellen, fragmentatie). Daarom kun je over het gedrag ervan redeneren aan de hand van de specificaties, in plaats van het empirisch te ontdekken.
Wat het bewijs zegt
Sectie met titel “Wat het bewijs zegt”Deze pagina is Evidence: Code-backed . De fasen en regels zijn terug te voeren op de core-repository:
- Het in-process-toegangspunt is
writeHtml(string $html): staticinsrc/Core/Concerns/HasTextOutput.php. - Het ontwerp met één doorgang, zonder bewaarde DOM en met element- en nestinglimieten is ADR-001 en de tokenizer/parser/style-stack-code in
src/Html/. - Het gelaagde engine-contract — CSS parsing/applicators, stijlstatus, lay-out, paint, paged media — is ADR-010 en wordt weerspiegeld in de indeling van
src/Html/(bijvoorbeeldCascade/,Css/,Flex/,Float/,Fragmentation/en de applicatorklassen). - De overgang voor browserdelegatie is
writeHtmlChrome()in hetzelfde bestand, gedocumenteerd als afhankelijk van de optionele renderer-extensie plus een Chrome/Chromium-binary.
De standaarden verankeren de dekkingsbewering op een eerlijke manier. De cascade brengt concurrerende declaraties terug tot één enkele waarde per eigenschap — origin, importance, layer, specificiteit, volgorde — volgens Spec: CSS Cascade 5, §6.1 CSS Cascade 5 §6.1 , en in-flow-plaatsing volgt de regels voor box en opmaakcontext volgens Spec: CSS Display 3, §2 CSS Display 3 §2 . Even belangrijk is de grens: een feature query bestaat juist omdat niet elke processor elke feature ondersteunt, volgens Spec: CSS Conditional 5, §2 CSS Conditional 5 §2 . De CSS-engine van NextPDF is een afgebakende, op de specificatie afgestemde subset, en dat openlijk benoemen hoort bij het contract.
Praktijkvoorbeeld
Sectie met titel “Praktijkvoorbeeld”In-process renderen is één aanroep. De uitvoer is selecteerbare PDF-tekst, geen gerasterde pagina:
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('HTML Basic');$doc->addPage();
$html = <<<'HTML'<h1 style="color: #1E3A8A;">HTML Rendering in NextPDF</h1><p>NextPDF renders <strong>HTML and CSS</strong> directly into PDF pages,<em>in-process</em>.</p><ul> <li>Headings, paragraphs, bold and italic</li> <li>Lists, tables, inline styles</li></ul>HTML;
$doc->writeHtml($html);$doc->save(__DIR__ . '/html-basic.pdf');Als hetzelfde document willekeurige moderne CSS met exacte browsergetrouwheid vereiste, zou de aanroep in plaats daarvan writeHtmlChrome($html) zijn — hetzelfde document, een ander renderpad en een bewuste afhankelijkheid van de optionele browser-renderer.
Veelvoorkomend misverstand
Sectie met titel “Veelvoorkomend misverstand”Het terugkerende misverstand is dat een HTML-naar-PDF-engine “in wezen een browser is”. Dat is niet zo, en de engine pretendeert dat ook niet. Een browser is een omvangrijke, continu bijgewerkte implementatie van het volledige webplatform. De in-process engine van NextPDF is een op de specificatie afgestemde subset voor documentlay-out. Het eerlijke mentale model is “een degelijke CSS-engine voor printdocumenten”, niet “Chrome in PHP”. Wanneer je echt het volledige platform nodig hebt, is writeHtmlChrome() daarvoor bedoeld. Het is een afzonderlijk pad waarvoor je zelf kiest, met zijn eigen operationele voetafdruk, geen stille terugval.
Een tweede misverstand: aannemen dat het browserpad slechts “de pagina over het netwerk rendert”. De constructie doet juist het tegenovergestelde. De delegatie-overgang rendert altijd met geblokkeerde netwerktoegang voor subresources — geen externe afbeeldingen, lettertypen, stylesheets of frames — zodat deze geen vector voor uitgaande verzoeken kan worden. Pixelgetrouwheid, ja; open netwerk-egress, nee.
Grenzen en beperkingen
Sectie met titel “Grenzen en beperkingen”Deze pagina legt de vorm van de pijplijn uit en de keuze tussen in-process en browser. Het is geen CSS-ondersteuningsmatrix. Welke exacte eigenschappen, modules en selectors de in-process engine dekt, wordt bepaald door de code en de bijbehorende conformiteitstests, niet door dit overzicht. Die dekking evolueert. Het pad voor browserdelegatie vereist een optionele extensie en een Chrome/Chromium-binary. De configuratie, de operationele kenmerken en de interne indeling van die extensie vallen hier buiten de scope en zijn gedocumenteerd bij dat pakket. “In-process” beschrijft het standaardpad writeHtml(). Het is geen bewering dat elk renderpad een subproces vermijdt. De architecturale beweringen zijn juist op de beoordelingsdatum van deze pagina. De gezaghebbende bronnen zijn src/Html/, ADR-001 en ADR-010 in de core-repository.
De in-process CSS-engine is een Core-mogelijkheid. De overgang voor browserdelegatie is een optionele extensie, die hier alleen op het mogelijkheidsniveau wordt getoond:
| Edition | Availability |
|---|---|
| Core | Core levert de in-process HTML/CSS-engine (writeHtml). |
| Pro | Het pad voor browserdelegatie is een optionele add-on-extensie, onafhankelijk van de editieniveau. |
| Enterprise | Het pad voor browserdelegatie is een optionele add-on-extensie, onafhankelijk van de editieniveau. |
Gerelateerde documentatie
Sectie met titel “Gerelateerde documentatie”- Het pijplijnmodel — waar het HTML-inhoudspad zich bevindt in de algehele documentstroom.
- Wanneer je NextPDF niet moet gebruiken — de eerlijke grens, inclusief waar het browserpad of een ander hulpmiddel past.
- De gids voor integratiebeslissingen — kiezen tussen de in-process engine en een renderer voor je situatie.
Verklarende woordenlijst
Sectie met titel “Verklarende woordenlijst”- In-process renderen — HTML/CSS naar PDF omzetten binnen het PHP-proces, zonder browser of standaard subproces (
writeHtml()). - Eén doorgang / streamend — een tokenstream van links naar rechts verwerken zonder een volledige DOM-boom te bewaren (ADR-001).
- Cascade — het CSS-proces dat concurrerende declaraties tot één waarde per eigenschap herleidt op basis van origin, importance, layer, specificiteit en volgorde.
- Opmaakcontext — de lay-outomgeving die een box creëert en die bepaalt hoe de in-flow-inhoud ervan wordt geplaatst.
- Engine-laagcontract — de afgedwongen regelset (ADR-010) die definieert wat de parsing-, stijl-, lay-out-, paint- en paged-media-lagen elk mogen doen.
- Overgang voor browserdelegatie — het optionele
writeHtmlChrome()-pad dat rendert via een headless browser met geblokkeerde netwerktoegang voor subresources.