Перейти к содержимому

Обзор NextPDF Artisan

NextPDF Artisan — это мост Chrome для NextPDF. Он отправляет фрагмент Hypertext Markup Language (HTML) в headless-процесс Chrome по протоколу Chrome DevTools Protocol (CDP), получает результат работы printToPDF и встраивает его в целевой документ Portable Document Format (PDF) как Form XObject. Встроенный текст остаётся доступен для выделения и поиска.

Пакет Artisan (nextpdf/artisan) добавляет к движку NextPDF с открытым исходным кодом средство отрисовки, которое передаёт построение макета в Chrome. Собственный HTML-конвейер NextPDF уже поддерживает широкое подмножество Cascading Style Sheets (CSS). Используйте мост Artisan для документов, которым нужен макет уровня Chrome: CSS flexbox и grid, пользовательские веб-шрифты, загружаемые из источников data Uniform Resource Identifier (URI), и сложные селекторы. При этом вы по-прежнему получаете векторный текст, а не растрированный снимок экрана.

Мост устроен как конвейер небольших узкоспециализированных компонентов. ChromeHtmlRenderer управляет отрисовкой. ChromeSecurityPolicy проверяет входные данные и оборачивает их в строго ограниченный HTML-документ. BrowserPool отвечает за жизненный цикл процесса Chrome. ViewportCalculator сопоставляет точки PDF с пикселями CSS. Читатель NextPDF\Parser разбирает результат Chrome, а PageImporter преобразует его в Form XObject. Каждый компонент объявлен как final, использует внедрение через конструктор и типизирован на уровне 10 PHPStan.

Мост зависит от внешних зависимостей. Ему нужны библиотека chrome-php/chrome (^1.15) и исполняемый файл Chrome или Chromium, доступный процессу PHP. Ни то ни другое не входит в комплект. Если библиотека отсутствует, мост выбрасывает ChromeNotAvailableException вместо тихого сбоя; см. /integrations/artisan/failure-modes/ на странице /integrations/artisan/troubleshooting/.

Средство отрисовки никогда не передаёт содержимое в Chrome, пока входные данные не пройдут ChromeSecurityPolicy::validate(). Документ, который получает Chrome, всегда оборачивается строгой Content Security Policy (CSP) через заголовок Content-Security-Policy и многоуровневую сетевую блокировку CDP. Поскольку мост обрабатывает потенциально недоверенный HTML, модель транспорта и изоляции описана на странице /integrations/artisan/security-and-operations/, а не в кратком изложении здесь.

Эта страница описывает поставляемое поведение пакета, проверенное по src/Artisan/ и набору тестов tests/Unit/Artisan/. Это не заявление о попиксельном соответствии интерактивному браузеру Chrome: анимации захватываются на финальном кадре, макет не полагается на JavaScript, а импортируется только первая страница Chrome.

HTML fragment

ChromeSecurityPolicy::validate()

ChromeSecurityPolicy::wrapHtml()

CSP + reset CSS

BrowserPool

headless Chrome

CDP: Network.setBlockedURLs '*'

Page.setDocumentContent

Chrome printToPDF

NextPDF\\Parser\\PdfReader

PageImporter → Form XObject

Embedded in target PDF

(text selectable)

Diagram
КомпонентЗона ответственностиИсходный код
ChromeHtmlRendererУправляет одной отрисовкой; возвращает ChromeRenderResultsrc/Artisan/ChromeHtmlRenderer.php
ChromeRendererConfigНеизменяемый объект-значение с конфигурациейsrc/Artisan/ChromeRendererConfig.php
ChromeSecurityPolicyПроверка входных данных и безопасная HTML-обёрткаsrc/Artisan/ChromeSecurityPolicy.php
BrowserPoolЖизненный цикл процесса Chrome и политика его перезапускаsrc/Artisan/BrowserPool.php
ViewportCalculatorПреобразование 72 pt/inch ↔ 96 px/inchsrc/Artisan/ViewportCalculator.php
ChromeRenderResultТипизированный результат отрисовки (ChromeRenderResultInterface)src/Artisan/ChromeRenderResult.php
PageImporterРазобранная страница Chrome → ImportedFormXObjectsrc/Artisan/PageImporter.php
EInvoiceServiceFactoryФабрика без контейнера для контрактов электронных счетов Premiumsrc/Artisan/EInvoiceServiceFactory.php
  • Происхождение версии. Опубликованный артефакт Composer помечен тегом v0.1.0. Docblock-блоки в исходном коде содержат @since 1.7.0 (мост Chrome) и @since 1.1.0 (фабрика электронных счетов); оба значения унаследованы от линейки версий nextpdf/core, существовавшей до переименования. Пакет был переименован в nextpdf/artisan в записи CHANGELOG 2.0.0. Считайте тег Composer достоверной версией для установки, а маркеры @since — историей версий движка.
  • Только первая страница. PageImporter::import() по умолчанию использует страницу с индексом 0. Содержимое, которое переходит на вторую страницу Chrome, обрезается, если не задать явную высоту, как описано на странице /integrations/artisan/production-usage/.
  • Нет контейнера внедрения зависимостей (DI). Artisan работает без контейнера. EInvoiceServiceFactory даёт средам без контейнера служб единый способ создавать экземпляры служб; см. /integrations/artisan/boot-and-discovery/.

Каждая отрисовка один раз за вызов выполняет загрузку страницы Chrome и printToPDF, поэтому несёт соответствующие затраты. BrowserPool поддерживает процесс Chrome активным между отрисовками и перезапускает его каждые 100 отрисовок, чтобы ограничить рост потребления памяти. В асимптотике Big-O доминирует работа Chrome над макетом, а не сам мост. Измеренный бюджет эталонного сценария для этой страницы см. в performance_budget во frontmatter и на странице /integrations/artisan/production-usage/.

Мост отрисовывает потенциально недоверенный HTML внутри Chrome. Входные данные проверяются по размеру и содержимому до того, как их увидит Chrome. Обёрнутый документ содержит default-src 'none'. Блокировка на уровне CDP останавливает каждый запрос вложенного ресурса. Полная модель транспорта и изоляции, включая явные ограничения флага песочницы Chrome, описана на странице /integrations/artisan/security-and-operations/. Не считайте этот раздел полным описанием состояния безопасности.

Мост с открытым исходным кодом отрисовывает HTML в PDF. Уровни Premium добавляют поверх отрисованного документа соответствующее требованиям встраивание электронных счетов (Pro) и их проверку (Enterprise). Когда эти уровни не установлены, EInvoiceServiceFactory возвращает null, поэтому путь с открытым исходным кодом остаётся полностью работоспособным без них.

  • Установка — /integrations/artisan/install/
  • Настройка — /integrations/artisan/configuration/
  • Быстрый старт — /integrations/artisan/quickstart/
  • Настройка средства отрисовки Chrome — /integrations/artisan/chrome-renderer-setup/
  • Безопасность и эксплуатация — /integrations/artisan/security-and-operations/
  • Использование в продакшене — /integrations/artisan/production-usage/