Ir al contenido
getnextpdf.com

La canalización HTML

Spec: CSS Cascade 5, §6.1Spec: CSS Display 3, §2

NextPDF representa HTML y CSS en PDF dentro del propio proceso PHP: sin navegador ni subproceso de forma predeterminada. Esta página explica las etapas por capas que atraviesa la conversión, qué abarca realmente el motor CSS y el caso en el que delegar en un renderizador de navegador real es la elección honesta.

«HTML a PDF» suena como una sola operación. En realidad es una cascada, un modelo de caja, una pasada de maquetación y una pasada de pintado. Cada una es un problema bien especificado con sus propios modos de fallo. Un motor que las fusiona en un único procedimiento es frágil. Un cambio en el análisis del color puede desplazar una caja, y la única forma de saberlo es representar y mirar.

El modelo en el proceso tiene una ventaja real: ningún navegador que instalar, ningún entorno aislado que operar y ningún límite de proceso que atravesar. Pero solo compensa si la conversión se descompone de forma suficientemente limpia para probar cada aspecto por separado. La arquitectura es lo que hace que «representar HTML en PHP» sea confiable en lugar de meramente posible.

  • La conversión de HTML/CSS se ejecuta en el proceso mediante writeHtml(). El resultado es contenido PDF nativo, no una imagen de una página.
  • Es de una sola pasada y en flujo. El tokenizador produce una lista de tokens. El analizador la consume de izquierda a derecha, y no se retiene ningún árbol DOM completo (ADR-001). Límites estrictos acotan el número de elementos y la profundidad de anidamiento.
  • El motor está organizado en capas explícitas: análisis de CSS y aplicadores, estado de estilo, maquetación y formato, pintado y medios paginados, con reglas estrictas sobre qué puede hacer cada capa (ADR-010).
  • El motor CSS abarca la cascada, el modelo de caja y la maquetación común (bloque, en línea, tablas, flotantes y más): considerable, pero un subconjunto definido de lo que implementa un navegador moderno.
  • Cuando se necesita fidelidad exacta de navegador para CSS moderno arbitrario, NextPDF puede delegar en un renderizador de navegador headless a través de una extensión opcional: una costura deliberada y aislada de la red, no la ruta predeterminada.

La conversión es una secuencia de etapas, cada una de las cuales consume la salida tipada de la etapa anterior.

  1. TokenizarEl HTML se convierte en una lista ordenada de tokens: sin árbol DOM retenido.
  2. Resolver CSSSe analizan los estilos; la cascada y los aplicadores calculan valores tipados.
  3. Estado de estiloUna pila de estilos push/pop lleva los valores calculados por nivel de anidamiento.
  4. MaquetaciónSe calcula la geometría de bloque, en línea, de tabla y de flotantes; aquí no se pinta.
  5. PintadoBordes, fondos, texto y decoraciones emiten operadores PDF.
  6. Medios paginadosLas reglas de salto de página y @page se aplican cuando el cursor cruza los límites de página.
La canalización HTML en el proceso: una única pasada de izquierda a derecha sobre un flujo de tokens, con la resolución de CSS, el estado de estilo, la maquetación y el pintado como capas separadas, y los saltos de medios paginados aplicados a medida que avanza el cursor.

Dos reglas arquitectónicas hacen que esto sea más que un flujo.

Las capas tienen contratos. El texto CSS se lee únicamente dentro de las clases de aplicadores. El código de maquetación calcula la geometría, pero no emite operadores de pintado. El código de pintado lee una instantánea inmutable del estilo calculado, nunca el estado mutable de seguimiento de la maquetación. El código de medios paginados desencadena los saltos, pero delega la decoración de la página en la capa de pintado. Estos límites se hacen cumplir (ADR-010). Por eso una nueva propiedad CSS es un nuevo aplicador, en lugar de un cambio que se propaga a la vez por el analizador, el despacho de maquetación y el pintor.

No hay DOM. La canalización es de una sola pasada y en flujo por decisión (ADR-001): como máximo un estado de estilo por nivel de anidamiento más el cursor activo, no un objeto por elemento. Unas pocas operaciones necesitan genuinamente anticipación: el dimensionamiento de columnas de tabla, :has(), :last-child. Estas se gestionan mediante estructuras de índice de exploración previa acotadas sobre la lista plana de tokens, no reteniendo un árbol. El número de elementos y la profundidad de anidamiento tienen límites estrictos, de modo que una entrada patológica falla rápido en lugar de agotar la memoria.

El motor CSS resuelve la semántica real de CSS, no una imitación. Las declaraciones en conflicto se reducen a un único valor por propiedad según origen, importancia, capa, especificidad y orden: la cascada auténtica. La maquetación sigue el modelo de caja. El tipo de una caja y el contexto de formato que establece deciden cómo se sitúan ella y sus hermanas en el flujo. El código fuente del motor está organizado precisamente en torno a estos aspectos (cascada, caja/display, flex, flotantes, tablas, fragmentación). Por eso se puede razonar sobre su comportamiento frente a las especificaciones, en lugar de descubrirlo empíricamente.

La representación en el proceso es una sola llamada. La salida es texto PDF seleccionable, no una página rasterizada:

<?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');

Si el mismo documento requiriera CSS moderno arbitrario con fidelidad exacta de navegador, la llamada sería en cambio writeHtmlChrome($html): el mismo documento, una ruta de representación diferente y una dependencia deliberada del renderizador de navegador opcional.

El concepto erróneo recurrente es que un motor de HTML a PDF es «básicamente un navegador». No lo es, ni pretende serlo. Un navegador es una implementación vasta y actualizada continuamente de toda la plataforma web. El motor en el proceso de NextPDF es un subconjunto alineado con las especificaciones y centrado en la maquetación de documentos. El modelo mental honesto es «un motor CSS competente para documentos de impresión», no «Chrome en PHP». Cuando realmente se necesita la plataforma completa, para eso está writeHtmlChrome(). Es una ruta separada, de adhesión voluntaria, con su propia huella operativa, no un mecanismo de reserva silencioso.

Un segundo concepto erróneo: suponer que la ruta del navegador es meramente «representar la página a través de la red». Es lo contrario por diseño. La costura de delegación siempre representa con el acceso de red a subrecursos bloqueado —sin imágenes, fuentes, hojas de estilo ni marcos remotos—, de modo que no puede convertirse en un vector de solicitudes salientes. Fidelidad de píxel, sí; una salida de red abierta, no.

Esta página explica la forma de la canalización y la elección entre el proceso interno y el navegador. No es una matriz de soporte de CSS. Qué propiedades, módulos y selectores exactos abarca el motor en el proceso lo define el código y sus pruebas de conformidad, no esta descripción general. Esa cobertura evoluciona. La ruta de delegación al navegador requiere una extensión opcional y un binario de Chrome/Chromium. Su configuración, sus características operativas y la disposición interna de esa extensión quedan fuera del alcance aquí y se documentan junto con ese paquete. «En el proceso» describe la ruta predeterminada writeHtml(). No es una afirmación de que toda ruta de representación evite un subproceso. Las afirmaciones arquitectónicas son precisas a la fecha de revisión de esta página. Las fuentes autorizadas son src/Html/, ADR-001 y ADR-010 en el repositorio principal.

El motor CSS en el proceso es una capacidad de Core. La costura de delegación al navegador es una extensión opcional, presentada aquí solo a nivel de capacidad:

Rutas de representación HTML — edition availability
EditionAvailability
CoreCore proporciona el motor HTML/CSS en el proceso (writeHtml).
ProLa ruta de delegación al navegador es una extensión adicional opcional, independiente del nivel de edición.
EnterpriseLa ruta de delegación al navegador es una extensión adicional opcional, independiente del nivel de edición.
  • Representación en el proceso — convertir HTML/CSS en PDF dentro del proceso PHP, sin navegador ni subproceso predeterminado (writeHtml()).
  • Una sola pasada / en flujo — consumir un flujo de tokens de izquierda a derecha sin retener un árbol DOM completo (ADR-001).
  • Cascada — el proceso de CSS que resuelve las declaraciones en conflicto en un único valor por propiedad según origen, importancia, capa, especificidad y orden.
  • Contexto de formato — el entorno de maquetación que establece una caja y que rige cómo se sitúan sus contenidos en el flujo.
  • Contrato de capa del motor — el conjunto de reglas obligatorias (ADR-010) que define qué puede hacer cada una de las capas de análisis, estilo, maquetación, pintado y medios paginados.
  • Costura de delegación al navegador — la ruta opcional writeHtmlChrome() que representa mediante un navegador headless con el acceso de red a subrecursos bloqueado.