Salta ai contenuti

HTML: sottosistema di rendering da HTML+CSS verso PDF

Il sottosistema HTML converte HTML+CSS in flussi di contenuto PDF con un’unica passata in avanti. È il sottosistema più esteso e a più alto rischio del motore (324 file in src/Html/).

Terminal window
composer require nextpdf/core:^3

Il sottosistema HTML è un renderer streaming a passata singola da HTML+CSS verso PDF. La superficie pubblica espone un solo metodo, Document::writeHtml(). Internamente, HtmlParser tokenizza l’input, risolve gli stili, calcola l’impaginazione ed emette operatori PDF in un’unica passata in avanti, senza conservare un albero del documento.

È importante chiarire l’ambito. Questo sottosistema non è un renderer a documento ritenuto. Non mantiene un grafo degli elementi, non rielabora l’impaginazione dei contenuti già scritti e non consente di modificare l’input dopo l’avvio dell’analisi. Implementa un sottoinsieme curato di CSS con versioni di specifica fissate. Due decisioni architetturali lo governano. ADR-001 fissa il modello di streaming a passata singola e i relativi limiti. ADR-010 fissa il contratto a quattro livelli (analisi CSS, stato di stile, impaginazione, paint), insieme alle componenti aggiuntive per i media paginati e per la misurazione.

HtmlParser ha un livello di rischio classificato come critico nel manifest del modulo. Cinque file riportano annotazioni documentate come zona pericolosa: l’orchestratore HtmlParser (tokenizer in streaming, oltre 1000 LOC), HtmlStyleState (oltre 100 campi di proprietà CSS con un modello di ereditarietà a stack), HtmlBlockHandler (dispatch dei blocchi accoppiato allo stato di stile), FlexLayoutEngine (misurazione e impaginazione flex complete) e TableParser (paginazione colspan/rowspan attraverso le interruzioni di pagina). Trattare le modifiche in quest’area come lavoro in modalità di pianificazione.

Questa pagina è il punto di ingresso. Le pagine di dettaglio coprono: pipeline per la sequenza delle fasi, css-resolver per cascata e specificità, layer-contracts-adr010 per i confini tra i livelli e streaming-constraints-adr001 per il modello senza albero ritenuto e i relativi limiti.

writeHtml() esegue il rendering di contenuti da destra a sinistra (RTL). Impostare la proprietà CSS direction: rtl sul body, su una tabella o su qualsiasi elemento. Il motore risolve l’ordine visivo con l’algoritmo bidirezionale Unicode (UAX #9) tramite il motore bidirezionale del livello di tipografia — vedere Tipografia per i dettagli su BidiEngine. I contenuti misti latini, arabi e numerici vengono ordinati correttamente e un numero che segue l’arabo mantiene le sue cifre da sinistra a destra.

Anche l’arabo riceve lo shaping contestuale: il motore seleziona la forma iniziale, mediale, finale o isolata di ciascuna lettera e applica la legatura Lam-Alef. Lo shaping richiede un font registrato la cui character map copra il blocco Arabic Presentation Forms-B; una face solo latina, inclusi i font standard-14, non può disegnare l’arabo. Nelle tabelle, ogni cella viene riordinata e sottoposta a shaping autonomamente e si allinea al lato iniziale (destro) con direction: rtl. L’RTL si applica ad arabo, ebraico, persiano e urdu; l’ebraico viene riordinato ma non sottoposto a shaping.

Impostare la direzione con la proprietà CSS direction — l’attributo HTML dir non viene mappato su di essa. L’allineamento orizzontale del testo di blocco e inline non di tabella, e text-align: justify, non sono ancora applicati. Per una fattura araba eseguibile e l’elenco completo delle limitazioni attuali, vedere Eseguire il rendering di HTML arabo da destra a sinistra.

SimboloPosizioneRuolo
Document::writeHtml(string $html): staticsrc/Core/Concerns/HasTextOutput.phpPunto di ingresso pubblico. Esegue il rendering dell’HTML alla posizione corrente del cursore.
Document::createStandalone(): selfsrc/Core/Document.phpCrea un documento autonomo.
HtmlParser::parse(string $html): HtmlRenderResultsrc/Html/HtmlParser.phpOrchestratore interno.
HtmlRenderResultsrc/Html/HtmlRenderResult.phpRisultato immutabile: flusso, cursore finale, font utilizzati.
DefaultHtmlSecurityPolicysrc/Html/DefaultHtmlSecurityPolicy.phpCriteri predefiniti per tag/attributi/CSS/URL.
HtmlSecurityPolicyInterfacesrc/Contracts/HtmlSecurityPolicyInterface.phpContratto per i criteri personalizzati.

Tratto da 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>Direct to PDF.</p>');
$doc->save(__DIR__ . '/output/08-html-basic.pdf');

Un report tabellare con un blocco di stile incorporato, modellato su examples/09-html-table.php.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Exception\HtmlParsingException;
function renderInventory(string $rowsHtml, string $out): void
{
$doc = Document::createStandalone();
$doc->setTitle('Inventory');
$doc->addPage();
$html = '<style>table { width: 100%; } '
. 'th { background-color: #1E3A8A; color: #FFFFFF; }</style>'
. '<table border="1" cellpadding="5">' . $rowsHtml . '</table>';
try {
$doc->writeHtml($html);
} catch (HtmlParsingException $e) {
// Input cap, element cap (50,000), or nesting cap (100). Do not retry.
throw $e;
}
$doc->save($out);
}
  • Sottoinsieme CSS curato. Il supporto è definito per modulo e per versione fissata. Consultare la matrice di supporto CSS prima di fare affidamento su una proprietà.
  • I limiti rigidi generano eccezioni. Input di 10 MB, 50,000 elementi, 100 livelli di annidamento: ciascuno genera HtmlParsingException. Vedere vincoli dello streaming.
  • Nessuna rielaborazione dell’impaginazione. L’output viene scritto una sola volta nell’ordine del documento; gli stili successivi non possono modificare l’output già prodotto.
  • :has() è subordinato alla funzionalità sperimentale css.has.
  • Sottosistema a rischio critico. Cinque file sono contrassegnati come zona pericolosa. Usare la modalità di pianificazione per le modifiche in src/Html/.

Vincoli dello streaming a passata singola (ADR-001)

Sezione intitolata “Vincoli dello streaming a passata singola (ADR-001)”

Il renderer non mantiene alcun albero del documento ed esegue un’unica passata in avanti. I limiti su elementi, annidamento e input sono rigidi. I dettagli completi e il contratto di sicurezza per i worker si trovano in vincoli dello streaming (ADR-001).

L’analisi CSS, lo stato di stile, l’impaginazione e il paint sono separati in quattro livelli con contratti unidirezionali, insieme alle componenti aggiuntive per i media paginati e per la misurazione. Dettagli completi in contratti tra livelli (ADR-010).

Budget di memoria per documenti di grandi dimensioni

Sezione intitolata “Budget di memoria per documenti di grandi dimensioni”

La memoria per lo stato di stile e il cursore è O(profondità di annidamento), non O(numero di elementi). Il performance_budget per pagina è peak_mb: 64. Il limite di 50,000 elementi rappresenta il tetto massimo; suddividere gli input più grandi su più chiamate writeHtml(). Dettagli in vincoli dello streaming.

L’attraversamento è O(numero di token). Il dimensionamento delle colonne delle tabelle aggiunge una scansione limitata delle righe per ogni tabella. La pre-scansione opzionale :has() aggiunge una passata limitata sull’elenco dei token. Il benchmark delle prestazioni della pipeline di rendering HTML applica una soglia di regressione del 5% (lavoro già integrato, PR #564). Il performance_budget per pagina (wall_ms: 1500, peak_mb: 64) è il tetto operativo.

DefaultHtmlSecurityPolicy applica una allowlist di tag, attributi, proprietà CSS e schemi URL, oltre a un tetto di input di 10 MB e a un tetto di annidamento di 100 livelli, indipendentemente dal parser. L’allowlist delle proprietà CSS è il tetto di sicurezza. La tabella di supporto a runtime è un tetto di funzionalità distinto. Implementare HtmlSecurityPolicyInterface per fornire criteri più restrittivi. Il recupero delle risorse esterne è regolato separatamente da DefaultExternalResourcePolicy.

Nei valori href e src delle immagini, l’allowlist degli URL rifiuta anche i percorsi con radice backslash (\…) e UNC (\\host\share), oltre al rifiuto già esistente dei percorsi protocol-relative (//) e all’allowlist che ammette solo http(s) o percorsi relativi. I backslash vengono normalizzati in slash prima del controllo, quindi un include di file locale con percorso assoluto Windows o un recupero da condivisione SMB — nessuno dei quali presenta uno schema URI — non può sfuggire attraverso il ramo “nessuno schema, quindi relativo”.

Estratto della matrice di supporto CSS (solo righe verificate)

Sezione intitolata “Estratto della matrice di supporto CSS (solo righe verificate)”

Questa pagina non ripete il supporto proprietà per proprietà. La matrice di supporto CSS è l’unico riferimento autorevole per lo stato verificato per modulo W3C, inclusi i moduli verificati e quelli dichiarati.

Il sottosistema implementa un sottoinsieme curato di CSS con versioni di specifica fissate. Le mappature comportamentali della specifica per la cascata sono documentate con identificatori di clausola e chunk in css-resolver. Lo stato di conformità per modulo è disponibile nella matrice di supporto CSS.

Funzionalità Enterprise. Premium amplia la copertura CSS (stampa avanzata e moduli aggiuntivi) sulla stessa identica pipeline a passata singola. L’architettura, i limiti e i contratti tra livelli sono identici in tutte le edizioni. Vedere la matrice di supporto CSS.