Pro редакция
Projection — глубокий справочник
Эта страница — углублённый справочник по модулю Pro Projection. Здесь документируются публичная поверхность tokenize, emit и round-trip, гейт намерения и семантика кругового обхода (round-trip) потока содержимого. ContentProjectionWriter разбирает поток содержимого PDF в плоский упорядоченный список токенов, а затем повторно сериализует список токенов в новый поток содержимого. Модель односторонняя: эмиссия создаёт новый поток, а не редактирует оригинал на месте.
Примечание. «Проекция» здесь означает проекцию токенов потока содержимого, а не координатную или геопространственную проекцию.
Доступность и лицензирование
Заголовок раздела «Доступность и лицензирование»Эта возможность поставляется в составе NextPDF Pro (nextpdf/pro) и активируется лицензионным конвертом уровня Pro. Развёртывание без соответствующего права не загружает классы этой возможности. Сравните редакции и получите лицензию.
Отдельного флага лицензии на функцию нет. Это возможность редакции Pro. Эмиссия дополнительно требует явного аргумента ProjectionIntent, обеспечиваемого системой типов, а не переключателем лицензии.
Поверхность публичного API
Заголовок раздела «Поверхность публичного API»composer require nextpdf/pro:^3Модуль находится в пространстве имён NextPDF\Pro\Projection. Все операции ContentProjectionWriter статические.
| Символ | Параметры | Поведение по умолчанию | Возвращает | Выбрасывает или завершается с | Примечания |
|---|---|---|---|---|---|
ContentProjectionWriter::tokenize | string $contentStream | Разбирает поток в плоский упорядоченный список токенов; нормализует пробельные символы, отбрасывает комментарии, пропускает нераспознанные байты | list<ContentToken> | Нет; некорректные или управляющие байты пропускаются, а не отклоняются | Только для чтения; намерение не требуется. |
ContentProjectionWriter::emit | list<ContentToken> $tokens, ProjectionIntent $intent | Сериализует токены в новый поток содержимого; результат не зависит от значения намерения | string | В теле — нет; отсутствующий или не являющийся ProjectionIntent аргумент завершается ошибкой на границе типов | Намерение — это гейт в точке вызова, а не переключатель времени выполнения. |
ContentProjectionWriter::roundTrip | string $contentStream | Токенизирует, затем повторно эмитирует без изменений; проверочный гейт | string | Нет | Результат не побайтово идентичен; последовательность операторов и значения операндов сохраняются. |
ContentToken::__construct | ContentTokenType $type, string|int|float|bool|null $value = null | Создаёт неизменяемый токен; не выполняет валидации | ContentToken | Нет; несовместимый по типу $value завершается ошибкой на границе типов | readonly; type и value публичные. |
ContentToken::isTextOperator | — | Сообщает, является ли токен текстовым оператором (BT, ET, Tj, TJ, Td, TD, Tm, T*, Tf, Tc, Tw, Tz, TL, Tr, Ts, ', ") | bool | Нет; для нетокенов-операторов возвращает false | — |
ContentToken::isTextShowingOperator | — | Сообщает, является ли токен оператором показа текста (Tj, TJ, ', ") | bool | Нет; для нетокенов-операторов возвращает false | Подмножество текстовых операторов. |
ContentTokenType | — (строковое перечисление) | Перечисляет дискриминаторы токенов: LiteralString, HexString, Number, Name, Operator, ArrayBegin, ArrayEnd, DictBegin, DictEnd, Boolean, Null | — | — | Обратные значения — стабильные идентификаторы. |
ProjectionIntent | — (чистое перечисление) | Перечисляет два разрешённых намерения эмиссии: Sanitization, SteganographicEmbedding | — | — | Универсального варианта нет, поэтому статический анализ отмечает необъявленное использование. |
public static function tokenize(string $contentStream): arraypublic static function emit(array $tokens, ProjectionIntent $intent): stringpublic static function roundTrip(string $contentStream): stringenum ProjectionIntent{ case Sanitization; case SteganographicEmbedding;}public function __construct( public ContentTokenType $type, public string|int|float|bool|null $value = null,) {}
public function isTextOperator(): boolpublic function isTextShowingOperator(): boolКонтракт поведения
Заголовок раздела «Контракт поведения»ContentProjectionWriter::tokenize($contentStream) разбирает поток в плоский упорядоченный list<ContentToken>. Он охватывает литеральные строки, шестнадцатеричные строки, имена, числа, разделители массивов и словарей, булевы значения, null и операторы. Пробельные символы и комментарии поглощаются и отбрасываются; нераспознанный байт продвигает курсор, не создавая токена. Проход выполняется только для чтения и не требует намерения.
emit($tokens, $intent) сериализует список токенов обратно в байты потока содержимого и требует ProjectionIntent. Намерение — это лишь объявление в точке вызова: эмитируемые байты идентичны независимо от переданного варианта. Числа сохраняют различие между целыми и с плавающей точкой — целые эмитируются дословно, числа с плавающей точкой — с точностью до шести дробных разрядов с усечением завершающих нулей. Литеральные строки повторно экранируются, шестнадцатеричные строки эмитируются в верхнем регистре, а имена сохраняют ведущую косую черту (solidus). За каждым оператором следует перевод строки; разделители массивов и словарей подавляют соседний разделитель.
roundTrip($contentStream) токенизирует, затем повторно эмитирует без изменений. Это проверочный гейт: подтвердите чистый результат, прежде чем полагаться на любую последовательность «изменить-и-эмитировать». Результат не побайтово идентичен входу — пробельные символы нормализованы, а комментарии удалены, — но последовательность операторов и значения операндов сохраняются.
У ProjectionIntent ровно два варианта: Sanitization (деструктивное, необратимое редактирование) и SteganographicEmbedding (встраивание скрытой полезной нагрузки). Универсального варианта нет, поэтому статический анализ может отметить любую эмиссию без объявленного, известного назначения. ContentToken — это неизменяемое readonly-значение, несущее дискриминатор type и декодированное value; isTextOperator() и isTextShowingOperator() классифицируют токены-операторы и возвращают false для каждого токена, не являющегося оператором.
Граничные случаи и режимы отказа
Заголовок раздела «Граничные случаи и режимы отказа»- Подтвердите чистый круговой обход перед любой последовательностью «изменить-и-эмитировать». Сбойный круговой обход считайте условием остановки.
- Намерение
Sanitizationнеобратимо. Удалённые токены отсутствуют в результате и не могут быть восстановлены из него. - Намерение не меняет результат.
emit()создаёт одни и те же байты для любого варианта; аргумент — это гейт в точке вызова. Редактирование и стеганографические правки применяются вызывающим кодом, изменяющим список токенов перед эмиссией. - Эмиттер нормализует пробельные символы и отбрасывает комментарии, поэтому побайтовое сравнение с оригиналом различается даже при неизменённом круговом обходе.
- Операнды с плавающей точкой форматируются с не более чем шестью дробными разрядами и затем усекаются. Значения, требующие большей точности, округляются при эмиссии; целые числа точны.
- Декодируемые экранирования входных литеральных строк включают
\n,\r,\t,\b,\f, экранированные разделители и до трёхзначных восьмеричных экранирований, ограниченных одним байтом. - Шестнадцатеричная строка с нечётным числом цифр дополняется завершающим нулём на входе, соответствуя правилу ISO для шестнадцатеричных строк.
- Некорректные или управляющие байты пропускаются, а не отклоняются;
tokenize()не выбрасывает исключений при непредвиденном вводе. - Этот модуль не выполняет криптографических операций и не определяет поведения, специфичного для FIPS.
Соответствие
Заголовок раздела «Соответствие»Токенизация трактует поток как последовательность операторов и операндов в стандартном синтаксисе объектов PDF, согласно ISO 32000-2:2020, 8.2. Группировка байтов в токены следует лексическим классам символов ISO 32000-2:2020, 7.2. Шестнадцатеричная строка нечётной длины дополняет последнюю цифру нулём, согласно ISO 32000-2:2020, 7.3.4.3. Эти пункты зафиксированы в записи цитирования этой страницы.
Эти утверждения описывают возможности относительно цитируемых пунктов. NextPDF не имеет сертификации соответствия, и поддержка пункта не является заявлением о сертификации.
Заметки по разработке
Заголовок раздела «Заметки по разработке»- Доступно начиная с выпуска модуля 1.10.0; все три операции — статические точки входа на
ContentProjectionWriter. - Tokenize и emit линейны по длине потока содержимого. Опубликованных показателей пропускной способности нет; измеряйте на репрезентативных потоках.
- Плоская модель токенов — один токен на лексический элемент, а не сгруппированный по операторам — это то, что позволяет выполнять точечные правки, например корректировку одного числа внутри массива TJ. Сгруппированные по операторам представления находятся в другом месте дерева Pro и выходят за рамки этой страницы.
ContentTokenнеизменяем. Создавайте изменённый список, конструируя новые токены, а не изменяя существующие.- Держите гейт кругового обхода в конвейере: успешный
roundTrip()— это предусловие, вокруг которого построен модуль, перед любой деструктивной правкой.
Граница публикации
Заголовок раздела «Граница публикации»Эта страница документирует только внешне наблюдаемое поведение и поддерживаемую поверхность публичного API. Внутренние пути пространств имён, вспомогательные классы, таблицы механизмов, имена файлов runbook и префиксы тикетов выходят за рамки.