HTML: HTML+CSS から PDF へのレンダリングサブシステム
HTML サブシステムは、HTML+CSS を 1 回の前方パスで PDF コンテンツストリームに変換します。 これはエンジン内で最大かつ最もリスクの高いサブシステムです (src/Html/ 配下の 324 ファイル)。
インストール
「インストール」という見出しのセクションcomposer require nextpdf/core:^3概念の概要
「概念の概要」という見出しのセクションHTML サブシステムは、シングルパスのストリーミング HTML+CSS-to-PDF レンダラーです。公開されているのは 1 つのメソッド Document::writeHtml() のみです。内部的には、HtmlParser が入力をトークン化し、スタイルを resolve(解決)し、レイアウトを計算したうえで、ドキュメントツリーを保持せずに 1 回の前方パスで PDF オペレーターを出力します。
スコープを明確にしておきます。このサブシステムは、ドキュメント保持型のレンダラーではありません。要素グラフを保持せず、すでに書き込まれたコンテンツを再レイアウトせず、パース開始後に入力を変更させることもありません。固定された仕様ピンに基づき、厳選された CSS のサブセットを実装しています。この前提は 2 つのアーキテクチャ決定によって規定されています。ADR-001 は、シングルパスのストリーミングモデルとその上限を定めています。ADR-010 は、4 層の契約 (CSS パース、スタイル状態、レイアウト、ペイント) に加えて、ページメディアおよび計測の補助機能を定めています。
HtmlParser は、モジュールマニフェストでリスクが critical に分類されています。5 つのファイルには、danger-zone の注釈が文書化されています。HtmlParser オーケストレーター (ストリーミングトークナイザー、1000 行超)、HtmlStyleState (スタック継承モデルを持つ 100 を超える CSS プロパティフィールド)、HtmlBlockHandler (スタイル状態と結合したブロックディスパッチ)、FlexLayoutEngine (完全な flex の計測とレイアウト)、TableParser (ページ区切りをまたぐ colspan/rowspan のページネーション) です。ここでの変更は plan モードの作業として扱ってください。
このページがエントリポイントです。詳細ページは次のとおりです。ステージシーケンスについては pipeline、カスケードと詳細度については css-resolver、レイヤー境界については layer-contracts-adr010、ツリーを保持しないモデルとその上限については streaming-constraints-adr001 を参照してください。
右から左への記述と双方向テキスト
「右から左への記述と双方向テキスト」という見出しのセクションwriteHtml() は右から左(RTL)へのコンテンツをレンダリングします。CSS の direction: rtl プロパティを body、テーブル、または任意の要素に設定してください。エンジンは、タイポグラフィレイヤーの双方向エンジンを通じて Unicode 双方向アルゴリズム(UAX #9)で視覚的な順序を解決します。BidiEngine の詳細については タイポグラフィ を参照してください。ラテン文字、アラビア語、数値が混在するコンテンツは正しく並べ替えられ、アラビア語の後に続く数値はその桁を左から右に保ちます。
アラビア語は文脈依存のシェイピングも受けます。エンジンは各文字の語頭形、語中形、語末形、または独立形を選択し、Lam-Alef リガチャを適用します。シェイピングには、文字マップが Arabic Presentation Forms-B ブロックをカバーする登録済みフォントが必要です。standard-14 フォントを含むラテン文字専用のフェイスでは、アラビア語を描画できません。テーブルでは、各セルが個別に並べ替えとシェイピングを受け、direction: rtl のもとで先頭(右)端に揃えられます。RTL はアラビア語、ヘブライ語、ペルシャ語、ウルドゥー語に適用されます。ヘブライ語は並べ替えられますが、シェイピングは行われません。
記述方向は CSS の direction プロパティで設定します。HTML の dir 属性はこれにマッピングされません。テーブル以外のブロックおよびインラインテキストの水平方向の配置、ならびに text-align: justify はまだ適用されていません。実行可能なアラビア語の請求書の例と、現在の制約の全リストについては、右から左へ記述するアラビア語 HTML のレンダリング を参照してください。
API サーフェス
「API サーフェス」という見出しのセクション| シンボル | 場所 | 役割 |
|---|---|---|
Document::writeHtml(string $html): static | src/Core/Concerns/HasTextOutput.php | 公開エントリ。現在のカーソル位置に HTML をレンダリングします。 |
Document::createStandalone(): self | src/Core/Document.php | スタンドアロンドキュメントの構築。 |
HtmlParser::parse(string $html): HtmlRenderResult | src/Html/HtmlParser.php | 内部オーケストレーター。 |
HtmlRenderResult | src/Html/HtmlRenderResult.php | イミュータブルな結果: ストリーム、終端カーソル、使用フォント。 |
DefaultHtmlSecurityPolicy | src/Html/DefaultHtmlSecurityPolicy.php | デフォルトの tag/attribute/CSS/URL ポリシー。 |
HtmlSecurityPolicyInterface | src/Contracts/HtmlSecurityPolicyInterface.php | カスタムポリシー用のポリシー契約。 |
コードサンプル — クイックスタート
「コードサンプル — クイックスタート」という見出しのセクションソースは 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');コードサンプル — プロダクション
「コードサンプル — プロダクション」という見出しのセクション埋め込みスタイルブロックを含むテーブルレポートで、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);}エッジケースと注意点
「エッジケースと注意点」という見出しのセクション- 厳選された CSS のサブセット。 サポートはモジュール単位で、ピン留めされています。プロパティに依存する前に、CSS サポートマトリクス を確認してください。
- ハード上限は例外をスローします。 10 MB の入力、
50,000要素、100 のネストレベル — いずれもHtmlParsingExceptionをスローします。ストリーミング制約 を参照してください。 - 再レイアウトはありません。 出力はドキュメント順に 1 回だけ書き込まれ、後から指定されたスタイルが先行する出力を変更することはできません。
:has()はゲートされています。css.has実験的機能の背後にあります。- critical リスクのサブシステム。 5 つの danger-zone ファイル。
src/Html/配下の変更には plan モードを使用してください。
シングルパスストリーミングの制約 (ADR-001)
「シングルパスストリーミングの制約 (ADR-001)」という見出しのセクションレンダラーはドキュメントツリーを保持せず、1 回の前方パスを実行します。要素、ネスト、入力の上限はハードリミットです。詳細とワーカー安全性の契約は ストリーミング制約 (ADR-001) にあります。
レイヤー契約 (ADR-010)
「レイヤー契約 (ADR-010)」という見出しのセクションCSS パース、スタイル状態、レイアウト、ペイントは、一方向の契約を持つ 4 つのレイヤーに分離され、さらにページメディアと計測の補助機能が加わります。詳細は レイヤー契約 (ADR-010) にあります。
大きなドキュメントのメモリバジェット
「大きなドキュメントのメモリバジェット」という見出しのセクションスタイル状態とカーソルのメモリは O(ネストの深さ) であり、O(要素数) ではありません。ページごとの performance_budget は peak_mb: 64 です。50,000 要素の上限がハードな上限です。より大きな入力は複数の writeHtml() 呼び出しに分割してください。詳細は ストリーミング制約 にあります。
パフォーマンス
「パフォーマンス」という見出しのセクション走査は O(トークン数) です。テーブルの列サイズ計算では、テーブルごとに上限付きの行スキャンが追加されます。オプションの :has() 事前スキャンでは、上限付きのトークンリストのパスが 1 回追加されます。HTML レンダーパイプラインのパフォーマンスベンチマークは、5% の回帰ゲートを強制します (マージ済みの作業、PR #564)。ページごとの performance_budget (wall_ms: 1500、peak_mb: 64) が運用上の上限です。
セキュリティに関する注意
「セキュリティに関する注意」という見出しのセクションDefaultHtmlSecurityPolicy は、タグ、属性、CSS プロパティ、URL スキームの許可リストに加えて、10 MB の入力上限と 100 レベルのネスト上限を、パーサーとは独立して強制します。CSS プロパティの許可リストがセキュリティ上の上限です。ランタイムのサポートテーブルは、別個の機能上限です。より厳格なポリシーを提供するには、HtmlSecurityPolicyInterface を実装してください。外部リソースの取得は、DefaultExternalResourcePolicy によって個別に管理されます。
属性 href および画像の src の値について、URL 許可リストは、既存のプロトコル相対 (//) の拒否、および http(s) または相対のみの許可リストに加えて、バックスラッシュで始まる (\…) パスと UNC (\\host\share) パスも拒否します。バックスラッシュはチェック前にスラッシュへ正規化されます。そのため、Windows の絶対パスによるローカルファイルのインクルードや SMB 共有の取得は、いずれも URI スキームを持たないにもかかわらず、「スキームがないため相対パスである」という分岐をすり抜けることはできません。
CSS サポートマトリクスの抜粋 (Verified 行のみ)
「CSS サポートマトリクスの抜粋 (Verified 行のみ)」という見出しのセクションこのページでは、プロパティごとのサポートを再掲しません。CSS サポートマトリクス は、どのモジュールが Verified でどれが Claimed かを含め、W3C モジュールごとの検証済みステータスについての唯一の権威です。
このサブシステムは、固定された仕様ピンに基づき、厳選された CSS のサブセットを実装しています。カスケードに関する動作仕様のマッピングは、css-resolver にクローズおよびチャンクの識別子付きで文書化されています。モジュールごとの準拠ステータスは CSS サポートマトリクス にあります。
商用上の位置づけ
「商用上の位置づけ」という見出しのセクションエンタープライズ機能。 Premium は、同一のシングルパスパイプライン上で CSS カバレッジ (高度な印刷と追加モジュール) を拡張します。アーキテクチャ、上限、レイヤー契約は、エディション間で同一です。CSS サポートマトリクス を参照してください。