Paged.js CLI

Paged.js CLI превращает подготовленный HTML-документ в PDF с управляемой полиграфической версткой: команда задаёт выходной файл, формат и ориентацию страниц, а CSS-правила отвечают за поля, колонтитулы, нумерацию, развороты, разрывы и печатные метки. Для проверки макета можно открыть отладочное окно Chromium, подключить дополнительные стили и обработчики, ограничить доступ к файлам и сетевым ресурсам, а затем повторять ту же сборку из сценария автоматизации.

Рабочий процесс строится вокруг одного входного HTML-файла или страницы, доступной движку Chromium. Пользователь переходит в каталог проекта, запускает команду с путём к документу и параметром выходного PDF, после чего Paged.js анализирует стили печати, разбивает поток на страницы и передаёт результат механизму печати браузера. Сообщения в терминале показывают стадию загрузки и ошибки, а режим отладки оставляет окно открытым, чтобы исследовать созданные страницы через инструменты разработчика.

Основная настройка находится не в диалогах, а в структуре HTML и таблицах стилей. Правила @page определяют размер листа и поля, селекторы левых, правых, первых и именованных страниц меняют оформление отдельных участков, а margin-boxes выводят номера, названия глав и другие повторяющиеся элементы. Параметры команды дополняют эту модель: выбирают носитель print или screen, добавляют CSS и JavaScript, создают закладки PDF, управляют тайм-аутом и задают разрешённые каталоги либо домены.

Скачать Paged.js CLI

Оценка 9.7 Рекомендуем
  • Редактирование PDF
  • Русский интерфейс
  • Просто новичкам
Скачать бесплатно на Windows
Лучшая альтернатива
Paged.js CLI
Оценка 8.5
  • Нет визуального редактора
  • Нужны Node.js и Chromium
  • Не редактирует готовый PDF
Скачать Paged.js CLI
Загрузка начнётся после нажатия

Как проходит сборка документа

Проект удобнее организовать так, чтобы входной файл, печатные стили, изображения, шрифты и дополнительные сценарии лежали в предсказуемых подкаталогах. В HTML следует использовать полноценную разметку с корректным элементом head, объявленной кодировкой и ссылками на CSS. Относительные пути разрешаются относительно расположения входной страницы, поэтому перенос проекта на другой компьютер не ломает оформление, если внутренняя структура каталогов остаётся прежней. Внешние ресурсы допустимы, но они делают результат зависимым от сети, сертификатов, доступности сервера и времени ответа. Для отчётов, книг и инструкций надёжнее хранить иллюстрации и шрифты рядом с документом и разрешать движку доступ только к нужным каталогам.

Минимальный вызов содержит вход и имя результата. Команда pagedjs-cli document.html -o document.pdf открывает страницу, внедряет механизм Paged.js, ждёт окончания пагинации и печатает построенное представление. Если параметр -o не указывает нужный каталог, результат окажется там, куда направляет текущая рабочая папка или внутренняя логика имени. В производственном сценарии лучше всегда писать полный предсказуемый путь и заранее создавать каталог назначения. Так сборочный сценарий может однозначно проверить существование файла, его размер и код завершения команды.

Входом может служить файл на диске либо страница, которую Chromium способен открыть. Разница важна для ресурсов: документ с диска использует правила доступа к файловой системе, а страница на сервере загружает стили, изображения и шрифты как сетевые запросы. Если макет использует защищённые материалы, запросам можно передать дополнительные заголовки. Если документ не должен обращаться наружу, режим блокировки удалённых запросов превращает случайную зависимость от сети в явную ошибку, которую проще найти до публикации.

Предпросмотр книжного разворота, подготовленного Paged.js

Что происходит между HTML и PDF

Paged.js не отправляет исходную страницу прямо на обычную печать. Сначала модуль разбивки исследует поток содержимого, измеряет доступную область страницы и создаёт последовательность контейнеров. Модуль обработки CSS преобразует правила страничных носителей в конструкции, понятные Chromium, а обработчики добавляют вычисляемые элементы: счётчики, строки, ссылки на цели и повторяющиеся области полей. После завершения этой стадии в документе появляются элементы с классами Paged.js, каждый из которых соответствует отдельному листу. Уже это представление передаётся функции создания PDF.

Из такой архитектуры следует практическое правило: ошибку нужно искать на той стадии, где она возникла. Если ресурс не загружается, проверяют путь, доступ и сетевой запрос. Если текст есть, но переносится не туда, исследуют CSS разрывов и размер области содержимого. Если в режиме отладки страницы выглядят правильно, а в PDF пропадает фон или меняется формат, проверяют параметры печати Chromium. Разделение диагностики экономит время, потому что изменение случайных свойств в исходном файле редко исправляет проблему, возникшую уже при печати.

Подготовка входного HTML

Семантическая разметка помогает управлять длинным документом точнее, чем набор безымянных блоков. Главы удобно оформлять элементами section или article с понятными классами, заголовки оставлять настоящими h2–h4, таблицам задавать thead и tbody, а иллюстрации объединять с относящимся к ним текстом. Тогда CSS может назначать разрыв перед каждой главой, запрещать отделение заголовка от первого абзаца, повторять шапку таблицы и строить закладки по тегам заголовков. Избыточные контейнеры без назначения усложняют измерение высоты и создают неожиданные точки фрагментации.

Для печати полезно отделить экранные стили от правил, влияющих на страницы. Общая типографика может находиться в основном CSS, а размеры листа, поля, колонтитулы, разрывы и печатные метки — в отдельном файле, подключаемом для media print. Параметр --style позволяет добавить такой файл перед рендерингом, не меняя исходную страницу. Это удобно, когда один HTML используется для сайта, электронной инструкции и нескольких печатных форматов. Каждый вариант получает собственный печатный CSS и собственную команду сборки.

Сценарии страницы должны завершать изменение содержимого до начала окончательной пагинации. Если таблица заполняется асинхронно, формулы преобразуются после загрузки или изображения получают размеры с задержкой, ранняя печать создаёт пустые области, неверные номера и повторную разбивку. Надёжный проект либо формирует готовый HTML заранее, либо использует обработчик, который ждёт нужного события и только затем разрешает Paged.js продолжить работу. Увеличение тайм-аута помогает лишь тогда, когда операция действительно завершается; оно не исправляет бесконечный запрос или исключение JavaScript.

Относительные пути и базовый адрес

Путь вроде images/chart.png вычисляется от адреса HTML, а путь в добавленном CSS — от самого CSS-файла по правилам браузера. Из-за этого одинаковая строка может указывать на разные места. При переносе стиля в подкаталог следует пересчитать ссылки на шрифты и фоны либо использовать структуру, в которой каждый CSS хранит ресурсы рядом с собой. Диагностировать ошибку проще в режиме отладки: вкладка Network показывает фактический адрес запроса, код ответа и причину блокировки.

Пути с пробелами и национальными символами обычно обрабатываются Chromium, но командная оболочка может разделить их до запуска программы. Вызов нужно заключать в кавычки, а в сценариях автоматизации передавать аргументы массивом, а не собирать одну длинную строку. Тот же принцип относится к имени выходного PDF. Если команда работает вручную, но падает из задачи сборки, первым делом сравнивают текущую папку, пользователя процесса, переменные среды и доступные каталоги.

Формат страницы, ориентация и размеры

Главным местом для определения геометрии остаётся правило @page. Свойство size принимает стандартный формат или пару размеров, а margin задаёт область между краем листа и основным содержимым. Например, макет книги может использовать компактный формат и увеличенное внутреннее поле, а технический отчёт — A4 с одинаковыми отступами. CSS хранит эти решения рядом с остальной версткой, поэтому команда остаётся короткой и воспроизводимой.

Параметр --page-size полезен, когда формат выбирается на уровне задания, а исходный CSS менять нельзя. Флаги --width и --height задают размеры в миллиметрах и подходят для нестандартных листов, этикеток или вкладышей. Не следует одновременно задавать противоречащие размеры в CSS и командной строке: браузер должен выбрать одно значение, а результат становится труднее предсказывать. В проекте стоит заранее определить приоритет и использовать второй механизм только как осознанное переопределение.

Флаг --landscape меняет ориентацию печати. Он удобен для отдельного отчёта, целиком состоящего из широких таблиц, но не решает задачу смешанной ориентации внутри одного документа. Для отдельных альбомных участков применяют именованные страницы с собственным размером либо собирают части раздельно и объединяют позже. При этом нужно заранее проверить нумерацию и закладки, потому что постобработка нескольких PDF отличается от единого потока Paged.js.

Поля, bleed и печатные метки

Поля страницы определяют место не только для белого пространства, но и для margin-boxes. Если верхнее поле слишком мало, колонтитул может наложиться на текст или выйти за видимую область. Сначала задают физический размер поля, затем размещают содержимое в верхних, нижних и боковых областях, после чего проверяют длинные названия глав и двузначные номера. Колонтитул должен выдерживать самый неблагоприятный текст, а не только короткий пример на первой странице.

Свойства bleed и marks предназначены для макетов, которые будут обрезаться после печати. Фон или изображение, доходящее до края, продолжают за линию реза, а метки помогают совместить операции типографии. Эти свойства следует согласовать с требованиями принимающей стороны: сам факт наличия меток не гарантирует правильный цветовой профиль, разрешение растров или допустимый размер выпуска. Paged.js CLI формирует геометрию страницы, но проверка допечатных параметров остаётся отдельной стадией.

Схема заполненных областей полей страницы Paged.js

Левые, правые и первые страницы

Селекторы @page :left и @page :right позволяют зеркалить внутренние и внешние поля разворота. На левой странице внутренним является правое поле, на правой — левое. Там же меняют расположение номера, чтобы он всегда находился у внешнего края. Такой подход работает лучше фиксированного выравнивания, потому что сохраняет симметрию после вставки или удаления страниц.

Селектор первой страницы подходит для титула или начала раздела, где не нужен обычный верхний колонтитул. Важно различать первую страницу всего документа и первую страницу именованного раздела. Если каждая глава должна начинаться особым листом, ей назначают имя страницы или собственный класс с разрывом и соответствующим правилом. Иначе селектор сработает один раз, а последующие главы унаследуют обычное оформление.

Пустые страницы могут появляться намеренно, когда глава обязана начинаться справа. Их оформление задают отдельно: обычно убирают номер, колонтитулы и декоративные линии. Не стоит удалять такой лист только потому, что на нём нет текста; он поддерживает логику разворота. Если пустота возникла неожиданно, проверяют сочетание break-before, обязательной стороны и остатка предыдущего содержимого.

Именованные страницы

Именованная страница связывает элемент документа с отдельным правилом @page. Например, класс chapter может использовать книжный формат, класс wide-table — альбомный лист, а title — титульное оформление без номера. Свойство page назначается контейнеру, после чего движок выбирает соответствующую геометрию при создании листов. Это позволяет менять поля, фон и margin-boxes без разрыва логической структуры HTML.

Назначать имя лучше крупному блоку, который действительно образует самостоятельную часть. Если имя меняется на маленьком фрагменте внутри абзаца, движку приходится завершать текущую страницу, создавать новую и затем возвращаться к прежнему правилу, что порождает лишние листы. Для широкого рисунка или таблицы разумнее обернуть объект в секцию и явно определить разрывы до и после неё.

Пример разных именованных страниц в одном документе Paged.js

При смешении размеров особенно внимательно проверяют фон, метки обреза и нумерацию. Счётчик страниц продолжает идти по всему документу, если его не сбросить, а поля каждого имени рассчитываются независимо. Одинаковая величина верхнего отступа может визуально выглядеть по-разному на портретном и альбомном листе, поэтому проверку проводят на готовом развороте, а не только по числам в CSS.

Разрывы и фрагментация содержимого

Свойства break-before, break-after и break-inside управляют точками, где поток может перейти на следующую страницу. Разрыв перед главой обеспечивает стабильное начало, запрет разрыва внутри небольшой карточки удерживает её целиком, а требование правой страницы создаёт при необходимости пустой лист. Однако запрет нельзя воспринимать как абсолютный, если объект физически выше доступной области: браузеру всё равно придётся его разделить или вывести за границы.

Для заголовков эффективнее правило, запрещающее разрыв сразу после них, чем попытка вручную вставлять пустые блоки. Для абзацев работают свойства widows и orphans, задающие минимальное число строк в начале и конце фрагмента. Слишком большие значения создают обширные пробелы, особенно при коротких страницах и крупных шрифтах. Оптимальное значение выбирают на реальном тексте и проверяют после каждой заметной смены гарнитуры или ширины колонки.

Фрагментация flex- и grid-контейнеров сложнее обычного блочного потока. Макет, идеально выглядящий на экране, может плохо делиться между листами из-за фиксированной высоты, выравнивания по центру или зависимости размеров дочерних элементов. Для длинных печатных документов безопаснее использовать обычный поток там, где содержимое должно естественно переходить на следующую страницу, а grid оставлять для ограниченных по высоте элементов: обложек, карточек и панелей.

Таблицы на нескольких страницах

Корректная семантика таблицы позволяет Chromium повторять группу заголовков и отделять тело от итоговой строки. В HTML нужно использовать thead, tbody и при необходимости tfoot, а в CSS избегать фиксированной высоты всей таблицы. Длинная строка с большим текстом может разделиться не так, как ожидается; если строка должна оставаться целой, ей задают запрет внутреннего разрыва, но только при уверенности, что она помещается на лист.

Широкую таблицу сначала пытаются сделать компактнее: уменьшить внутренние отступы, переносить слова, скрыть второстепенные столбцы или вынести подробности в приложение. Масштабирование всего документа ухудшает читаемость остальных страниц. Если ширины всё равно не хватает, таблице назначают именованную альбомную страницу. В таком случае проверяют, что переход назад к обычному формату происходит после контейнера таблицы, а не после последней строки.

Повторяемая шапка должна быть короткой. Многострочный заголовок съедает высоту на каждом листе и может вступить в конфликт с верхним колонтитулом. Полезно также задать явные ширины столбцов и тестировать длинные значения: адреса, идентификаторы и непрерывные строки часто расширяют таблицу сильнее, чем демонстрационные данные.

Колонтитулы, номера и содержимое полей

Margin-boxes находятся внутри полей страницы и заполняются свойством content. Для номера используют counter(page), для общего числа — counter(pages). Текст можно объединять со счётчиком, но оформление задаётся обычными свойствами шрифта, выравнивания и границ. Важно оставить полю достаточно места: длинная строка не расширяет физическое поле, а перенос может увеличить высоту и приблизить колонтитул к основному тексту.

Разные стороны разворота могут получать разное выравнивание и содержимое. На внешнем крае ставят номер, на внутреннем — название книги или раздела. Для титула и пустых листов соответствующие области очищают. Такой CSS надёжнее добавления колонтитула в HTML, потому что повторение происходит на уровне страницы и не зависит от ручных копий.

Повернутый текст в боковой области поля страницы Paged.js

Боковые области позволяют выводить повернутые метки, название серии или навигацию, но их нужно проверять на реальном устройстве просмотра. Некоторые программы показывают обрезку иначе, чем Chromium в режиме отладки. Если элемент подходит слишком близко к краю, следует увеличить поле или уменьшить длину, а не рассчитывать на то, что зритель всегда откроет документ без масштабирования.

Бегущие заголовки через string-set

Механизм строк берёт текст из элемента потока и сохраняет его под именем. Заголовок главы может присвоить значение через string-set, а верхняя область страницы вывести его функцией string(). При переходе к следующей главе строка обновляется автоматически. Это избавляет от копирования названий и сохраняет правильный колонтитул после изменения порядка разделов.

Нужно решить, какое значение показывать на странице с новым заголовком: первое найденное, последнее или значение, действовавшее в начале листа. Выбор влияет на страницы, где предыдущая глава заканчивается, а следующая начинается ниже. Тестировать следует именно пограничные листы, потому что середина главы почти всегда выглядит правильно и не выявляет спорную семантику.

Предпросмотр бегущих заголовков на страницах Paged.js

Если в заголовке есть номер, декоративный элемент или скрытый текст, строка может получить нежелательное содержимое. Для колонтитула лучше выделить отдельный текстовый узел либо использовать атрибут, значение которого однозначно. Так верстальщик контролирует регистр, сокращение и знаки препинания независимо от видимого заголовка.

Нумерация разделов, рисунков и ссылок

CSS-счётчики подходят не только для страниц. Главам, рисункам, таблицам и примерам можно назначить собственные последовательности. Номер формируется из структуры документа, поэтому вставка нового объекта автоматически сдвигает последующие значения. Контент псевдоэлемента становится частью визуального результата, но для доступности и дальнейшей обработки важные номера иногда лучше сохранять и в разметке.

Функции ссылок на цель позволяют вывести номер страницы, на которой расположен указанный элемент. Так собирают оглавление и перекрёстные ссылки без ручного пересчёта. Каждая цель должна иметь уникальный идентификатор, а ссылка — корректный фрагмент. После изменений полезно проверять не только отображаемое число, но и кликабельность PDF, потому что видимый текст и интерактивная аннотация формируются разными механизмами.

Если оглавление заполняется до окончательной пагинации, номера могут повлиять на ширину строк, вызвать перенос и тем самым изменить сами номера. Paged.js выполняет необходимые проходы, однако сложный пользовательский обработчик может нарушить этот порядок. Признак проблемы — нестабильный результат между одинаковыми запусками. Тогда временно отключают дополнительные сценарии, упрощают оглавление и возвращают изменения по одному.

Закладки и структура PDF

Параметр --outline-tags создаёт иерархию закладок по выбранным HTML-тегам. Запись h1,h2 означает, что первый тег образует верхний уровень, а второй — дочерний. В статье без h1 можно выбрать h2,h3. Порядок тегов должен соответствовать реальной структуре; пропуск уровней и использование заголовка только ради крупного шрифта приводят к неудобной панели навигации.

Перед включением закладок стоит привести текст заголовков к форме, понятной читателю вне страницы. Слишком длинная формулировка занимает панель, а повторяющиеся названия не дают понять, куда ведёт переход. Декоративные номера можно оставить, если они помогают сопоставить дерево с содержанием. Скрытые служебные заголовки лучше не включать в список тегов.

Закладки не заменяют оглавление. Оглавление печатается внутри документа и сохраняет номера страниц, а дерево PDF служит быстрым переходом в программе просмотра. Для большой инструкции полезны оба механизма. После сборки проверяют верхний и нижний уровни, переход на первую строку раздела и отсутствие пустых пунктов.

Добавление CSS без изменения страницы

Опция --style подключает дополнительную таблицу стилей перед рендерингом. Её можно применять повторно, разделяя базовую типографику, формат листа, фирменное оформление и исправления для конкретного выпуска. Порядок подключения влияет на каскад, поэтому более специфичные переопределения помещают позже и не злоупотребляют !important. Когда почти каждое правило требует усиления, проще пересмотреть структуру каскада.

Дополнительный стиль удобен для скрытия экранной навигации, кнопок, интерактивных панелей и других элементов, которые не должны попадать в печать. При этом нельзя удалять блоки, от которых зависит JavaScript страницы, до выполнения нужных вычислений. Безопаснее скрывать их через print-правила или удалять в обработчике на известной стадии.

Для нескольких форматов можно создать команды вроде книга, A4 и черновик, каждая из которых подключает свой CSS и пишет результат под отдельным именем. Такой подход делает различия явными и проверяемыми. Копирование всего HTML для каждого формата быстро приводит к расхождению текста, тогда как общий документ с разными слоями стилей сохраняет единый контент.

Дополнительные сценарии и обработчики

Параметр --additional-script внедряет JavaScript до рендеринга и может повторяться. Основное назначение — подключение пользовательских обработчиков Paged.js. Они получают доступ к этапам разбора, создания страниц и завершения потока, поэтому способны менять узлы, добавлять классы, собирать сведения и исправлять случаи, которые нельзя выразить одним CSS.

Обработчик должен быть узким и предсказуемым. Если он переписывает большие части DOM, добавляет сетевые запросы и зависит от случайного времени, диагностика становится сложнее. Полезно разделять задачи: один файл отвечает за сноски, другой — за специфические таблицы, третий — за контроль переполнения. При ошибке их отключают по одному и быстро находят виновника.

Любое изменение, влияющее на размеры, нужно выполнять до окончательной разбивки либо сопровождать осознанным повторным расчётом. Добавление изображения после создания страниц может вытолкнуть текст, не обновив номера. Изменение только атрибута, который не меняет геометрию, безопаснее. В отладочном окне следует смотреть консоль: необработанное исключение в дополнительном сценарии часто объясняет пустой PDF лучше, чем сообщения самой команды.

Когда отключать автоматическое внедрение

Флаг --disable-script-injection запрещает автоматическое добавление полифилла. Он нужен, когда страница уже загружает подходящую сборку Paged.js или когда разработчик полностью управляет последовательностью сценариев. Обычному проекту этот режим не требуется: без механизма пагинации страница останется обычным длинным полотном, а браузер напечатает её по собственным правилам.

Если полифилл подключён дважды, возможны повторная разбивка, дублированные страницы и обработчики, срабатывающие два раза. При таких симптомах проверяют head документа и список дополнительных сценариев. Выбирают один способ подключения и фиксируют его в сценарии сборки, чтобы коллеги не добавляли вторую копию для надёжности.

Выбор print или screen media

По умолчанию CLI эмулирует печатный носитель. Поэтому правила внутри @media print активны, а экранные могут не применяться. Параметр --media screen нужен, когда PDF должен повторять экранное оформление или когда проект сознательно хранит нужные правила в screen. Это не просто косметическое переключение: меняются display, цвета, размеры, скрытые элементы и даже загружаемые ресурсы.

Если результат неожиданно лишён навигации или, наоборот, содержит элементы сайта, проверяют медиа-запросы до изменения отдельных селекторов. В инструментах разработчика можно вручную эмулировать print и сравнить вычисленные стили. В стабильном проекте печатные правила должны быть достаточно самостоятельными, чтобы их поведение не зависело от случайного порядка экранных файлов.

Тайм-аут и ожидание ресурсов

Опция --timeout задаёт максимальное время операции. Она защищает автоматизацию от зависшего браузера, недоступного шрифта или страницы, которая никогда не сообщает о завершении. Значение выбирают с запасом относительно обычного времени большого документа. Слишком короткий предел даёт случайные падения на медленной машине, а чрезмерно длинный заставляет задачу долго ждать заведомо неисправный запрос.

При превышении времени сначала запускают тот же вход с --debug и смотрят Network и Console. Частые причины — адрес, недоступный из контейнера, сертификат, бесконечная загрузка, сценарий с ошибкой и слишком тяжёлое изображение. Затем блокируют удалённые запросы или временно заменяют ресурсы, чтобы отделить сетевую проблему от сложности пагинации.

Большой документ может быть медленным без единой ошибки. На время влияют количество узлов, сложность селекторов, число страниц, шрифты, прозрачности и обработчики. Профилирование начинают с измерения нескольких последовательных запусков на одной машине. Затем упрощают самый дорогой компонент и сравнивают, а не делают вывод по одному субъективному ожиданию.

Доступ к файлам и сетевым ресурсам

Флаг --blockLocal запрещает чтение файлов с диска. Он полезен при рендеринге недоверенного HTML, который не должен обращаться к произвольным путям. Параметр --allowedPath формирует список разрешённых каталогов и повторяется для нескольких мест. Практически это означает, что документу можно открыть только папку проекта и каталог шрифтов, не выдавая доступ ко всему профилю пользователя.

Флаг --blockRemote запрещает сетевые запросы, а --allowedDomain оставляет доступ только к нужным доменам. Это снижает риск скрытой загрузки и делает сборку воспроизводимее. Следует учитывать косвенные запросы: CSS может загружать шрифт, изображение — перенаправляться, а сценарий — обращаться к API. Белый список формируют после наблюдения за реальными запросами, а не по одному имени главной страницы.

Ограничения доступа способны объяснить отсутствующую картинку при отсутствии заметной ошибки в верстке. Включение предупреждений через --warn и просмотр сетевой панели помогают увидеть блокировку. Не следует решать проблему полным снятием защиты в постоянной задаче; лучше добавить конкретный путь или домен и сохранить минимальные права.

Дополнительные заголовки запросов

Опция --extra-header добавляет заголовок к запросу страницы и может повторяться. Она применяется, когда внутренний сервер требует токен, специальный Host, язык или иной контекст. Секрет нельзя записывать в общий сценарий или журнал. Его передают через защищённую переменную среды и следят, чтобы команда не печаталась целиком в публичном логе.

Заголовок не исправит авторизацию, основанную на интерактивном входе, одноразовом подтверждении или сложной сессии. Для таких страниц надёжнее заранее получить готовый HTML либо использовать удалённый браузер с подготовленным профилем, если это допускает политика проекта. Любой защищённый сценарий проверяют на отсутствие случайного включения личных данных в итоговый PDF.

Удалённый Chromium и аргументы браузера

Параметр --browserEndpoint подключает CLI к уже запущенному Chrome через WebSocket endpoint. Это полезно в инфраструктуре, где браузеры вынесены в отдельный сервис, заранее прогреты или запускаются с корпоративными сертификатами. Адрес должен быть доступен из среды команды, а версия протокола — совместима с используемым Puppeteer. При разрыве соединения задача завершится ошибкой, поэтому сервису нужны мониторинг и ограничение числа параллельных вкладок.

Параметр --browserArgs передаёт Chromium список аргументов через запятую. Ими задают прокси, сертификаты, графический режим и другие параметры запуска. Особенно осторожно следует относиться к отключению песочницы: такой флаг иногда используют в контейнере, но он уменьшает изоляцию. Безопаснее настроить контейнер и профиль seccomp так, чтобы Chromium мог работать с защитой.

Различия между встроенным и удалённым браузером могут проявиться в шрифтах, доступных кодеках и поведении печати. Поэтому эталонный PDF создают в той же среде, где будет выполняться регулярная сборка. Результат, проверенный на рабочем ноутбуке, не гарантирует идентичность на сервере с другим набором шрифтов.

Отладочный режим

Флаг --debug вместо немедленной записи PDF показывает результат в окне браузера. В DOM видны контейнеры страниц, области содержимого, margin-boxes и элементы, перенесённые между листами. Инспектор позволяет выбрать проблемный узел, увидеть вычисленный break, размер и переполнение. Это главный инструмент для ошибок, которые невозможно понять по терминальному сообщению.

Отладочный интерфейс Paged.js с сеткой базовых линий и областями полей

Полезно включить визуальные правила: контуры страниц, подсветку области контента, базовую сетку и полупрозрачные фоны margin-boxes. Они не входят в финальный PDF, если подключены только в отладочном стиле. Цветная граница быстро показывает, какой контейнер создаёт лишнюю высоту, а сетка помогает сравнить вертикальный ритм на развороте.

При исследовании перенесённого элемента нужно смотреть не только его исходный узел, но и созданные фрагменты. Paged.js может клонировать оболочку и разделить содержимое. Стиль, завязанный на :first-child, :last-child или соседний селектор, после фрагментации иногда ведёт себя иначе. Надёжнее использовать явный класс или обработчик, который отмечает начало и конец фрагмента.

Вывод промежуточного HTML

Флаг --html сохраняет HTML-представление вместо обычного PDF-результата. Такой файл полезен для исследования созданной структуры, сравнения двух сборок и поиска классов, добавленных Paged.js. Его не следует воспринимать как исходный редактируемый документ: в нём много технических контейнеров, рассчитанных на конкретную пагинацию.

Промежуточный HTML помогает автоматическому контролю. Сценарий может подсчитать страницы, найти элементы с признаком переполнения или убедиться, что каждая глава получила ожидаемое имя страницы. Проверка структуры дополняет визуальное сравнение PDF и быстрее указывает место сбоя.

Фоны и прозрачность

Опция --forceTransparentBackground принудительно оставляет фон прозрачным. Она нужна для специфической последующей обработки, но обычный документ чаще ожидает белый лист. Прозрачность может выглядеть тёмной в некоторых программах просмотра и взаимодействовать с изображениями при наложении. Перед применением следует проверить весь дальнейший процесс, а не только окно Chromium.

Если цветной фон не попадает в PDF без этой опции, причина обычно находится в print-стиле или параметрах печати. Проверяют print-color-adjust, фон самого page-box и отсутствие screen-only правил. Важные цветовые плашки лучше тестировать на нескольких страницах: край, bleed и прозрачность могут различаться у центрального блока и margin-box.

Шрифты и типографика

Chromium использует доступные системе шрифты и web-fonts, загруженные страницей. Для стабильного результата гарнитуру размещают в проекте, объявляют через @font-face и указывают форматы, которые понимает браузер. Если шрифт не найден, подстановка меняет ширину строк, число страниц и положение ссылок. Поэтому визуально похожая замена всё равно считается ошибкой верстки.

Начертания подключают отдельно: normal, italic, нужные веса. Искусственное утолщение и наклон могут отличаться на сервере. После загрузки нужно дождаться готовности набора шрифтов до пагинации. Симптом раннего расчёта — первый запуск даёт другой перенос, чем второй, когда файлы уже находятся в кэше.

Для русского текста проверяют набор кириллицы, кавычки, длинное тире, неразрывные пробелы и переносы. CSS-свойство hyphens зависит от языка элемента, поэтому в HTML указывают корректный lang. Без него браузер может не переносить длинные слова, и узкая колонка получит большие пробелы или выход текста за край.

Изображения, SVG и качество печати

Растровая иллюстрация должна иметь достаточное физическое разрешение для размера, в котором она печатается. Большое число пикселей само по себе не помогает, если CSS растягивает маленький файл на весь лист. Одновременно чрезмерные изображения увеличивают память и время. Их подготавливают под максимальный ожидаемый размер с разумным запасом и выбирают формат по содержимому.

SVG подходит для схем, логотипов и графиков: линии сохраняют чёткость при масштабировании, а текст может оставаться векторным. Однако внешние ресурсы внутри SVG подчиняются тем же правилам доступа, что и HTML. Сложные фильтры и маски следует проверять в итоговом PDF; экранный предпросмотр не всегда гарантирует одинаковую печать.

Чтобы рисунок не отделялся от подписи, оба элемента объединяют в контейнер и запрещают разрыв внутри, пока блок помещается на страницу. Для крупной иллюстрации лучше разрешить контролируемый разрыв перед ней и задать максимальную высоту относительно листа. Фиксированная высота без object-fit искажает пропорции.

Математические формулы

В составе зависимостей CLI присутствуют KaTeX и MathJax, а практический макет может преобразовывать формулы перед пагинацией. Главное условие — завершить генерацию математического DOM и загрузку шрифтов до измерения страниц. Формула, появившаяся позднее, изменяет высоту строки и сдвигает последующие номера.

Длинные формулы плохо переносятся автоматически. Для них задают отдельный блочный контейнер, масштабирование или правила переноса, а особо широкие выражения выносят на отдельную страницу. Уменьшение всего текста ради одной формулы ухудшает документ. В отладке проверяют переполнение каждой формулы и наличие используемых математических шрифтов.

Если формулы видны в окне, но исчезают в задаче без сети, значит библиотека или шрифт загружаются удалённо. Материалы следует включить в проект и разрешить соответствующий каталог. При строгой блокировке это одновременно повышает воспроизводимость и исключает отправку содержимого стороннему серверу.

Пакетная и автоматическая сборка

Для серии документов создают сценарий, который перебирает входные файлы и запускает CLI с одинаковым набором параметров. Каждый результат получает однозначное имя, отдельный журнал и код состояния. Параллельный запуск ускоряет работу, но каждый Chromium потребляет заметную память. Число процессов ограничивают по ресурсам машины и измеряют на самом тяжёлом документе.

В системе непрерывной интеграции устанавливают зависимости из зафиксированного lock-файла, добавляют нужные шрифты и сохраняют результат как артефакт задачи. Различия окружения сводят к минимуму контейнером. Официальный проект содержит Dockerfile и пример запуска с профилем seccomp; при адаптации образа важно не удалить системные библиотеки, необходимые Chromium.

После команды проверяют не только код ноль. Полезны минимальный размер PDF, ожидаемый диапазон страниц, наличие ключевого текста и отсутствие пустых листов. Для критичного выпуска сравнивают визуальные снимки страниц с эталоном. Такая проверка ловит ситуацию, когда браузер успешно создал файл, но подставил другой шрифт или не загрузил изображения.

Стабильность повторных запусков

Одинаковые входы и окружение должны давать одинаковую структуру страниц. Случайное различие обычно указывает на дату, текущее время, нестабильный порядок данных, сетевую зависимость или гонку сценариев. Динамические значения передают в HTML как явные параметры, сортируют коллекции и отключают обращения к непредсказуемым сервисам.

Побитовое совпадение PDF не всегда возможно из-за метаданных и внутренних идентификаторов, поэтому контроль строят на рендеринге страниц либо на извлечённом тексте и геометрии. Важен пользовательский результат: одинаковые переносы, колонтитулы, изображения и ссылки. Сравнение одного размера файла недостаточно.

Типовые ошибки запуска

Команда не найдена

Сообщение о неизвестной команде означает, что пакет не установлен в доступной области или каталог глобальных npm-команд отсутствует в PATH. Сначала проверяют node и npm, затем выполняют установку и открывают новое окно терминала, чтобы среда перечитала PATH. В проекте с локальной зависимостью команду вызывают через npm script или npx, не полагаясь на глобальную установку.

На машине с несколькими менеджерами Node.js пакет может установиться для одной среды, а команда выполняться в другой. Сравнивают пути к node, npm и pagedjs-cli. Не следует копировать исполняемый файл вручную: рядом с ним находятся зависимости, и разрозненная копия быстро ломается.

Chromium не запускается

Ошибка запуска браузера часто связана с отсутствующими системными библиотеками, правами на временный каталог, неподходящей архитектурой или ограничениями контейнера. Текст ошибки Puppeteer обычно содержит имя библиотеки или рекомендацию. Устанавливают системные зависимости для используемого дистрибутива и проверяют простой запуск браузера до анализа HTML.

В контейнере не стоит автоматически добавлять флаг отключения песочницы. Сначала используют рекомендованный профиль безопасности, непривилегированного пользователя и корректные права. Если политика всё же требует особого аргумента, риск документируют и не запускают недоверенные входы в той же среде.

PDF пустой или содержит одну пустую страницу

Сначала проверяют, открывается ли вход в режиме debug и есть ли содержимое до пагинации. Причиной бывает неверный путь, редирект на страницу входа, CSS с display:none для print, ошибка сценария или отключённое внедрение Paged.js. В сетевой панели убеждаются, что загружен именно ожидаемый HTML, а не сообщение сервера.

Если DOM заполнен, исследуют размеры контейнера. Абсолютно позиционированный корневой блок, нулевая высота, transform и фиксированная область просмотра могут не дать нормального потока. Временно отключают сложную раскладку и возвращают правила по одному.

Не загружаются изображения или стили

Проверяют фактический адрес запроса, код ответа и настройки blockLocal, blockRemote, allowedPath и allowedDomain. Ошибка регистра в имени файла часто незаметна на одной файловой системе и проявляется на другой. Для CSS учитывают его собственный базовый путь. После исправления очищают кэш или запускают в чистом профиле, чтобы не принять старый ресурс за новый.

Если сервер требует заголовок, добавляют его через соответствующую опцию и следят за перенаправлением: новый домен тоже должен входить в белый список. Для надёжной публикации лучше убрать такую зависимость и хранить статические материалы рядом с документом.

Неверный формат или обрезанные края

Сравнивают @page size с параметрами page-size, width, height и landscape. Затем измеряют поля и bleed. Объект с шириной 100vw может ориентироваться на область просмотра, а не на печатную область; для страницы предпочтительнее проценты контейнера или физические единицы. Также проверяют transform и отрицательные поля.

Если проблема видна только в одной программе просмотра, открывают PDF в другом движке и исследуют MediaBox, CropBox и BleedBox. Это помогает отличить неверную геометрию от способа отображения. Для типографии используют её требования к коробкам страницы.

Колонтитул дублируется или отстаёт на главу

Дублирование обычно возникает при одновременном HTML-колонтитуле и margin-box либо при двойном подключении полифилла. Отставание бегущей строки связано с выбором значения на пограничной странице. Уточняют режим string(), тестируют страницу смены главы и удаляют ручные копии повторяющегося текста.

Если название слишком длинное, оно может перенестись и выглядеть как дубль. Ограничивают размер, используют сокращённое значение из атрибута или задают одно строковое представление. Нельзя просто скрыть переполнение, если обрезка делает названия неразличимыми.

Лишняя пустая страница

Проверяют требование recto, right или left, разрывы до и после раздела и высоту предыдущего элемента. Комбинация явного page break с началом на правой стороне часто создаёт два перехода. Оставляют одно правило, которое выражает реальное требование. Небольшое переполнение предыдущей страницы тоже способно создать лист с невидимой строкой; подсветка контейнеров показывает такой фрагмент.

Таблица выходит за край

Находят столбец, который не умеет сжиматься: непрерывный идентификатор, pre, изображение или элемент с min-width. Добавляют перенос, ограничение ширины и подходящий table-layout. Если данные требуют ширины, назначают таблице альбомную именованную страницу вместо уменьшения шрифта до нечитаемого размера.

Сборка зависает

Ограничивают время через timeout, запускают debug и смотрят незавершённые запросы. Затем повторяют с blockRemote, без дополнительных сценариев и с упрощённым HTML. Если зависание исчезло, возвращают компоненты по одному. Такой двоичный поиск быстрее полного чтения большого стиля.

Практический сценарий: книга или методическое пособие

Структуру книги делят на титул, выходные сведения, оглавление, главы и приложения. Каждая глава получает класс, разрыв перед началом и строку для бегущего заголовка. Развороты используют зеркальные поля, номер выводится снаружи, а пустая страница очищается. Оглавление строит номера через ссылки на цели, закладки формируются по заголовкам глав и подразделов.

Перед выпуском проверяют четыре типа листов: начало главы справа, продолжение главы слева, лист с иллюстрацией и пустой оборот. Затем смотрят самую длинную главу, самое длинное название и переход к приложению. Такой набор быстрее обнаруживает системные дефекты, чем последовательный просмотр только первых страниц.

Практический сценарий: отчёт с данными

HTML отчёта формируют из проверенных данных до запуска CLI. Основные таблицы остаются портретными, а особенно широкие секции получают именованную альбомную страницу. Заголовок отчёта, дата данных и идентификатор выпуска выводятся в margin-box или на титуле. Сетевые графики заменяют встроенными SVG или файлами, чтобы повторный запуск не зависел от панели аналитики.

Автоматическая проверка убеждается, что присутствуют все разделы, число таблиц не нулевое и нет маркеров данные загружаются. Для конфиденциального отчёта включают блокировку сети и белый список путей. Так HTML не сможет незаметно обратиться к внешнему пикселю или загрузить изменившийся ресурс.

Практический сценарий: счета и персональные документы

Шаблон счёта должен выдерживать короткие и длинные реквизиты, много строк и перенос на второй лист. Шапку таблицы повторяют, итог удерживают рядом с последними строками, а реквизиты не фиксируют абсолютной высотой. Каждый документ собирают из отдельного HTML или из одного шаблона с заранее подставленными данными.

В пакетной задаче имя PDF строят из безопасного внутреннего идентификатора, а не из произвольного имени клиента. Журнал не должен раскрывать содержимое. После сборки проверяют, что сумма, номер и получатель присутствуют, а число страниц разумно. Для электронного обмена отдельно решают подпись и стандарты долгосрочного хранения: CLI отвечает за макет, а не за юридическую подпись.

Практический сценарий: техническая документация

Инструкции выигрывают от семантических заголовков, автоматических закладок и стабильных ссылок на рисунки. Блоки кода оформляют с переносом или контролируемым горизонтальным уменьшением, потому что длинная строка способна расширить страницу. Предупреждения объединяют в контейнер, который не разрывается, если помещается целиком.

Для каждого языка создают готовый HTML с корректным атрибутом lang и подходящими шрифтами. Длины текстов различаются, поэтому нельзя переносить координаты из одной локализации. Одинаковая таблица стилей должна быть протестирована на самых длинных строках каждого языка.

Установка и проверка рабочей среды

Перед первой сборкой проверяют, что команды node и npm доступны из того же терминала, где будет запускаться Paged.js CLI. Установка выполняется командой npm install -g pagedjs-cli. Глобальный способ удобен для ручной работы, но команду проекта лучше закреплять и как зависимость разработки: тогда сценарий npm использует пакет из node_modules и не зависит от содержимого профиля другого пользователя. Оба варианта нельзя смешивать без контроля, иначе ручной вызов и автоматическая задача могут обратиться к разным наборам файлов.

После установки полезно вызвать справку и выполнить пробную сборку небольшого HTML. Справка подтверждает, что оболочка видит именно нужную команду и показывает доступные параметры. Тестовый документ должен содержать русский текст, одну картинку, локальный шрифт и простое правило @page. Такая проверка одновременно обнаруживает проблемы кодировки, доступа к файлам и запуска Chromium.

Пакет Puppeteer загружает или использует совместимый Chromium в рамках своей установки. Если политика компании запрещает автоматическую загрузку браузера, окружение готовят заранее и указывают допустимый способ подключения. В изолированной сети нужно обеспечить доступ ко всем npm-зависимостям через доверенное зеркало, а затем проверить целостность пакетов по lock-файлу. Копирование готового node_modules между разными операционными системами ненадёжно, потому что часть зависимостей и путь к браузеру могут различаться.

Глобальный вызов и сценарий проекта

Глобальная команда удобна для эксперимента: пользователь находится в каталоге макета и пишет pagedjs-cli index.html -o result.pdf. Для регулярной работы в package.json создают сценарий, например "pdf": "pagedjs-cli index.html -o build/result.pdf". После этого сборка запускается через npm, а все участники команды получают одинаковое имя операции. В сценарий можно добавить подготовку каталога, генерацию HTML и последующую проверку результата.

При локальной зависимости вызов через npm script автоматически добавляет node_modules/.bin в PATH. Это избавляет от платформенных различий в пути к исполняемому файлу. В системе непрерывной интеграции сначала выполняют чистую установку по lock-файлу, затем сценарий PDF. Если команда работает только после глобальной установки, проект ещё не является самодостаточным.

Полный разбор параметров команды

Вход и выход

Позиционный аргумент указывает входной документ, а опция -i или --inputs предоставляет явную форму задания входа. В большинстве сценариев достаточно одного HTML, который уже связывает все разделы. Если материал хранится в нескольких файлах, их объединяют на стадии подготовки либо создают главную страницу, загружающую нужное содержимое. Это сохраняет единый порядок пагинации, счётчиков и ссылок.

Опция -o или --output задаёт имя результата. Расширение и каталог указывают явно. Перед запуском проверяют, что родительский каталог существует и процесс может в него писать. Не следует направлять выход поверх входного HTML или CSS. При пакетной обработке временный файл сначала пишут под отдельным именем, проверяют, а затем атомарно заменяют опубликованный PDF, чтобы читатель не получил недописанный результат.

Размеры и ориентация

-s и --page-size выбирают стандартный размер, -w и --width задают ширину в миллиметрах, -h и --height — высоту, а -l и --landscape включают альбомную ориентацию. Эти параметры удобны как внешняя конфигурация задания. Если размеры уже определены в @page, команду не перегружают дублирующими значениями. Один ответственный слой уменьшает вероятность конфликта.

Нестандартную геометрию проверяют измерением готового PDF, а не только визуально. Программа просмотра может автоматически вписать любую страницу в окно и скрыть разницу между 210 и 216 миллиметрами. Для серии этикеток или вкладышей ошибка в несколько миллиметров критична, поэтому контроль должен читать фактический MediaBox.

Debug, HTML и предупреждения

-d или --debug открывает браузерный результат, -x или --html записывает промежуточное HTML-представление, а --warn включает предупреждения. Эти режимы решают разные задачи. Debug нужен для интерактивного инспектора, HTML — для сохранения созданной структуры, warnings — для журнала автоматической задачи. В сложном проекте полезно иметь отдельные npm scripts для каждого режима.

Предупреждение не всегда делает код завершения ошибочным, поэтому журнал нужно анализировать отдельно. Проект может считать некоторые сообщения допустимыми, но список таких исключений должен быть коротким и документированным. Новое предупреждение после изменения стиля рассматривают как регрессию, пока не доказано обратное.

Носитель и фон

--media принимает print или screen. Выбранное значение определяет активные media-запросы до начала измерения. --forceTransparentBackground влияет на фон печати. Комбинацию фиксируют в сценарии, потому что случайный переход на screen способен изменить десятки свойств без заметной ошибки в терминале.

Стили и сценарии

--style добавляет CSS, а --additional-script — JavaScript. Обе опции рассчитаны на повторение, поэтому каждый файл передают отдельным аргументом. Это лучше объединения путей через запятую, если документация конкретной опции не требует такого формата. Порядок аргументов сохраняют осознанно: поздний стиль может переопределить ранний, а обработчик может ожидать класс, созданный предыдущим сценарием.

Сетевые и файловые ограничения

--blockLocal и --blockRemote включают запреты, а повторяемые --allowedPath и --allowedDomain формируют исключения. --extra-header добавляет заголовок в форме имя:значение. Такие параметры особенно важны для задач, которые принимают HTML от других систем. Без ограничений страница выполняется в полноценном браузерном контексте и может обращаться к ресурсам, доступным процессу.

Chromium, тайм-аут и внедрение

--browserEndpoint подключает удалённый браузер, --browserArgs передаёт аргументы запуска через запятую, --timeout ограничивает ожидание, а --disable-script-injection отключает автоматическое внедрение полифилла. Последнюю опцию используют только при собственном управлении Paged.js. Обычная страница без внедрения не получит ожидаемую страничную модель.

Базовый CSS-каркас печатного документа

@page {
  size: A4;
  margin: 20mm 18mm 22mm;

  @bottom-center {
    content: counter(page);
    font-size: 9pt;
  }
}

html {
  font-family: "Document Sans", sans-serif;
  font-size: 10.5pt;
  line-height: 1.45;
}

h2 {
  break-before: page;
  break-after: avoid;
}

p {
  widows: 3;
  orphans: 3;
}

Каркас задаёт физический лист, поля, номер и базовый вертикальный ритм. Разрыв перед h2 подходит документу, где каждый крупный раздел должен начинаться с нового листа; для статьи с короткими разделами его убирают. Значения widows и orphans не гарантируют идеальную страницу, но уменьшают вероятность одинокой строки. После выбора гарнитуры эти параметры проверяют заново, потому что метрика шрифта меняет число строк.

Разворот с зеркальными полями

@page :left {
  margin-left: 18mm;
  margin-right: 25mm;

  @bottom-left {
    content: counter(page);
  }
}

@page :right {
  margin-left: 25mm;
  margin-right: 18mm;

  @bottom-right {
    content: counter(page);
  }
}

@page :blank {
  @bottom-left { content: none; }
  @bottom-right { content: none; }
}

Внутреннее поле разворота сделано шире, а номер перемещается к внешнему краю. Пустая страница очищается. Если документ печатается не разворотами, такое зеркалирование может только мешать; для отдельных листов используют одинаковые поля. Селекторы left и right нужно проверять после титула, потому что вставка ненумерованного листа влияет на физическую сторону последующих страниц.

Именованная альбомная секция

@page wide {
  size: A4 landscape;
  margin: 14mm;
}

.wide-section {
  page: wide;
  break-before: page;
  break-after: page;
}

.wide-section table {
  width: 100%;
  table-layout: fixed;
}

Контейнер получает собственную страницу и явные границы перехода. Такой приём лучше применять ко всей секции, а не к отдельной строке таблицы. После wide-section следующий блок возвращается к обычному неназванному правилу. Если движок создаёт пустой лист, проверяют, не совпали ли break-after секции и break-before следующего заголовка.

Бегущий заголовок главы

.chapter-title {
  string-set: chapter-title content(text);
}

@page :left {
  @top-left {
    content: string(chapter-title);
  }
}

@page :right {
  @top-right {
    content: string(chapter-title);
  }
}

Значение извлекается из текста заголовка и выводится сверху. Для очень длинных названий можно добавить атрибут с сокращённой формой и брать его вместо content(text). Колонтитул не должен повторять декоративный номер или скрытый значок, если они не нужны читателю.

Стабильный блок рисунка

.illustration {
  break-inside: avoid;
  margin: 5mm 0;
}

.illustration img {
  display: block;
  max-width: 100%;
  max-height: 190mm;
  object-fit: contain;
}

.illustration .caption {
  break-before: avoid;
}

Контейнер старается удержать изображение и пояснение вместе. Ограничение высоты не даёт рисунку вытеснить подпись за лист. Если весь блок выше страницы, запрет разрыва не может выполнить невозможное; исходное изображение уменьшают или разрешают рисунку занять отдельный лист.

Контейнерная сборка

Официальный проект предоставляет Dockerfile и пример запуска образа с --init и профилем seccomp. Контейнер фиксирует системные библиотеки Chromium, набор пакетов и рабочую папку. Макет подключают как том или копируют на стадии сборки, а PDF выводят в отдельный каталог. Пользователь внутри контейнера должен иметь право чтения входа и записи выхода.

Флаг --init помогает корректно обрабатывать дочерние процессы браузера и сигналы завершения. Профиль seccomp даёт Chromium необходимые системные вызовы, не отменяя защиту целиком. Запуск от root и отключение sandbox кажутся простым решением, но создают более опасную среду и часто маскируют неправильные права.

Шрифты включают в образ явно. Если контейнер опирается на шрифты хоста, результат меняется между агентами. После установки обновляют шрифтовый кэш и выполняют тест, который печатает все нужные начертания. Для кириллицы проверяют не только основной текст, но и жирный, курсив, моноширинный код и символы формул.

Входы из недоверенных систем помещают в отдельный временный каталог, включают blockRemote и разрешают только его путь. После задачи каталог удаляют. Контейнер не должен получать домашнюю папку, ключи или сокет Docker. Такой дизайн ограничивает ущерб даже при вредоносном HTML или сценарии.

Производительность и расход памяти

Каждая страница существует как DOM до печати, поэтому очень большой документ требует памяти на весь поток, стили и изображения. Признаки нехватки — завершение Chromium без понятной CSS-ошибки, медленная сборка после определённого числа страниц и падение только на сервере с меньшим лимитом. Измеряют пиковую память процесса, а не среднее потребление всей машины.

Оптимизацию начинают с изображений и структуры DOM. Скрытая экранная навигация всё равно может занимать память, если её лишь делают невидимой после загрузки; ненужные блоки лучше не включать в печатный вход. Тысячи вложенных оболочек увеличивают стоимость селекторов и фрагментации. SVG с огромным количеством точек иногда тяжелее подготовленного растра.

Сложные селекторы, особенно зависящие от глубокой структуры и повторяемые для каждого узла, замедляют расчёт стилей. Печатный CSS можно сделать проще экранного: явные классы, небольшая специфичность и отсутствие анимаций. Анимации и переходы в PDF не нужны и должны быть отключены.

Разделение книги на части уменьшает пиковую память, но усложняет общую нумерацию, оглавление и закладки. Поэтому его применяют после измерений, а не заранее. Если документ всё же собирают частями, номера страниц передают как параметры, PDF объединяют проверенным инструментом и повторно валидируют навигацию.

Регрессионное тестирование макета

Небольшой тестовый набор должен покрывать каждый механизм: зеркальные поля, пустую страницу, длинный бегущий заголовок, таблицу на три листа, широкую именованную страницу, рисунок у нижнего края, формулу, кириллицу и закладки. Такой набор выполняется быстрее полной книги и сразу показывает, какая функция изменилась после обновления зависимости или стиля.

Визуальное сравнение строят по растровым изображениям страниц с одинаковым разрешением. Разницу фильтруют с небольшим допуском на сглаживание, но существенный сдвиг текста, исчезновение линии или смена шрифта должны провалить тест. Для динамических дат и идентификаторов используют фиксированные тестовые значения, иначе сравнение будет шумным.

Структурные проверки дополняют изображение. Из PDF извлекают число страниц и текст ключевых заголовков, а из промежуточного HTML — количество контейнеров страниц и отсутствие элементов с известным классом переполнения. Ни один тест не охватывает всё: визуальный может не заметить сломанную ссылку, а текстовый — неверное расположение.

Эталон обновляют только после осознанного просмотра изменения. Автоматическая перезапись после каждого запуска уничтожает смысл регрессии. В описании изменения фиксируют, какие страницы должны отличаться и почему. Это особенно важно, когда небольшая правка шрифта переразбивает сотни листов.

Безопасная обработка недоверенного HTML

Входная страница способна выполнять JavaScript в Chromium. Поэтому HTML от пользователя нельзя считать безобидным документом. Задачу запускают с минимальными правами, без секретов в среде, с блокировкой файлов и сети, ограниченным временем и отдельным временным каталогом. Дополнительные сценарии разрешают только из доверенного набора.

Белый список путей должен включать конкретные каталоги, а не корень диска. Белый список доменов — только серверы, необходимые для этого макета. Перенаправления и вложенные ресурсы проверяют. Если документ можно полностью подготовить без сети, blockRemote является предпочтительным режимом.

Результат также проверяют: недоверенный текст может создать огромное число страниц, чрезмерно большие изображения или ссылки на нежелательные адреса. Лимиты на размер входа, время, память и число страниц защищают очередь. После сбоя процесс Chromium и временные файлы должны быть удалены, иначе серия запросов исчерпает ресурсы.

Командные рецепты

Обычный PDF

pagedjs-cli index.html -o build/document.pdf

Подходит, когда вся геометрия находится в CSS. Каталог build создают заранее.

Отладка с дополнительным стилем

pagedjs-cli index.html --debug --style css/debug.css --warn

Окно остаётся открытым, вспомогательный CSS подсвечивает области, предупреждения выводятся в терминал. Debug-стиль не добавляют в обычную команду.

Сборка без сетевых запросов

pagedjs-cli index.html -o build/document.pdf --blockRemote --allowedPath ./assets

Команда запрещает сеть и разрешает каталог материалов. Если CSS лежит отдельно, в список включают и его расположение либо общий каталог проекта, выбранный по принципу минимальных прав.

Альбомный отчёт

pagedjs-cli report.html -o build/report.pdf --page-size A4 --landscape

Подходит для документа, целиком рассчитанного на широкие таблицы. Для смешанной ориентации используют именованные страницы в CSS.

Закладки по заголовкам

pagedjs-cli manual.html -o build/manual.pdf --outline-tags h2,h3

h2 становится верхним уровнем, h3 — дочерним. Перед запуском проверяют последовательность заголовков.

Дополнительный обработчик

pagedjs-cli book.html -o build/book.pdf --additional-script js/handler.js

Сценарий загружается до рендеринга и должен регистрировать обработчик без сетевых зависимостей и необработанных исключений.

Сравнение Paged.js CLI с аналогами

ПрограммаЛучше подходит дляГлавное ограничение
Paged.js CLIАвтоматической книжной и отчётной верстки из HTML и современного CSS Paged MediaТребует подготовки разметки и стилей без визуального редактора
WeasyPrintСерверной генерации документов из HTML/CSS в Python-проектахНе выполняет браузерный JavaScript как Chromium
PrinceПрофессиональной типографики с развитой поддержкой печатного CSSДля постоянного коммерческого применения нужна соответствующая лицензия
Vivliostyle CLIКниг, публикаций и сборок из web-контента с экосистемой VivliostyleШаблоны и расширения требуют освоения собственного рабочего процесса
wkhtmltopdfПреобразования существующих веб-страниц на базе старого WebKitСовременный CSS и JavaScript поддерживаются ограниченно
PDF CommanderРучного редактирования, объединения и оформления уже созданных PDFНе предназначен для программной страничной верстки HTML

Paged.js CLI выбирают, когда исходником служит HTML, важны @page, бегущие заголовки, развороты и автоматический повтор сборки. WeasyPrint удобнее в инфраструктуре Python и при отсутствии динамического JavaScript. Prince подходит для требовательной издательской задачи, где ценятся зрелые средства печатного CSS и приемлема коммерческая модель. Vivliostyle CLI логичен для проектов, уже использующих его публикационный стек. wkhtmltopdf оставляют для совместимости со старыми шаблонами, а PDF Commander применяют после генерации, когда документ нужно интерактивно поправить, объединить или снабдить элементами, не связанными с HTML-версткой.

Ограничения, которые нужно учитывать заранее

CLI не предоставляет холст, панель объектов и мышиное редактирование. Любая правка проходит через HTML, CSS, сценарий или параметр команды. Это даёт точную воспроизводимость, но требует навыков веб-верстки и понимания страничной модели. Пользователь, которому нужно переставить пару страниц в готовом PDF, быстрее справится в обычном редакторе.

Программа не импортирует существующий PDF обратно в редактируемый HTML-макет. Исходником остаётся веб-документ. Если процесс начинается с чужого PDF, сначала нужен инструмент извлечения или ручного редактирования, а Paged.js CLI пригодится только после появления структурированного HTML.

Результат зависит от Chromium, шрифтов и системных библиотек. Поэтому перенос команды без окружения может изменить разбиение. Контейнер, фиксированные зависимости и комплект шрифтов уменьшают риск. Для долгоживущего проекта сохраняют тестовый набор документов, который проверяется после любого изменения среды.

Поддержка CSS Paged Media широка, но не каждый сложный крайний случай реализован одинаково. Page floats, необычная фрагментация, вложенные именованные страницы и сложные таблицы могут потребовать обработчика или переработки разметки. Макет следует строить от простого потока и добавлять сложность после проверки, а не пытаться перенести экранную композицию без адаптации.

Как добиться воспроизводимого результата

  1. Хранить HTML, CSS, сценарии, шрифты и изображения в одном управляемом проекте.
  2. Фиксировать зависимости через package-lock и устанавливать их одинаковой командой.
  3. Запускать сборку из известной рабочей папки с явными входом и выходом.
  4. Ограничивать сеть и разрешать только необходимые каталоги либо домены.
  5. Использовать один и тот же образ Chromium и один набор шрифтов.
  6. Проверять код завершения, число страниц, ключевой текст и изображения.
  7. Сравнивать критические страницы с утверждёнными визуальными эталонами.
  8. Сохранять журнал предупреждений без секретов и персональных данных.

Эти меры важнее попытки исправить каждый выпуск вручную. Воспроизводимая команда превращает верстку в проверяемый процесс: изменение текста, стиля или данных приводит к новому файлу по тем же правилам. Если результат отличается, команда может показать, какой вход или компонент среды изменился.

Контроль перед передачей PDF

Сначала проверяют геометрию: формат листа, ориентацию, поля, bleed, метки, отсутствие обрезанного текста и неожиданных пустых страниц. Затем типографику: нужные шрифты, начертания, переносы, вдовы и сироты, вертикальный ритм. После этого переходят к структуре: оглавление, номера, бегущие заголовки, закладки и ссылки.

Отдельно открывают страницы с самыми сложными объектами: широкая таблица, большое SVG, длинная формула, код, сноска и переход между именованными страницами. Проверяют начало и конец документа, потому что там действуют специальные селекторы. Если PDF пойдёт в печать, выполняют допечатную проверку в предназначенном для этого инструменте.

Для интерактивного чтения тестируют поиск текста, копирование, кликабельные ссылки и панель закладок. Текст, преобразованный в изображение сторонним компонентом, визуально выглядит правильно, но не ищется. Удобство навигации оценивают на реальном размере экрана, а не только в масштабе страница целиком.

Рабочая стратегия настройки

Начинать лучше с минимального HTML, одного шрифта, обычного потока и базового @page. После получения правильного PDF добавляют зеркальные поля, колонтитулы, разрывы, именованные страницы, оглавление и обработчики. Каждое изменение проверяют на коротком тестовом документе, где есть пограничные случаи. Такой порядок позволяет знать, какое правило породило дефект.

Режим debug используют не как последнюю меру, а как обычную часть верстки. DOM страниц показывает реальные размеры и помогает увидеть, где браузер применил каскад не так, как ожидалось. Когда макет стабилен, тот же вход запускают без debug и сравнивают PDF с предпросмотром. Различие указывает на параметры печати, а не на исходный поток.

Для регулярной публикации команда должна быть записана в package script или сценарии проекта. Ручной набор флагов неизбежно приводит к пропущенному стилю, другому носителю или неверному пути. Сценарий также задаёт ограничения доступа, тайм-аут и проверку результата, поэтому безопасные настройки не зависят от памяти оператора.

Итоговый подход к Paged.js CLI

Paged.js CLI наиболее полезен там, где документ уже описан HTML и CSS, а PDF нужно получать многократно с одинаковой страничной логикой. Команда связывает вход, печатные стили, обработчики и Chromium, а @page, margin-boxes, счётчики, строки и разрывы превращают непрерывный веб-поток в книгу, отчёт или инструкцию. Качественный результат начинается с семантической разметки, явных путей и готовых ресурсов, продолжается отладкой созданных страниц и завершается автоматической проверкой PDF. Такой процесс требует больше подготовки, чем ручная печать страницы, зато изменения текста и дизайна воспроизводятся без повторной расстановки каждого элемента.