HTML パイプライン
Spec: CSS Cascade 5, §6.1 CSS Cascade 5 §6.1 Spec: CSS Display 3, §2 CSS Display 3 §2 Evidence: Code-backed
NextPDF は、HTML と CSS をお使いの PHP プロセス内で PDF としてレンダリングします。デフォルトではブラウザーもサブプロセスも使用しません。このページでは、変換が通過する階層化されたステージ、CSS エンジンが実際にカバーする範囲、そして実際のブラウザーレンダラーへ委譲することが適切な選択となるケースについて説明します。
なぜ重要なのか
「なぜ重要なのか」という見出しのセクション「HTML から PDF へ」は、一つの操作のように聞こえます。しかし実際には、カスケード、ボックスモデル、レイアウトパス、ペイントパスで構成されています。それぞれが、独自の障害モードを持つ、仕様で明確に定義された問題領域です。これらを一つの手続きにまとめてしまうエンジンは脆弱です。色のパースを変更するとボックスが移動することがあり、それを知る唯一の方法はレンダリングして確認することです。
プロセス内モデルには明確な利点があります。インストールが必要なブラウザーも、運用すべきサンドボックスも、データを受け渡すためのプロセス境界もありません。ただし、この利点が活きるのは、変換が各関心事を個別にテストできるほど明確に分解されている場合に限られます。「PHP で HTML をレンダリングする」ことを、単に可能であるだけでなく信頼できるものにしているのは、このアーキテクチャです。
手短に言えば
「手短に言えば」という見出しのセクション- HTML/CSS の変換は、
writeHtml()を介して プロセス内 で実行されます。その結果はネイティブの PDF コンテンツであり、ページの画像ではありません。 - これは シングルパスかつストリーミング です。トークナイザーがトークンリストを生成します。パーサーはそれを左から右へ消費し、完全な DOM ツリーは保持しません(ADR-001)。ハードキャップによって要素数とネストの深さが制限されます。
- エンジンは 明示的な層 として構成されています。CSS のパースとアプリケーター、スタイル状態、レイアウトと整形、ペイント、ページメディア。そして、どの層が何を行えるかについて厳格なルールがあります(ADR-010)。
- CSS エンジンは、カスケード、ボックスモデル、一般的なレイアウト(ブロック、インライン、テーブル、フロートなど)をカバーします。十分な機能を備えていますが、モダンブラウザーが実装する機能の、定義されたサブセットです。
- 任意のモダン CSS に対してブラウザーと完全に同等の忠実度が必要な場合、NextPDF はオプションの拡張機能を通じて ヘッドレスブラウザーレンダラーへ委譲 できます。これは意図的に設けられ、ネットワークから分離された接合点であり、デフォルトの経路ではありません。
NextPDF のアプローチ
「NextPDF のアプローチ」という見出しのセクション変換はステージの連なりであり、各ステージは前のステージの型付き出力を消費します。
- Tokenize HTML becomes an ordered token list — no retained DOM tree.
- Resolve CSS Parse styles; the cascade and applicators compute typed values.
- Style state A push/pop style stack carries computed values per nesting level.
- Layout Block, inline, table, and float geometry computed; no paint here.
- Paint Borders, backgrounds, text, and decorations emit PDF operators.
- Paged media Page-break and @page rules applied as the cursor crosses page bounds.
二つのアーキテクチャ上のルールが、この流れを単なるフロー以上のものにしています。
層には契約があります。 CSS テキストは、アプリケータークラスの内部でのみ読み取られます。レイアウトコードはジオメトリを計算しますが、ペイント演算子は出力しません。ペイントコードは不変の算出スタイルスナップショットを読み取り、可変のレイアウト追跡状態は決して読み取りません。ページメディアコードはページ区切りを発生させますが、ページの装飾はペイント層に委譲します。これらの境界は強制されています(ADR-010)。だからこそ、新しい CSS プロパティは、パーサー、レイアウトディスパッチ、ペインターへ一度に波及する変更ではなく、新しいアプリケーターとして実装されるのです。
DOM はありません。 パイプラインは設計上シングルパスかつストリーミングです(ADR-001)。保持するのは、ネストレベルごとに最大一つのスタイル状態とアクティブなカーソルであり、要素ごとに一つのオブジェクトではありません。一部の操作は、テーブルの列幅決定、:has()、:last-child のように、本当に先読みを必要とします。これらは、ツリーを保持するのではなく、フラットなトークンリストを対象にした有界な事前スキャン用インデックス構造によって処理されます。要素数とネストの深さはハードキャップされているため、病的な入力はメモリを使い果たすのではなく、即座に失敗します。
CSS エンジンは、見せかけではなく、本物の CSS セマンティクスを解決します。競合する宣言は、オリジン、重要度、レイヤー、詳細度、順序によって、プロパティごとに一つの値へと絞り込まれます。これが実際のカスケードです。レイアウトはボックスモデルに従います。ボックスの種類と、それが確立する整形コンテキストが、そのボックスとフロー内の兄弟要素の配置を決定します。エンジンのソースコードは、まさにこれらの関心事(カスケード、box/display、flex、float、テーブル、フラグメンテーション)を中心に構成されています。だからこそ、その挙動を経験的に探るのではなく、仕様に照らして論理的に推論できるのです。
エビデンスが示すこと
「エビデンスが示すこと」という見出しのセクションこのページは Evidence: Code-backed です。これらのステージとルールは、コアリポジトリに対応しています。
- プロセス内のエントリーポイントは、
src/Core/Concerns/HasTextOutput.php内のwriteHtml(string $html): staticです。 - 要素数とネストの上限を備えた、シングルパスかつ DOM を保持しない設計は、ADR-001 と、
src/Html/内の tokenizer/parser/スタイルスタックのコードにあります。 - 層構造のエンジン契約 — CSS の parsing/applicators、スタイル状態、レイアウト、ペイント、ページメディア — は ADR-010 で定義され、
src/Html/の構成に反映されています(例えばCascade/、Css/、Flex/、Float/、Fragmentation/、そしてアプリケータークラス)。 - ブラウザー委譲の接合点は、同じファイル内の
writeHtmlChrome()であり、オプションのレンダラー拡張機能と Chrome/Chromium バイナリを必要とすることが文書化されています。
これらの標準仕様により、カバレッジに関する主張を誠実に裏付けられます。カスケードは、競合する宣言を、オリジン、重要度、レイヤー、詳細度、順序によって、プロパティごとに単一の値へと絞り込みます。出典は Spec: CSS Cascade 5, §6.1 CSS Cascade 5 §6.1 であり、フロー内の配置はボックスと整形コンテキストのルールに従います。出典は Spec: CSS Display 3, §2 CSS Display 3 §2 。同じく重要なのは、この境界です。フィーチャークエリが存在するのは、まさにすべてのプロセッサーがすべての機能をサポートするわけではないからです。出典は Spec: CSS Conditional 5, §2 CSS Conditional 5 §2 。 NextPDF の CSS エンジンは、 定義された、仕様に整合したサブセットであり、それを率直に明言することも契約の一部です。
実践的な例
「実践的な例」という見出しのセクションプロセス内レンダリングは、一回の呼び出しです。出力は、ラスタライズされたページではなく、選択可能な PDF テキストです。
<?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');同じドキュメントで、任意のモダン CSS についてブラウザーと完全に同等の忠実度が必要な場合、呼び出しは代わりに writeHtmlChrome($html) となります。同じドキュメント、異なるレンダリング経路、そしてオプションのブラウザーレンダラーへの意図的な依存です。
よくある誤解
「よくある誤解」という見出しのセクション繰り返し見られる誤解は、HTML から PDF へのエンジンが「基本的にはブラウザーである」というものです。そうではありませんし、そうであると主張してもいません。ブラウザーは、ウェブプラットフォーム全体を継続的に更新しながら実装する巨大なソフトウェアです。NextPDF のプロセス内エンジンは、ドキュメントレイアウトに焦点を当てた、仕様に整合した サブセット です。誠実なメンタルモデルは、「PHP の中の Chrome」ではなく、「有能な印刷ドキュメント向け CSS エンジン」です。プラットフォーム全体が本当に必要な場合、そのためにあるのが writeHtmlChrome() です。これは独自の運用フットプリントを持つ、別個のオプトイン経路であり、暗黙のフォールバックではありません。
二つ目の誤解は、ブラウザー経路が単に「ネットワーク越しにページをレンダリングする」だけだと思い込むことです。設計上、これはその正反対です。委譲の接合点は、サブリソースのネットワークアクセスを無条件にブロックした状態でレンダリングします。リモートの画像、フォント、スタイルシート、フレームは一切なく、したがってアウトバウンドリクエストのベクトルになることはありません。ピクセル単位の忠実度はありますが、開かれたネットワークの送信経路はありません。
制限と境界
「制限と境界」という見出しのセクションこのページは、パイプラインの形と、プロセス内かブラウザーかの選択について説明します。これは CSS のサポートマトリクスでは ありません。プロセス内エンジンが正確にどのプロパティ、モジュール、セレクターをカバーするかは、この概要ではなく、コードとその適合性テストによって定義されます。そのカバレッジは進化します。ブラウザー委譲の経路には、オプションの拡張機能と Chrome/Chromium バイナリが必要です。そのセットアップ、運用上の特性、およびその拡張機能の内部構成は、ここでは対象外であり、そのパッケージとともに文書化されています。「プロセス内」は、デフォルトの writeHtml() 経路を指します。これは、すべてのレンダリング経路がサブプロセスを回避するという主張ではありません。アーキテクチャに関する記述は、このページのレビュー日時点で正確です。権威ある情報源は、コアリポジトリ内の src/Html/、ADR-001、ADR-010 です。
プロセス内 CSS エンジンは、Core の機能です。ブラウザー委譲の接合点はオプションの拡張機能であり、ここでは機能レベルでのみ示しています。
| Edition | Availability |
|---|---|
| Core | Core はプロセス内 HTML/CSS エンジン(writeHtml)を提供します。 |
| Pro | ブラウザー委譲の経路は、エディションのティアとは独立した、オプションのアドオン拡張機能です。 |
| Enterprise | ブラウザー委譲の経路は、エディションのティアとは独立した、オプションのアドオン拡張機能です。 |
関連ドキュメント
「関連ドキュメント」という見出しのセクション- パイプラインモデル — HTML コンテンツの経路が、ドキュメント全体のフローのどこに位置するか。
- NextPDF を使うべきでない場合 — ブラウザー経路や別のツールが適する場面を含む、誠実な境界。
- 統合の意思決定ガイド — 利用ケースに対して、プロセス内エンジンとレンダラーのどちらを選ぶか。
- プロセス内レンダリング — ブラウザーやデフォルトのサブプロセスを使わずに、PHP プロセス内で HTML/CSS を PDF に変換すること(
writeHtml())。 - シングルパス/ストリーミング — 完全な DOM ツリーを保持せずに、トークンストリームを左から右へ消費すること(ADR-001)。
- カスケード — 競合する宣言を、オリジン、重要度、レイヤー、詳細度、順序によって、プロパティごとに一つの値へと解決する CSS のプロセス。
- 整形コンテキスト — ボックスが確立し、そのフロー内のコンテンツがどのように配置されるかを規定するレイアウト環境。
- エンジン層契約 — パース、スタイル、レイアウト、ペイント、ページメディアの各層が何を行えるかを定義する、強制適用されるルールセット(ADR-010)。
- ブラウザー委譲の接合点 — サブリソースのネットワークアクセスをブロックした状態で、ヘッドレスブラウザーを介してレンダリングする、オプションの
writeHtmlChrome()経路。