เลย์เอาต์เอนจินแบบกำหนดเองและการดักจับข้อความขณะทำเลย์เอาต์
ภาพรวมโดยย่อ
หัวข้อที่มีชื่อว่า “ภาพรวมโดยย่อ”NextPDF ไม่ได้เปิดเผยอินเทอร์เฟซสำหรับเลย์เอาต์เอนจินแบบเสียบเพิ่มได้ ให้ใช้สัญญาส่วนขยายเลย์เอาต์สาธารณะ TextPreprocessorInterface เพื่อดักจับข้อความขณะทำเลย์เอาต์ อีเวนต์วงจรชีวิตของเนื้อหาช่วยให้สังเกตสิ่งที่เลย์เอาต์สร้างขึ้นได้
การติดตั้ง
หัวข้อที่มีชื่อว่า “การติดตั้ง”composer require nextpdf/core:^3ภาพรวมเชิงแนวคิด
หัวข้อที่มีชื่อว่า “ภาพรวมเชิงแนวคิด”ไปป์ไลน์เลย์เอาต์เป็นส่วนภายใน ไปป์ไลน์นี้ครอบคลุมการจัดวางกลิฟ การสร้างชุดย่อยฟอนต์ การส่งออก ToUnicode CMap และต้นไม้โครงสร้าง NextPDF ไม่อนุญาตให้แทนที่ไปป์ไลน์นี้ ผลลัพธ์ระดับไบต์ที่เสถียรและความสอดคล้องกับ tagged-PDF ขึ้นอยู่กับบิลด์เดียวที่มีการควบคุม
NextPDF เปิดเผย จุด ก่อน เลย์เอาต์: TextPreprocessorInterface พรีโปรเซสเซอร์จะรับข้อความดิบและคืนค่าผลลัพธ์ที่แบ่งเป็นเซกเมนต์ก่อนที่ข้อความนั้นจะเข้าสู่การจัดวางกลิฟ การสร้างชุดย่อยฟอนต์ การส่งออก ToUnicode CMap หรือการสร้างต้นไม้โครงสร้าง ใช้เส้นทางที่รองรับนี้เพื่อเปลี่ยนเนื้อหาข้อความโดยไม่ต้องแตะเลย์เอาต์เอนจิน
PHPDoc ของซอร์สกำหนดกฎไว้อย่างเคร่งครัด: อิมพลีเมนต์ ต้องไม่ เปลี่ยนพฤติกรรมของเลย์เอาต์ อิมพลีเมนต์ต้องไม่เพิ่มอักขระที่ส่งผลต่อเลย์เอาต์ เช่น line feed, carriage return หรือ tab และต้องรักษาลำดับการอ่านเชิงตรรกะไว้ พรีโปรเซสเซอร์ระบุการแทนที่เนื้อหา แต่ไม่ได้ตัดสินเลย์เอาต์ ต้องปฏิบัติตามกฎนี้ มิฉะนั้นผลลัพธ์ที่เสถียรและความสามารถในการเข้าถึงจะเสียหาย
หากต้องการสังเกตผลลัพธ์ของเลย์เอาต์แทนการเปลี่ยนแปลง ให้ใช้อีเวนต์วงจรชีวิตของเนื้อหาใน ทริกเกอร์การกระทำและตัวรับฟังอีเวนต์ ContentRenderedEvent จะถูกส่งหลังจากที่เนื้อหาถูกวาดลงบนหน้า FontLoadedEvent จะถูกส่งหนึ่งครั้งต่อตระกูลฟอนต์และสไตล์
พื้นผิว API
หัวข้อที่มีชื่อว่า “พื้นผิว API”NextPDF\Contracts\TextPreprocessorInterface (เสถียรตั้งแต่ 1.9.0):
| เมท็อด | คืนค่า | วัตถุประสงค์ |
|---|---|---|
process(string $text) | TextPreprocessResult | แปลงข้อความดิบก่อนไปป์ไลน์การเรนเดอร์ และคืนค่าผลลัพธ์ที่แบ่งเป็นเซกเมนต์พร้อมเมทาดาทาของการปกปิด |
ผลลัพธ์ NextPDF\Contracts\TextPreprocessResult ที่คืนค่ามาคือวัตถุค่าแบบตรึง ลายเซ็นของคอนสตรักเตอร์และพรอเพอร์ตีสาธารณะของวัตถุนี้มีความเสถียรและจะไม่เปลี่ยนแปลงในรีลีสแบบ minor หรือ patch อาจเพิ่มเมท็อดใหม่ได้
ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — เริ่มต้นอย่างรวดเร็ว”ตัวอย่างพรีโปรเซสเซอร์ขนาดเล็กด้านล่างนี้ปิดบังโทเค็นแบบคงที่ พรีโปรเซสเซอร์นี้ไม่เพิ่มอักขระที่ส่งผลต่อเลย์เอาต์และรักษาลำดับการอ่านไว้
<?php
declare(strict_types=1);
use NextPDF\Contracts\TextPreprocessorInterface;use NextPDF\Contracts\TextPreprocessResult;use NextPDF\Contracts\TextSegment;
final class TokenMaskingPreprocessor implements TextPreprocessorInterface{ public function process(string $text): TextPreprocessResult { $masked = \str_replace('SECRET-TOKEN', '••••••••••••', $text);
return new TextPreprocessResult([ new TextSegment($masked, redacted: $masked !== $text), ]); }}ตัวอย่างโค้ด — โปรดักชัน
หัวข้อที่มีชื่อว่า “ตัวอย่างโค้ด — โปรดักชัน”พรีโปรเซสเซอร์ระดับโปรดักชันเก็บกฎการจับคู่ไว้ที่เดียว พรีโปรเซสเซอร์นี้จะล้มเหลวแบบปิด (fail closed) เมื่อพบแพตเทิร์นที่ไม่ถูกต้อง และไม่บันทึกข้อความต้นฉบับลงล็อกโดยเด็ดขาด
<?php
declare(strict_types=1);
use NextPDF\Contracts\TextPreprocessorInterface;use NextPDF\Contracts\TextPreprocessResult;use NextPDF\Contracts\TextSegment;use Psr\Log\LoggerInterface;
final class PatternRedactionPreprocessor implements TextPreprocessorInterface{ /** * @param non-empty-string $pattern A valid PCRE pattern for sensitive spans */ public function __construct( private readonly string $pattern, private readonly LoggerInterface $logger, ) {}
public function process(string $text): TextPreprocessResult { $result = \preg_replace($this->pattern, '[REDACTED]', $text);
if ($result === null) { // Fail closed: never emit unredacted text on a pattern error. $this->logger->error('Redaction pattern failed; substituting empty text');
return new TextPreprocessResult([new TextSegment('', redacted: true)]); }
return new TextPreprocessResult([ new TextSegment($result, redacted: $result !== $text), ]); }}กรณีขอบเขตและข้อควรระวัง
หัวข้อที่มีชื่อว่า “กรณีขอบเขตและข้อควรระวัง”- ไม่มีการแทนที่เลย์เอาต์ ไม่สามารถแทนที่การจัดวางกล่อง การตัดบรรทัด หรือการแบ่งหน้าผ่านสัญญานี้ การเสียบเลย์เอาต์เอนจินของผู้พัฒนาภายนอกถูกออกแบบให้อยู่นอกขอบเขต
- การบังคับใช้กฎ หากเพิ่ม
\n\rหรือ\tในprocess()จะทำให้เลย์เอาต์เสียหายและทำลายผลลัพธ์ที่เสถียร เอนจินเชื่อถือตามกฎนี้และจะไม่ตรวจสอบผลลัพธ์ซ้ำเพื่อหาอักขระที่ส่งผลต่อเลย์เอาต์ - ลำดับการอ่าน หากจัดเรียงเซกเมนต์ใหม่ จะทำลายลำดับการอ่านของ tagged-PDF และความสอดคล้องกับ PDF/UA
- ความรับผิดชอบเดียว พรีโปรเซสเซอร์มีหน้าที่ระบุการแทนที่เนื้อหา ใช้อีเวนต์วงจรชีวิตเพื่อเฝ้าสังเกต และอย่าส่งผลข้างเคียงผ่าน
process()
ประสิทธิภาพ
หัวข้อที่มีชื่อว่า “ประสิทธิภาพ”process() ทำงานหนึ่งครั้งต่อหนึ่ง text run บน hot path ของเลย์เอาต์ ควบคุมการใช้หน่วยความจำให้ต่ำ คอมไพล์แพตเทิร์นหนึ่งครั้งในคอนสตรักเตอร์ ไม่ใช่ในการเรียกแต่ละครั้ง อีเวนต์วงจรชีวิตของเนื้อหาไม่มีต้นทุนใด ๆ เมื่อไม่มีตัวรับฟังผูกไว้
หมายเหตุด้านความปลอดภัย
หัวข้อที่มีชื่อว่า “หมายเหตุด้านความปลอดภัย”ใช้ TextPreprocessorInterface เพื่อลบเนื้อหาอ่อนไหวออก ก่อน ที่เนื้อหานั้นจะไปถึงสตรีมเนื้อหา ชุดย่อยฟอนต์ หรือเมทาดาทา เนื่องจากทำงานก่อนการสร้างชุดย่อยและ ToUnicode CMap กลิฟที่ถูกปกปิดจึงไม่ถูกใส่ลงในไฟล์เลย จัดการความล้มเหลวของพรีโปรเซสเซอร์แบบ fail-closed และส่งออกข้อความว่างหรือข้อความที่ปิดบังแล้วแทนข้อความต้นฉบับ
ความสอดคล้อง
หัวข้อที่มีชื่อว่า “ความสอดคล้อง”หน้านี้ไม่ได้ระบุการอ้างอิงเชิงบรรทัดฐานเกี่ยวกับการลงนามหรือการจัดเก็บถาวร กฎลำดับการอ่านทำให้สัญญาสอดคล้องกับข้อกำหนดของ tagged-PDF เอกสารอ้างอิงด้านความสามารถในการเข้าถึงครอบคลุมความสอดคล้องในระดับแท็ก
บริบทเชิงพาณิชย์
หัวข้อที่มีชื่อว่า “บริบทเชิงพาณิชย์”NextPDF Pro มีกลยุทธ์การประมวลผลข้อความเบื้องต้นระดับโปรดักชัน รวมถึงการปกปิดข้อมูลที่ระบุตัวบุคคลได้ (PII) ที่ปรับแต่งสำหรับประเภทเอกสารทั่วไป ใน Core ผู้พัฒนาเขียน TextPreprocessorInterface ด้วยตัวเอง หรือใช้บิลด์แบบชำระเงินที่ผ่านการตรวจสอบแล้วผ่านสัญญาสาธารณะเดียวกัน
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”สัญญาและโมดูลที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “สัญญาและโมดูลที่เกี่ยวข้อง”- เอกสารอ้างอิงสัญญา Typography — ซึ่งจัดทำแคตตาล็อก
TextPreprocessorInterfaceและTextPreprocessResult - เอกสารอ้างอิงสัญญา Streaming — สัญญา
experimentalCursorInterfaceและStreamingWriterInterfaceซึ่งมีอิมพลีเมนต์ของเอนจินที่จัดส่งแล้ว - ทริกเกอร์การกระทำและตัวรับฟังอีเวนต์ — อีเวนต์วงจรชีวิตที่ใช้สังเกตผลลัพธ์ของเลย์เอาต์
- กฎความเสถียรของ SPI — คำมั่นเรื่องวัตถุค่าแบบตรึงซึ่งอยู่เบื้องหลัง
TextPreprocessResult - ภาพรวมการเขียนส่วนขยาย — พื้นผิวสาธารณะทั้งหมดของ service provider interface (SPI)
อภิธานศัพท์ให้คำนิยามของ text preprocessor และ extension point โปรดดูอภิธานศัพท์ที่เผยแพร่สำหรับคำนิยามมาตรฐานของแต่ละคำ