Ga naar inhoud

HTML naar een PDF-pagina renderen

Gebruik writeHtml() om een Hypertext Markup Language (HTML)- en Cascading Style Sheets (CSS)-fragment te renderen als pagina-inhoud in Portable Document Format (PDF). Geef opmaak mee en NextPDF rendert een opgemaakte pagina. De volledige, uitvoerbare versie van deze code staat in examples/08-html-basic.php. Volg de onderstaande stappen of kopieer het voorbeeld rechtstreeks.

NextPDF leest je HTML één keer en streamt het resultaat rechtstreeks naar de pagina. Dit is een single-pass streaming-pijplijn. Je hoeft dat model niet te begrijpen om dit recipe te gebruiken. Houd het wel in gedachten, want het verklaart een aantal regels verderop op deze pagina.

Terminal window
composer require nextpdf/core:^3

Deze opdracht installeert het pakket nextpdf/core. De voorbeelden op deze pagina draaien op PHP 8.4 en de ondersteunde runtime is >=8.4 <9.0.

writeHtml() neemt een HTML-string en tekent die op de huidige pagina, beginnend bij de huidige cursorpositie. In de engine scant NextPDF je HTML één keer en splitst die op in tokens (HtmlTokenizer). Vervolgens doorloopt NextPDF die lijst van links naar rechts (HtmlParser). Voor elk element schrijft de engine de bijbehorende PDF-tekeninstructies, content-stream-operators genoemd, naar een buffer. De engine bouwt geen elementenboom op en bewaart er ook geen in het geheugen tussen aanroepen. Dit bewuste ontwerp is het single-pass streaming-model dat is vastgelegd in ADR-001.

Elk ondersteund blokelement wordt een lay-outvak en elke tekstreeks wordt een text-show-operator. Stijlen uit inline style-attributen en een <style>-blok worden opgelost via de CSS-cascade: de regels die bepalen welke stijl wint wanneer er meer dan één van toepassing is. Tekstterugloop, uitlijning en spatiëring volgen het CSS Text-model, dat definieert hoe brontekst opgemaakte, afgebroken tekst wordt (W3C CSS Text Level 3).

Als je geen lettertype kiest, gebruikt de hoofdtekst een standaardlettertype. Dat standaardlettertype is een standaard Type 1-lettertype, een van de 14 standaardlettertypen die in ISO 32000-2 worden genoemd. De standaard verandert alleen wanneer je je eigen lettertype registreert en selecteert, of wanneer een conformiteitsprofiel vereist dat NextPDF een vervanger insluit.

Houd hier vanaf het begin rekening mee: NextPDF ondersteunt een subset van HTML en CSS, niet alles van beide. Dit recipe behandelt de ondersteunde subset. Het claimt geen volledige HTML- of volledige CSS-ondersteuning. Raadpleeg de CSS-ondersteuningsmatrix voor de exacte, geverifieerde status van elke module.

De methodesignatuur is writeHtml(string $html): static. Deze is gedeclareerd op de interface NextPDF\Contracts\PdfDocumentInterface en geïmplementeerd in NextPDF\Core\Concerns\HasTextOutput. De methode rendert op de huidige pagina en maakt er een voor je aan als er nog geen pagina bestaat. De volledige PHPDoc-tabel voor de methode wordt gegenereerd uit de broncode.

<?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>HTML Rendering in NextPDF</h1><p>Rendered with <strong>writeHtml()</strong>.</p>');
$doc->save(__DIR__ . '/out.pdf');

Dit volledige, op zichzelf staande voorbeeld is het voorbeeld dat het testframework uitvoert. Het komt overeen met examples/08-html-basic.php. In plaats van een uitvoerpad hard te coderen, schrijft het naar het pad dat het framework aanlevert. Daardoor kan het reproduceerbaarheidsframework het script twee keer uitvoeren en de resultaten vergelijken.

<?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 content</strong> directly into PDF pages.
This is the recommended approach for <em>mixed formatting</em>.</p>
<h2>Supported elements</h2>
<ul>
<li>Headings (h1-h6)</li>
<li>Paragraphs with <strong>bold</strong> and <em>italic</em></li>
<li>Ordered and unordered lists</li>
<li>Tables with borders and alignment</li>
<li>Inline styles (color, font-size, margin)</li>
</ul>
<h2>Ordered list</h2>
<ol>
<li>Create a Document instance</li>
<li>Add pages and content</li>
<li>Call save() or output()</li>
</ol>
HTML;
$doc->writeHtml($html);
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script twice.
// Honour it: do not hard-code a path, do not echo the PDF to STDOUT.
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');
$doc->save($out !== false ? $out : __DIR__ . '/render-html-to-pdf.pdf');
echo "Wrote render-html-to-pdf.pdf\n";

Verwachte STDOUT:

Wrote render-html-to-pdf.pdf
  • Cursoroverdracht. writeHtml() verplaatst de cursor naar het einde van de gerenderde inhoud. Een volgende cell() of tweede writeHtml() gaat vanaf daar verder, niet vanaf de bovenkant van de pagina.
  • Nog geen pagina. Als er geen pagina bestaat, voegt writeHtml() er vóór het renderen een toe. Roep eerst addPage() aan wanneer je een specifiek paginaformaat moet instellen.
  • Element- en nestinglimieten. De streaming-engine handhaaft een limiet van 50,000 elementen en een nestinglimiet van 100 niveaus (ADR-001). Een document dat een van beide limieten overschrijdt, wordt geweigerd in plaats van stilzwijgend afgekapt.
  • Niet-ondersteunde opmaak. Elementen en eigenschappen buiten de ondersteunde subset worden genegeerd of vallen terug op standaardgedrag; ze veroorzaken geen fouten. Controleer de dekking aan de hand van de CSS-ondersteuningsmatrix voordat je op een eigenschap vertrouwt.
  • Externe bronnen. Externe afbeeldingen en stylesheets volgen het beleid voor externe bronnen; het standaardbeleid haalt geen willekeurige externe URL’s op.

Tokenisatie en rendering gebeuren in één doorgang over je invoer, dus de kosten groeien lineair met het aantal tokens, O(n). Het standaardbudget voor dit recipe is wall_ms: 1500, peak_mb: 96. Omdat de engine de uitvoer streamt en geen Document Object Model (DOM) in het geheugen houdt, volgt het piekgeheugen de content-stream-buffer en de actieve stijlstack, niet de volledige documentgrootte.

Fragment uit de CSS-ondersteuningsmatrix (alleen geverifieerde rijen)

Sectie met titel “Fragment uit de CSS-ondersteuningsmatrix (alleen geverifieerde rijen)”

Dit fragment bevat alleen rijen met de beoordeling Verified in de op juistheid gecontroleerde CSS-ondersteuningsmatrix. „Verified” betekent dat er een src/Html/-implementatie is en een substantiële, specifieke fixture-suite die onder het structurele profiel deterministisch slaagt.

W3C-moduleNiveauStatusBewijs
CSS Flexible Box Layout (css_flexbox_1)1Geverifieerdsrc/Html/Flex/, tests/Unit/Html/Flex/
CSS Grid Layout (css_grid_1)1Geverifieerdsrc/Html/Grid/, WPT-corpus
CSS Cascading and Inheritance (css_cascade_3)3Geverifieerdsrc/Html/Cascade/, tests/Unit/Html/Cascade/
CSS Table (css_tables_3)3Geverifieerdsrc/Html/Table/, table-fixtures + golden PDF’s
CSS Fonts (css_fonts_4)4Geverifieerdsrc/Html/FontFace/, tests/Unit/Html/FontFace/

Eigenschappen zoals text-align, text-indent en color krijgen in de matrix de beoordeling „Claimed” (geïmplementeerd, maar zonder specifieke modulefixture), dus ze worden hier niet als Verified vermeld.

De HTML-engine behoudt geen DOM. De toestand bestaat uit een scalaire cursor plus een push/pop-stijlstack; tekstknooppunten die alleen uit witruimte bestaan, worden bij tokenisatie verwijderd. Een gevolg is dat een later element een eerder element niet opnieuw kan opmaken, en dat selectors die context van de volledige boom nodig hebben (bijvoorbeeld complexe :has()-gevallen) volgens ADR-006 worden beperkt. Plan een lay-out die alleen afhankelijk is van de documentvolgorde.

Parsing, lay-out en paint zijn afzonderlijke lagen. De parser zendt geen ruwe paint-operators uit en de lay-outdispatch parseert geen CSS. Wie die grenzen overschrijdt, creëert precies de koppelingsschuld die ADR-010 verbiedt. Voor recipeauteurs betekent dit dat het publieke toegangspunt writeHtml() is. Grijp niet in op de interne onderdelen van de parser.

Volgens ADR-020 mogen container-scoped opmaakcontexten (flex, table) een tijdelijke subboom opbouwen, begrensd tot 5,000 knooppunten per context, 20 niveaus diep, met een plafond voor actief geheugen van 50 MB over alle actieve contexten en 10 nestingniveaus. Buiten die contexten houdt het streaming-model geen boom vast. Houd afzonderlijke tabellen en flex-containers binnen de knooppuntgrens voor voorspelbaar geheugengebruik.

Behandel HTML-invoer als niet-vertrouwd. NextPDF voert geen scripts uit en het standaardbeleid voor externe bronnen haalt geen willekeurige externe URL’s op, dus de engine zelf is behoudend. Valideer of saneer toch alle HTML die je uit gebruikersinvoer samenstelt voordat je deze rendert. De element- en nestinglimieten beschermen je eveneens: ze begrenzen hoeveel werk een vijandig of misvormd document kan vergen.

VerklaringSpecClausulereference_id
CSS Text bepaalt de omzetting van brontekst in opgemaakte, afgebroken tekst.W3C CSS Text Level 3css_text_3#x1.x2.p4
Het standaardlettertype voor de hoofdtekst wordt herleid tot een standaard Type 1-lettertype.ISO 32000-2iso32000_2_sec9#x1.x29

Dit recipe laat zien hoe NextPDF een ondersteunde HTML- en CSS-subset rendert. Het claimt geen volledige HTML- of volledige CSS-ondersteuning. De geverifieerde status per module staat in de CSS-ondersteuningsmatrix.

Niet van toepassing.