Renderizar HTML em uma página PDF
Visão geral
Seção intitulada “Visão geral”Use writeHtml() para renderizar um fragmento de Hypertext Markup Language (HTML) e Cascading Style Sheets (CSS) como conteúdo de página em Portable Document Format (PDF). Forneça a marcação, e o NextPDF renderiza uma página formatada. A versão completa e executável deste código está em examples/08-html-basic.php. Siga as etapas abaixo ou copie o exemplo diretamente.
O NextPDF lê o HTML uma vez e transmite o resultado diretamente para a página. Este é um pipeline de streaming de passagem única. Você não precisa entender esse modelo para usar esta receita. Ainda assim, vale mantê-lo em mente, porque ele explica algumas regras mais adiante nesta página.
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3Este comando instala o pacote nextpdf/core. Os exemplos desta página são executados em PHP 8.4, e o runtime compatível é >=8.4 <9.0.
Visão conceitual
Seção intitulada “Visão conceitual”writeHtml() recebe uma string HTML e a desenha na página atual, começando pela posição atual do cursor. Internamente, o NextPDF varre o HTML uma vez e o divide em tokens (HtmlTokenizer). Em seguida, percorre essa lista da esquerda para a direita (HtmlParser). Para cada elemento, escreve em um buffer as instruções de desenho PDF correspondentes, chamadas de operadores de fluxo de conteúdo (content-stream operators). O mecanismo nunca constrói nem mantém uma árvore de elementos na memória entre chamadas. Esse design deliberado é o modelo de streaming de passagem única registrado no ADR-001.
Cada elemento de bloco suportado se torna uma caixa de layout, e cada trecho de texto se torna um operador de exibição de texto (text-show operator). Os estilos de atributos style inline e de um bloco <style> são resolvidos pela cascata CSS, ou seja, pelas regras que decidem qual estilo prevalece quando mais de um se aplica. A quebra de texto, o alinhamento e o espaçamento seguem o modelo CSS Text, que define como o texto de origem se transforma em texto formatado e quebrado em linhas (W3C CSS Text Level 3).
Se você não escolher uma fonte, o texto do corpo usa uma face padrão. Esse padrão é uma fonte Type 1 padrão, uma das 14 fontes padrão nomeadas na ISO 32000-2. Ele só muda quando você registra e seleciona a sua própria fonte, ou quando um perfil de conformidade exige que o NextPDF incorpore uma substituta.
Defina essa expectativa desde o início: o NextPDF suporta um subconjunto de HTML e CSS, não a totalidade de nenhum dos dois. Esta receita cobre o subconjunto suportado. Ela não afirma suporte completo a HTML nem a CSS. Para ver o status exato e verificado de cada módulo, consulte a matriz de suporte a CSS.
Superfície da API
Seção intitulada “Superfície da API”A assinatura do método é writeHtml(string $html): static. Ele é declarado na interface NextPDF\Contracts\PdfDocumentInterface e implementado em NextPDF\Core\Concerns\HasTextOutput. O método renderiza na página atual e cria uma para você caso ainda não exista nenhuma. A tabela PHPDoc completa do método é gerada a partir do código-fonte.
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”<?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');Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”Este exemplo completo e autossuficiente é o que o harness de testes executa. Ele espelha examples/08-html-basic.php. Em vez de codificar um caminho de saída fixo, ele grava no caminho fornecido pelo harness. Isso permite que o harness de reprodutibilidade execute o script duas vezes e compare os resultados.
<?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";STDOUT esperado:
Wrote render-html-to-pdf.pdfCasos extremos & pegadinhas
Seção intitulada “Casos extremos & pegadinhas”- Transferência do cursor.
writeHtml()move o cursor para o fim do conteúdo renderizado. Umcell()seguinte ou um segundowriteHtml()continua a partir desse ponto, não do topo da página. - Ainda sem página. Se não existir nenhuma página,
writeHtml()adiciona uma antes de renderizar. ChameaddPage()primeiro quando você precisar definir um tamanho de página específico. - Limites de elementos e de aninhamento. O mecanismo de streaming impõe um limite de
50,000elementos e um limite de aninhamento de 100 níveis (ADR-001). Um documento que excede qualquer um desses limites é rejeitado, em vez de ser truncado silenciosamente. - Marcação não suportada. Elementos e propriedades fora do subconjunto suportado são ignorados ou usam um fallback; eles não geram erros. Verifique a cobertura na matriz de suporte a CSS antes de depender de uma propriedade.
- Recursos externos. Imagens e folhas de estilo remotas seguem a política de recursos externos; a política padrão não busca URLs remotas arbitrárias.
Desempenho
Seção intitulada “Desempenho”A tokenização e a renderização acontecem em uma única passagem pela entrada, então o custo cresce linearmente com o número de tokens, O(n). O orçamento padrão para esta receita é wall_ms: 1500, peak_mb: 96. Como o mecanismo transmite a saída e não mantém nenhum Document Object Model (DOM) na memória, o pico de memória acompanha o buffer de fluxo de conteúdo e a pilha de estilos ativa, não o tamanho total do documento.
Trecho da matriz de suporte a CSS (apenas linhas verificadas)
Seção intitulada “Trecho da matriz de suporte a CSS (apenas linhas verificadas)”Este trecho inclui apenas as linhas classificadas como Verificado na matriz de suporte a CSS auditada quanto à veracidade. “Verificado” significa que há uma implementação em src/Html/ e um conjunto substancial e dedicado de fixtures que passa de forma determinística sob o perfil estrutural.
| Módulo W3C | Nível | Status | Evidência |
|---|---|---|---|
CSS Flexible Box Layout (css_flexbox_1) | 1 | Verificado | src/Html/Flex/, tests/Unit/Html/Flex/ |
CSS Grid Layout (css_grid_1) | 1 | Verificado | src/Html/Grid/, corpus WPT |
CSS Cascading and Inheritance (css_cascade_3) | 3 | Verificado | src/Html/Cascade/, tests/Unit/Html/Cascade/ |
CSS Table (css_tables_3) | 3 | Verificado | src/Html/Table/, fixtures de tabela + PDFs golden |
CSS Fonts (css_fonts_4) | 4 | Verificado | src/Html/FontFace/, tests/Unit/Html/FontFace/ |
Propriedades como text-align, text-indent e color são classificadas como “Reivindicado” na matriz (implementadas, mas sem fixture de módulo dedicada), por isso não aparecem aqui como Verificado.
Restrições do streaming de passagem única (ADR-001)
Seção intitulada “Restrições do streaming de passagem única (ADR-001)”O mecanismo HTML não retém nenhum DOM. Seu estado é um cursor escalar mais uma pilha de estilos push/pop; nós de texto compostos apenas por espaços em branco são descartados na tokenização. Uma consequência é que um elemento posterior não pode reestilizar um anterior, e seletores que precisam do contexto da árvore completa (por exemplo, casos complexos de :has()) ficam restritos conforme o ADR-006. Planeje um layout que dependa apenas da ordem do documento.
Contratos de camada (ADR-010)
Seção intitulada “Contratos de camada (ADR-010)”Análise (parsing), layout e pintura são camadas separadas. O parser não emite operadores de pintura brutos, e o despacho de layout não analisa CSS. Cruzar essas fronteiras gera a dívida de acoplamento que o ADR-010 proíbe. Para autores de receitas, isso significa que o ponto de entrada público é writeHtml(). Não acesse os internos do parser.
Orçamento de memória para documentos grandes
Seção intitulada “Orçamento de memória para documentos grandes”Conforme o ADR-020, contextos de formatação com escopo de contêiner (flex, table) podem construir uma subárvore efêmera, limitada a 5,000 nós por contexto, 20 níveis de profundidade, com um teto de memória ativa de 50 MB em todos os contextos ativos e 10 níveis de aninhamento. Fora desses contextos, o modelo de streaming não mantém nenhuma árvore. Mantenha tabelas individuais e contêineres flex dentro do limite de nós para ter consumo de memória previsível.
Notas de segurança
Seção intitulada “Notas de segurança”Trate a entrada HTML como não confiável. O NextPDF não executa scripts, e a política padrão de recursos externos não busca URLs remotas arbitrárias, portanto o próprio mecanismo é conservador. Ainda assim, valide ou sanitize qualquer HTML que você monte a partir da entrada do usuário antes de renderizá-lo. Os limites de elementos e de aninhamento também protegem você: eles delimitam quanto trabalho um documento hostil ou malformado pode exigir.
Conformidade
Seção intitulada “Conformidade”| Declaração | Especificação | Cláusula | reference_id |
|---|---|---|---|
| O CSS Text controla a tradução do texto de origem em texto formatado e quebrado em linhas. | W3C CSS Text Level 3 | css_text_3#x1.x2.p4 | |
| A face padrão do corpo é resolvida para uma fonte Type 1 padrão. | ISO 32000-2 | iso32000_2_sec9#x1.x29 |
Esta receita mostra como o NextPDF renderiza um subconjunto suportado de HTML e CSS. Ela não afirma suporte completo a HTML nem a CSS. O status verificado por módulo está na matriz de suporte a CSS.
Contexto comercial
Seção intitulada “Contexto comercial”Não aplicável.