Пользовательские движки макета и перехват текста на этапе макета
Коротко о главном
Заголовок раздела «Коротко о главном»NextPDF не предоставляет подключаемый интерфейс движка макета. Используйте публичный контракт расширения макета — TextPreprocessorInterface, — чтобы работать с текстом на этапе макета. События жизненного цикла содержимого позволяют наблюдать за тем, из чего формируется макет.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Pipeline макета является внутренним. Он охватывает раскладку глифов, формирование подмножества шрифта, вывод ToUnicode CMap и дерево структуры. NextPDF не позволяет заменить его. Стабильный побайтовый вывод и соответствие требованиям tagged-PDF зависят от единой контролируемой сборки.
NextPDF всё же предоставляет точку перед макетом: TextPreprocessorInterface. Реализация получает необработанный текст и возвращает сегментированный результат до того, как текст попадает в раскладку глифов, формирование подмножества шрифта, ToUnicode CMap или дерево структуры. Используйте этот поддерживаемый путь, чтобы менять текстовое содержимое, не затрагивая движок макета.
Исходный PHPDoc задаёт жёсткое правило: реализация не должна менять работу макета. Она не должна добавлять символы, влияющие на макет, такие как перевод строки, возврат каретки или табуляция, и должна сохранять логический порядок чтения. Препроцессор заявляет подмену содержимого; он не принимает решений о макете. Соблюдайте это правило, иначе стабильность вывода и доступность будут нарушены.
Чтобы наблюдать за результатом макета, а не менять его, используйте события жизненного цикла содержимого из раздела “Триггеры действий и обработчики событий”. ContentRenderedEvent срабатывает после отрисовки содержимого на странице. FontLoadedEvent срабатывает один раз для каждого семейства и начертания шрифта.
Поверхность API
Заголовок раздела «Поверхность API»NextPDF\Contracts\TextPreprocessorInterface (стабильный, начиная с 1.9.0):
| Метод | Возвращает | Назначение |
|---|---|---|
process(string $text) | TextPreprocessResult | Преобразует необработанный текст перед pipeline отрисовки и возвращает сегментированный результат с метаданными редактирования. |
Возвращаемый NextPDF\Contracts\TextPreprocessResult — замороженный объект-значение. Сигнатура его конструктора и публичные свойства стабильны и не меняются в минорных или патч-выпусках. Новые методы могут добавляться.
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»Небольшой препроцессор ниже маскирует фиксированный токен. Он не добавляет символов, влияющих на макет, и сохраняет порядок чтения.
<?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), ]); }}Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»Production-препроцессор хранит правила сопоставления в одном месте. При некорректном шаблоне он отказывает безопасно и никогда не записывает исходный текст в журнал.
<?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() выполняется один раз для каждого текстового фрагмента на горячем пути макета. Держите потребление памяти низким. Компилируйте шаблоны один раз в конструкторе, а не при каждом вызове. События жизненного цикла содержимого ничего не стоят, когда к ним не привязан ни один обработчик.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»Используйте TextPreprocessorInterface, чтобы удалять конфиденциальное содержимое до того, как оно попадёт в поток содержимого, подмножества шрифтов или метаданные. Поскольку он выполняется до формирования подмножества и ToUnicode CMap, отредактированные глифы никогда не попадают в файл. Считайте сбой препроцессора отказом в безопасную сторону и возвращайте пустой или маскированный текст вместо исходного.
Соответствие требованиям
Заголовок раздела «Соответствие требованиям»Эта страница не содержит нормативных заявлений о подписании или архивировании. Правило порядка чтения согласует контракт с требованиями tagged-PDF. Справочник по доступности охватывает соответствие на уровне тегов.
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»NextPDF Pro предоставляет production-ready стратегии предобработки текста, включая редактирование персональных данных (PII), настроенное под распространённые типы документов. В Core вы пишете TextPreprocessorInterface самостоятельно или используете проверенную сборку платной редакции через тот же публичный контракт.
См. также
Заголовок раздела «См. также»- Обзор разработки расширений
- Триггеры действий и обработчики событий
- Пользовательские шрифты
- Правила стабильности SPI
Связанные контракты и модули
Заголовок раздела «Связанные контракты и модули»- Справочник по контрактам типографики — здесь каталогизированы
TextPreprocessorInterfaceиTextPreprocessResult. - Справочник по контрактам потоковой передачи — контракты
experimentalCursorInterfaceиStreamingWriterInterface, для которых поставляется реализация движка. - Триггеры действий и обработчики событий — события жизненного цикла для наблюдения за выводом макета.
- Правила стабильности SPI — гарантия замороженного объекта-значения, стоящая за
TextPreprocessResult. - Обзор разработки расширений — вся публичная поверхность интерфейса поставщика услуг (SPI).
Глоссарий определяет термины препроцессор текста и точка расширения; канонические определения приведены в опубликованном глоссарии.