ไปป์ไลน์การเรนเดอร์ HTML
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”เมื่อเรียก writeHtml() ระบบจะประมวลผล HyperText Markup Language (HTML) แบบเดินหน้าเพียงรอบเดียว ได้แก่การแปลงอินพุตเป็นโทเคน การแก้ค่า @page และสไตล์ การจัดเค้าโครงเนื้อหา และการวาดตัวดำเนินการ Portable Document Format (PDF) ไปป์ไลน์ไม่เก็บทรีของอิลิเมนต์ไว้ข้ามขั้นตอนต่าง ๆ
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”ไปป์ไลน์การเรนเดอร์ HTML แปลง HTML+CSS ซึ่งหมายถึง HTML รวมกับ Cascading Style Sheets (CSS) ให้เป็นตัวดำเนินการของคอนเทนต์สตรีม PDF ด้วยการประมวลผลแบบเดินหน้าเพียงรอบเดียว ไปป์ไลน์ไม่สร้างทรีเอกสารแบบคงอยู่ ขั้นตอนด้านล่างสะท้อน HtmlParser::parse() บน main ในปัจจุบัน
ขั้นที่ 1 — ทำให้ปลอดภัยและทำให้เป็นมาตรฐาน HtmlParser::parse() ปฏิเสธอินพุตที่มีขนาดเกิน 10 MB ตัดอักขระควบคุมออก และทำให้การขึ้นบรรทัดใหม่เป็นมาตรฐาน โดยทั้ง CRLF และ CR เดี่ยวจะกลายเป็น LF ซึ่งตรงกับการทำให้การขึ้นบรรทัดใหม่ของ HTML เป็นมาตรฐานในต้นฉบับ จากนั้นรีเซ็ตทุกฟิลด์ของอินสแตนซ์ เพื่อไม่ให้สถานะจากการเรียกครั้งก่อนส่งต่อมาได้
ขั้นที่ 2 — แยก @page และบล็อกสไตล์ ตัวแยกวิเคราะห์จะแยกบล็อก <style> ออกมาก่อน จากนั้นนำกฎ @page ที่พบมาใช้กำหนดรูปทรงของหน้าใหม่ ขั้นตอนนี้เกิดขึ้นก่อนการประมวลผลโทเคนใด ๆ เพราะขนาดหน้าส่งผลต่อการตัดสินใจจัดเค้าโครงทุกครั้งหลังจากนั้น
ขั้นที่ 3 — แปลงเป็นโทเคน HtmlTokenizer::cleanHtml() ทำให้ช่องว่างเป็นมาตรฐานพร้อมรักษาเนื้อหา <pre> ไว้ จากนั้น tokenize() จะสร้าง list<HtmlToken> แบบแบนราบ ผลลัพธ์นี้เป็นรายการโทเคน ไม่ใช่กราฟของโหนด ไปป์ไลน์จะทิ้งโทเคนข้อความที่มีเฉพาะช่องว่างทันที HtmlChildScanner::scan() สร้างแมปดัชนี (จำนวนโหนดลูก จำนวนแท็ก ความว่างเปล่า) บนรายการแบบแบนราบ ดังนั้นตัวเลือกเชิงโครงสร้างจึงไม่ต้องใช้ทรี
ขั้นที่ 4 — การพรีสแกน :has() ที่เป็นตัวเลือก เมื่อเปิดใช้คุณสมบัติทดลอง css.has CssResolver::resolveHasSelectors() จะพรีสแกนรายการโทเคนแบบมีขอบเขตจำกัดหนึ่งครั้งเพื่อแก้ค่าตัวเลือกเชิงสัมพันธ์ ขั้นตอนที่มีเอกสารกำกับและมีขอบเขตจำกัดนี้เป็นข้อยกเว้นของกฎการประมวลผลรอบเดียว
ขั้นที่ 5 — ประมวลผลโทเคน (สไตล์ เค้าโครง การวาด) HtmlParser::processTokens() เดินผ่านรายการโทเคนหนึ่งครั้ง สำหรับแต่ละอิลิเมนต์ จะแก้ค่า cascade (ตัวประยุกต์ใช้ของ Layer 1 เขียน HtmlStyleState) คำนวณรูปทรง (การจัดเค้าโครงของ Layer 3) และส่งออกตัวดำเนินการ PDF (การวาดของ Layer 4) การสืบทอดสไตล์ใช้สแตก HtmlStyleState แบบ push-and-pop เคอร์เซอร์ (x, y ระยะขอบ ออฟเซ็ตของสตรีม) ถูกส่งต่อระหว่างตัวจัดการต่าง ๆ ผ่านสแนปช็อตของ HtmlBlockCursor ในแต่ละขั้น
ขั้นที่ 6 — คืนค่าผลลัพธ์ parse() คืนค่า HtmlRenderResult ที่เปลี่ยนแปลงไม่ได้ พร้อมคอนเทนต์สตรีมที่ส่งออก ตำแหน่งเคอร์เซอร์สุดท้าย และคีย์ฟอนต์ที่ใช้ ตัวเรียก (writeHtml()) ส่งเคอร์เซอร์กลับไปยังกรอบพิกัดของหน้า
สำหรับการแยกสี่เลเยอร์ภายในขั้นที่ 5 โปรดดูหน้า สัญญาของเลเยอร์ สำหรับคุณสมบัติที่ไม่เก็บทรีและขีดจำกัดที่เกี่ยวข้อง โปรดดูหน้า ข้อจำกัดของสตรีมมิง ประกอบ
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”| สัญลักษณ์ | ตำแหน่ง | ขั้น |
|---|---|---|
Document::writeHtml(string $html): static | src/Core/Concerns/HasTextOutput.php | จุดเข้าใช้สาธารณะ |
HtmlParser::parse(string $html): HtmlRenderResult | src/Html/HtmlParser.php | ประสานงานทุกขั้นตอน |
HtmlTokenizer::cleanHtml() / tokenize() | src/Html/HtmlTokenizer.php | ขั้นที่ 3 |
HtmlChildScanner::scan() | src/Html/HtmlChildScanner.php | แมปดัชนีของขั้นที่ 3 |
CssResolver::resolveHasSelectors() | src/Html/CssResolver.php | ขั้นที่ 4 (มีการควบคุมการเปิดใช้) |
HtmlRenderResult (stream, endX, endY, usedFontKeys) | src/Html/HtmlRenderResult.php | ขั้นที่ 6 |
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”ตัวอย่างนี้มาจาก 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>One pass.</p>');$doc->save(__DIR__ . '/output/08-html-basic.pdf');ตัวอย่างโค้ด — การใช้งานจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — การใช้งานจริง”เรนเดอร์รายงานที่จัดสไตล์ไว้และมีบล็อก <style> ฝังอยู่ ไปป์ไลน์จะแยกและนำบล็อกสไตล์มาใช้ก่อนการประมวลผลโทเคนใด ๆ
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Exception\HtmlParsingException;
function renderInvoice(string $bodyHtml, string $out): void{ $doc = Document::createStandalone(); $doc->setTitle('Invoice'); $doc->addPage();
$html = '<style>@page { margin: 20mm; } ' . 'h1 { color: #1E3A8A; } ' . 'table { width: 100%; }</style>' . $bodyHtml;
try { $doc->writeHtml($html); } catch (HtmlParsingException $e) { // Sanitize/cap failures surface here. Do not retry. throw $e; }
$doc->save($out);}กรณีขอบและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบและข้อควรระวัง”@pageถูกอ่านก่อนโทเคน กฎ@pageที่อยู่หลังเนื้อหายังคงมีผล เพราะการแยกสไตล์เกิดขึ้นก่อนการแปลงเป็นโทเคน รูปทรงของหน้าจะถูกกำหนดตายตัวก่อนขั้นที่ 5- ช่องว่างใน
<pre>จะถูกรักษาไว้cleanHtml()ปกป้องเนื้อหา<pre>ส่วนช่องว่างในตำแหน่งอื่น ๆ ไปป์ไลน์จะยุบรวมเข้าด้วยกัน :has()มีการควบคุมการเปิดใช้ หากไม่ได้เปิดใช้คุณสมบัติทดลองcss.hasขั้นที่ 4 จะไม่ทำงานและตัวเลือก:has()จะไม่จับคู่- บัฟเฟอร์สตรีมเดียว ไปป์ไลน์เขียนลงบัฟเฟอร์สตริงเพียงตัวเดียว และไม่เคยย้ายเนื้อหาที่เขียนไปแล้ว จึงไม่มีการจัดเค้าโครงใหม่
- ขีดจำกัดมีผลระหว่างการประมวลผล ขีดจำกัดของอิลิเมนต์และการซ้อนจะส่งข้อยกเว้นระหว่างขั้นที่ 5 ไม่ใช่ก่อนหน้านั้น เอกสารจึงอาจล้มเหลวกลางคันได้
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”ไปป์ไลน์เดินผ่านด้วยความซับซ้อน O(จำนวนโทเคน) การกำหนดขนาดคอลัมน์ของตารางเพิ่มการสแกนแถวแบบมีขอบเขตจำกัดต่อตาราง (ขั้นที่ 5 TableParser) เมื่อเปิดใช้ การพรีสแกน :has() จะเพิ่มการประมวลผลรายการโทเคนแบบมีขอบเขตจำกัดหนึ่งรอบ (ขั้นที่ 4) หน่วยความจำของสแตกสไตล์เป็น O(ความลึกของการซ้อน) ไม่ใช่ O(จำนวนอิลิเมนต์) โปรดดู ข้อจำกัดของสตรีมมิง เกณฑ์มาตรฐานประสิทธิภาพของไปป์ไลน์การเรนเดอร์ HTML ป้องกันการถดถอยด้วยเกตที่ 5% (งานที่ผสานแล้ว PR #564) performance_budget ต่อหน้า (wall_ms: 1500, peak_mb: 64) คือเพดานการทำงาน
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”ขั้นที่ 1 คือขอบเขตความปลอดภัยแรก ได้แก่ขีดจำกัดอินพุต 10 MB การตัดอักขระควบคุมออก และการทำให้การขึ้นบรรทัดใหม่เป็นมาตรฐาน ซึ่งทั้งหมดทำงานก่อนการแปลงเป็นโทเคน ระหว่างขั้นที่ 5 DefaultHtmlSecurityPolicy ควบคุมแท็ก แอตทริบิวต์ คุณสมบัติ CSS และสคีม URL ที่อนุญาต โปรดดู โมเดลความปลอดภัยของโมดูล HTML ประกอบ
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”การทำให้การขึ้นบรรทัดใหม่เป็นมาตรฐานเป็นไปตามการจัดการการขึ้นบรรทัดใหม่ของมาตรฐาน HTML โดย CRLF และ CR เดี่ยวจะกลายเป็น LF ความสอดคล้องของ CSS แบบรายคุณสมบัติมีเอกสารกำกับใน เมทริกซ์การรองรับ CSS และพฤติกรรมการ cascade มีเอกสารกำกับใน css-resolver หน้านี้ไม่ระบุการรองรับแบบรายคุณสมบัติซ้ำ
บริบทเชิงพาณิชย์
หัวข้อที่มีชื่อว่า “บริบทเชิงพาณิชย์”ความสามารถระดับองค์กร Premium ขยายการรองรับ CSS ให้กว้างขึ้นบนไปป์ไลน์เดียวกัน ลำดับหกขั้นไม่เปลี่ยนแปลงระหว่างรุ่นต่าง ๆ โปรดดู เมทริกซ์การรองรับ CSS ประกอบ