стабильность: Экспериментальная
Превью-флаги CSS постраничной вёрстки (бегущий контент GCPM, именованные страницы, плавающие блоки страницы)
Подключаемое превью. Эти четыре функции CSS по умолчанию выключены. Когда флаг выключен, движок выдаёт побайтово идентичный результат сборке, которая никогда не знала о существовании этой функции. Включайте функцию только тогда, когда она вам нужна, и проверяйте результат на своих документах.
Рендерер HTML добавляет четыре подключаемые функции постраничной вёрстки из
модулей CSS Paged Media и Generated Content for Paged Media (GCPM). Каждая — это
отдельный флаг в CssFeatureFlags. Каждая несёт честную границу с отказом
закрытием: конструкцию, которую однопроходный движок не может воспроизвести
точно, он отбрасывает или деградирует с именованной диагностикой, но никогда не
рендерит неверно.
| Функция | Флаг | Что делает, когда включена |
|---|---|---|
| Именованные строки (GCPM) | runningStrings | Захват string-set плюс string() в полях @page — бегущие колонтитулы. |
| Именованные страницы (Paged Media L3) | namedPagesAdvanced | @page <ident>, свойство page: и :first / :left / :right / :blank — поля и оформление для конкретной страницы. |
| Бегущие элементы (GCPM) | runningElements | position: running(<ident>) плюс content: element(<ident>) — воспроизведение текста элемента в поле страницы. |
| Плавающие блоки страницы (Page Floats L3) | pageFloats | float: top | bottom | snap — перемещение блока в верхнюю или нижнюю полосу страницы. |
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Флаги поставляются в пакете core. Публичная поверхность CssFeatureFlags
помечена @since 6.1.0. Версия движка (Version::VERSION) не меняется; эти
функции аддитивны и по умолчанию выключены.
Концептуальный обзор
Заголовок раздела «Концептуальный обзор»Рендерер однопроходный и потоковый (см. ADR-001). Он не хранит дерево документа и пишет вывод один раз в порядке документа. Это ограничение определяет каждую функцию здесь. Каждая функция разрешает то, что видит за один прямой проход, и отказывает закрытием на всём, что потребовало бы второго прохода или сохранённого дерева. Граница задокументирована, а не скрыта — знание о том, где функция останавливается, — часть её использования.
Функцию включают, конструируя CssFeatureFlags с флагом, установленным в
true, и передавая его в Config. Когда флаг выключен, соответствующий CSS
разбирается и игнорируется ровно так же, как неподдерживаемое свойство, поэтому
вывод побайтово идентичен сборке без этой функции.
Именованные строки — runningStrings
Заголовок раздела «Именованные строки — runningStrings»string-set: <ident> content() записывает значение, когда движок проходит мимо
элемента. Ссылка string(<ident>) внутри поля @page затем разрешается в самое
свежее значение, увиденное на этой странице. Это стандартный механизм для
бегущего колонтитула, отслеживающего текущую главу или раздел.
Разрешение однопроходное — «последнее увиденное на этой странице». Ссылка
string() разрешается в последнее значение, которое движок записал перед
вёрсткой полей этой страницы.
Граница с отказом закрытием. При выключенном флаге string() разрешается в
пустую строку, и вывод остаётся побайтово идентичным. Некорректный список
содержимого string-set отбрасывает только эту одну пару присваивания и
продолжает работу; он никогда не прерывает рендеринг.
Именованные страницы — namedPagesAdvanced
Заголовок раздела «Именованные страницы — namedPagesAdvanced»Свойство page: <ident> назначает элементу контекст именованной страницы, а
соответствующее правило @page <ident> задаёт поля и оформление этого
контекста. Псевдоклассы страниц :first, :left, :right и :blank выбирают
первую страницу, лицевые и оборотные страницы и намеренно пустые страницы.
Эта функция выбирает поля и оформление именованной или псевдостраницы. Она не меняет геометрию страницы.
Граница с отказом закрытием. Именованное или псевдоправило @page, которое
пытается изменить геометрию — size, rotate или поле блока содержимого,
меняющее размер области страницы, — отказывает закрытием с
UnsupportedNamedPageException, а не молча выдаёт страницу со смещением.
Сопоставление по псевдоклассам — первый слой; более широкие случаи селекторов
отложены и задокументированы.
Бегущие элементы — runningElements
Заголовок раздела «Бегущие элементы — runningElements»position: running(<ident>) убирает элемент из обычного потока и паркует его под
именем. content: element(<ident>) в поле страницы затем воспроизводит этот
элемент на каждой странице. Используйте это, когда колонтитулу нужен полный
стилизованный текст заголовка, а не только захваченная строка.
Граница с отказом закрытием. Этот слой воспроизводит только текст
бегущего элемента. Богатое содержимое — изображения, замещаемые элементы,
вложенная блочная структура — отбрасывается, и движок выдаёт диагностику
HTML_RUNNING_ELEMENT_DEGRADED, так что потеря видна, а не скрыта. Элемент
running(), который ссылается сам на себя, вложенный running() или захват,
превышающий внутренний бюджет, отказывают закрытием. При выключенном флаге
running() и element() инертны.
Плавающие блоки страницы — pageFloats
Заголовок раздела «Плавающие блоки страницы — pageFloats»float: top, float: bottom и float: snap перемещают блок в верхнюю или
нижнюю полосу страницы по блочной оси, резервируя высоту полосы, так что
окружающий текст перетекает вокруг зарезервированной области.
float: bottom (и snap, разрешающийся в нижнюю полосу) — это случай, который
однопроходный движок обрабатывает напрямую: блок захватывается и помещается в
нижнюю полосу страницы по мере её закрытия. float: top вырождается в полосу у
верха страницы.
Граница с отказом закрытием. snap по строчной оси (snap-inline) не
поддерживается. Блок, несущий неперемещаемый побочный эффект — например,
аннотацию-ссылку, чей прямоугольник привязан к позиции в потоке, — нельзя
переместить безопасно, поэтому он возвращается в обычный поток, и движок выдаёт
диагностику HTML_PAGE_FLOAT_*, объясняющую запасное поведение. При выключенном
флаге float: top | bottom | snap трактуется как неподдерживаемое значение и
игнорируется.
Поверхность API
Заголовок раздела «Поверхность API»| Символ | Расположение | Роль |
|---|---|---|
CssFeatureFlags | src/Html/CssFeatureFlags.php | Неизменяемый подключаемый набор флагов; конструктор принимает runningStrings, namedPagesAdvanced, runningElements, pageFloats (все по умолчанию false). |
Config::withCssFeatureFlags(CssFeatureFlags $flags): self | src/Core/Config.php | Присоединяет набор флагов к конфигурации документа. |
CssFeatureFlags::forMode(CssRenderingMode $mode, ?self $explicit = null): self | src/Html/CssFeatureFlags.php | Разрешает набор флагов для режима рендеринга (режим Safe принудительно выключает все флаги; режим Normal использует явный набор или allEnabled(), если он не задан). |
UnsupportedNamedPageException | src/Html/PagedMedia/UnsupportedNamedPageException.php | Выбрасывается, когда именованное/псевдоправило @page меняет геометрию страницы. |
Коды диагностических предупреждений проявляются через консультативный канал
результата рендеринга: HTML_RUNNING_ELEMENT_DEGRADED, семейство
HTML_RUNNING_ELEMENT_* и семейство HTML_PAGE_FLOAT_*.
Пример кода — Быстрый старт
Заголовок раздела «Пример кода — Быстрый старт»Включите именованные строки для бегущего колонтитула, отслеживающего текущую главу.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;use NextPDF\Html\Css\CssFeatureFlags;
$config = (new Config())->withCssFeatureFlags( new CssFeatureFlags(runningStrings: true),);
$doc = Document::createStandalone($config);$doc->addPage();$doc->writeHtml( '<style>' . 'h2 { string-set: chapter content(); }' . '@page { @top-center { content: string(chapter); } }' . '</style>' . '<h2>Introduction</h2><p>Body text…</p>',);$doc->save(__DIR__ . '/running-header.pdf');Пример кода — Продакшен
Заголовок раздела «Пример кода — Продакшен»Включите несколько флагов вместе и трактуйте консультативный канал как сигнал о том, что конструкция деградировала. Флаги независимы; включайте только те, которые используете.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Config;use NextPDF\Core\Document;use NextPDF\Exception\UnsupportedNamedPageException;use NextPDF\Html\Css\CssFeatureFlags;
$config = (new Config())->withCssFeatureFlags(new CssFeatureFlags( runningStrings: true, namedPagesAdvanced: true, runningElements: true, pageFloats: true,));
$doc = Document::createStandalone($config);$doc->addPage();
try { $doc->writeHtml($html);} catch (UnsupportedNamedPageException $e) { // A named @page rule tried to change page geometry (size/rotate/margin). // The engine fails closed rather than emit a misaligned page. throw $e;}
$doc->save($out);
// Inspect $doc's advisory channel for HTML_RUNNING_ELEMENT_DEGRADED and// HTML_PAGE_FLOAT_* before treating the output as final.Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Все четыре флага независимы и по умолчанию выключены. Выключенный флаг даёт побайтово идентичный вывод. Включайте только то, что используете.
string()пуст, когдаrunningStringsвыключен — по замыслу. Для выключенного случая предупреждения нет; это задокументированное поведение по умолчанию.- Бегущие элементы воспроизводят только текст. Изображения и вложенные блоки
внутри бегущего элемента отбрасываются с
HTML_RUNNING_ELEMENT_DEGRADED. Проверяйте консультативный канал. - Именованные страницы не могут менять геометрию. Меняющее геометрию
именованное/псевдоправило
@pageвыбрасываетUnsupportedNamedPageException. Задавайте размер и поворот страницы черезConfig, а не через именованное правило@page. - Плавающие блоки страницы оставляют ссылки в потоке. Плавающий блок,
содержащий аннотацию-ссылку, возвращается в обычный поток с диагностикой
HTML_PAGE_FLOAT_*, потому что прямоугольник ссылки привязан к её позиции в потоке.
Производительность
Заголовок раздела «Производительность»Каждая функция добавляет ограниченный объём однопроходной работы: именованные
строки записывают одно значение на элемент string-set; именованные страницы
добавляют разрешение полей на страницу; бегущие элементы захватывают один
текстовый буфер на запаркованный элемент; плавающие блоки резервируют одну полосу
на страницу. Ни одна не хранит дерево документа, поэтому модель памяти O(глубина
вложенности) потокового рендерера сохраняется. Постраничный
performance_budget (wall_ms: 1500, peak_mb: 64) не меняется.
Заметки по безопасности
Заголовок раздела «Заметки по безопасности»Эти флаги не расширяют поверхность ввода. Политика безопасности HTML, список разрешённых свойств CSS, а также ограничения на байты таблицы стилей и глубину вложенности применяются без изменений. Захваченное содержимое строк и элементов экранируется через тот же выходной путь, что и любой другой текст. Функции добавляют поведение вёрстки, а не новый канал поглощения данных.
Соответствие стандартам
Заголовок раздела «Соответствие стандартам»| Утверждение | Спецификация | Раздел |
|---|---|---|
string-set записывает именованную строку; string() разрешает её в поле страницы. | W3C CSS Generated Content for Paged Media | §3 |
position: running() убирает элемент из потока; content: element() воспроизводит его. | W3C CSS Generated Content for Paged Media | §5 |
Свойство page и @page <ident> выбирают контекст именованной страницы. | W3C CSS Paged Media Module Level 3 | §3 |
float: top | bottom | snap помещает блок в полосу страницы по блочной оси. | W3C CSS Page Floats Level 3 | §5 |
Это превью-реализации функций модулей рабочей группы. NextPDF реализует однопроходное подмножество с задокументированными выше границами с отказом закрытием. Проверенный статус по каждому свойству отслеживается в матрице поддержки CSS; сквозное соответствие здесь не заявляется. Текст стандартов не воспроизводится.