@imgly/pdfx-exporter
v0.1.0
Published
Export CE.SDK designs as print-ready PDF/X-1a, X-3 and X-4, with bleed; converts existing PDFs too.
Maintainers
Keywords
Readme
@imgly/pdfx-exporter
Exports CE.SDK designs as print-ready PDF/X-1a:2003, PDF/X-3:2003 or PDF/X-4, with an embedded output intent (FOGRA39, GRACoL 2013, sRGB or your own ICC profile) and real bleed boxes. Runs in the browser and in Node.js.
It replaces @imgly/plugin-print-ready-pdfs-web 1.x (Ghostscript, AGPL); see
Migrating.
import { exportPDFX } from '@imgly/pdfx-exporter';
// Engine → PDF/X in one call: every page of the scene, with bleed.
const printReady = await exportPDFX(cesdk.engine, { outputProfile: 'fogra39' });Usage
convertToPDFX converts a PDF Blob you already have:
import { convertToPDFX } from '@imgly/pdfx-exporter';
const pdf = await engine.block.export(page, 'application/pdf');
const printReady = await convertToPDFX(pdf, {
outputStandard: 'PDF/X-4', // or 'PDF/X-3', 'PDF/X-1a'
outputProfile: 'fogra39', // 'gracol' | 'srgb' | 'custom'
title: 'Spring campaign'
});Pass an array of Blobs to convert several PDFs; the result is an array in the same order.
Options
| Option | Default | Notes |
| --------------------------- | -------------- | -------------------------------------------------------------- |
| outputStandard | 'PDF/X-4' | 'PDF/X-1a', 'PDF/X-3' or 'PDF/X-4'. |
| outputProfile | — | Required. 'fogra39', 'gracol', 'srgb' or 'custom'. |
| customProfile | — | ICC profile Blob; required when outputProfile is 'custom'. |
| flattenTransparency | true for X-3 | PDF/X-1a always flattens; PDF/X-4 keeps live transparency. |
| flattenResolution | 300 | Resolution in dpi for flattened pages. |
| embedICCProfile | true | Embed the output profile in the output intent. |
| title | 'Untitled' | Document title in Info and XMP metadata. |
| outputCondition | per profile | Overrides the output intent's OutputCondition. |
| outputConditionIdentifier | per profile | Overrides the output intent's OutputConditionIdentifier. |
| nonPrinterProfile | 'keep' | 'keep' or 'reject'; see below. |
PDF/X-1a allows only CMYK and spot colours, so srgb is rejected for it.
srgb and other non-printer profiles are not PDF/X
PDF/X (ISO 15930) describes a printing condition, so its output intent must be a
printer profile (ICC device class prtr). srgb is a display profile (mntr),
and a custom profile may be a display, input or colour-space profile. Output
with such a profile is never PDF/X compliant, for any standard: Acrobat
Preflight reports "OutputIntent profile not 'prtr'" and checkPDFX reports
6.2.3 dest-profile-class. nonPrinterProfile decides what happens:
'keep'(default, as in@imgly/plugin-print-ready-pdfs-web1.x): the file is produced anyway. Use it where an RGB file with PDF/X structure (boxes, output intent, metadata) is good enough.'reject': conversion throwsOutput profile is not a printer profile (ICC device class "mntr"); PDF/X needs class "prtr"(with the profile's class) before any work is done (inexportPDFX, after the engine export).
With an RGB output intent, gray content colour is written as the equal RGB, so the only finding left is the profile class.
Exporting straight from the engine
exportPDFX takes the running CE.SDK engine instead of a PDF Blob: it exports
the pages, or any other blocks, itself, with print-oriented export settings and
bleed, and returns one PDF/X — engine to PDF/X in one call. Use convertToPDFX
only for PDFs you already have.
import { exportPDFX } from '@imgly/pdfx-exporter';
// Every page of the current scene, as one multi-page PDF/X:
const printReady = await exportPDFX(cesdk.engine, {
outputStandard: 'PDF/X-4',
outputProfile: 'fogra39'
});
// Selected pages, in the order given:
const back = await exportPDFX(engine, {
outputProfile: 'gracol',
blocks: [pages[3], pages[0]]
});
// Any block — a group, an image, a text — as a page of its own, mixed with pages:
const sticker = await exportPDFX(engine, {
outputProfile: 'fogra39',
blocks: [logoGroup, pages[0]]
});It works with the browser cesdk.engine, @cesdk/node and
@cesdk/node-native (tested against @cesdk/node-native 1.83); the engine parameter is typed by the methods it calls
(PDFXEngine), so the package has no CE.SDK dependency. It takes every
convertToPDFX option, plus:
| Option | Default | Notes |
| --------------- | ----------------------- | -------------------------------------------------------------------------------------------- |
| blocks | every page of the scene | Block ids, one output page each, in this order. Pages get bleed (below); any other block (group, image, text, …) is exported at its own size, without bleed boxes. A scene or stack block stands for its pages. Blocks the engine cannot export fail with the engine's error. |
| exportOptions | see below | Overrides the options passed to engine.block.export. |
| title | block or scene name | One block: its name, else the scene's. Several blocks: the scene's name. Else 'Untitled'. |
Engine export options. Each block is exported with
engine.block.export(block, { mimeType: 'application/pdf', … }) and:
| Engine option | exportPDFX sets | Why |
| -------------------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| exportPdfWithHighCompatibility | true | The engine's own default, set explicitly so every engine build behaves the same. It is the output the converter is validated against (corpus, legacy suite). Bitmaps and gradients are rasterised at the scene's scene/dpi (300 by default). false keeps source images and vector gradients — also passes every standard, but a sample page with a photo grew about 3× as PDF/X-4. |
| exportPdfWithDeviceCMYK | true for a CMYK output intent | CMYK and spot colours set in the scene reach the PDF as CMYK instead of a round trip through RGB. false for srgb (and RGB custom profiles): the converter does not map DeviceCMYK into an RGB intent, so PDF/X-4 with srgb would fail. Custom profiles are detected from the ICC header. |
| exportPdfWithUnderlayer | not set (off) | An underlayer is a white-ink layer for special printers, not part of a regular PDF/X job; turn it on through exportOptions. |
| printer's marks (1.83+) | not set | exportPdfWithCropMarks / exportPdfWithRegistrationMarks pass every standard with CMYK intents (the marks' All colorant fails 6.10 with srgb). They grow the MediaBox around the page, so combined with bleed exportPDFX throws instead of writing wrong boxes. |
| others | not set | pdfImageQuality, allowTextOverhang, abortSignal, onProgress, … keep the engine defaults; pass them in exportOptions. |
Overriding exportPdfWithDeviceCMYK: true with outputProfile: 'srgb' produces
a PDF/X-4 that checkPDFX rejects (rule 6.10).
Bleed. CE.SDK keeps a page's bleed in page/marginEnabled and
page/margin/{top,bottom,left,right} (design units), and engine.block.export
(1.83) includes those margins for a page in a VerticalStack or
HorizontalStack scene but exports the page area alone in a Free or
DepthStack scene. For a page with bleed enabled and any margin above 0,
exportPDFX exports a hidden copy of the page, enlarged by the margins, with
its own margins turned off and its content shifted by the left/top margins, so
whatever reaches into the bleed is printed, once, in every scene layout. The
output page then has MediaBox = BleedBox = page + bleed and TrimBox = the page. The engine snaps the page size to whole device pixels at
scene/dpi, so the TrimBox can be off by a device pixel or two (at most 0.5 pt
at 300 dpi).
Pages without bleed, and blocks other than pages, get TrimBox = MediaBox.
The copy lives only while it is exported: it is made invisible (it never shows
in an editor, but engine.scene.getPages() lists it for the duration of the
export) and destroyed in a finally, children first (destroying a page leaves
its children's fills and shapes behind in CE.SDK 1.82 and 1.83). The scene is
left as it was, whether or not the export succeeds. exportPDFX does not touch
undo histories: the copy is added and removed between two undo steps, so it
nets out of the next one, but an undo step the host app records while an export
runs would contain it. (A scratch history was tried and dropped: in
@cesdk/node-native 1.83, once the active history has been switched, an export
discards pending changes.) Overlapping exportPDFX
calls on the same engine object run one after the other. Limits: the copy's
direct children are placed with absolute positions and sizes taken from their
current frames, and a page's own fill (e.g. a background image fill on the page
itself) is stretched across the bleed by the engine.
Each page is exported separately and the pages are merged before conversion, so fonts used on several pages are embedded once per page (about 7% larger than a single scene export in a six-page text test).
Checking conformance
import { checkPDFX } from '@imgly/pdfx-exporter';
const violations = await checkPDFX(printReady, 'PDF/X-4');
// [] when the file conforms; otherwise { rule, message, object } per findingLoading
The engine is a WebAssembly module in wasm/, loaded on first use: fetched
next to the package's own files in the browser (serve dist/ and wasm/ as
siblings), read from disk in Node.js. It needs Node.js 22+ or a current browser
with WebAssembly SIMD (Chrome, Firefox, Edge, Safari 16.4+).
Logging
import { Logger } from '@imgly/pdfx-exporter';
Logger.setLogLevel('info'); // 'debug' | 'info' | 'warn' (default) | 'error'
Logger.getLogs(); // most recent 1000 entries
Logger.clearLogs();Migrating from @imgly/plugin-print-ready-pdfs-web 1.x
- Uninstall
@imgly/plugin-print-ready-pdfs-web, install this package and change the import specifiers; the API is unchanged:convertToPDFX, the deprecatedconvertToPDFX3(defaults to PDF/X-3),Loggerand the validation error messages behave as in 1.82 and 1.83. - New:
outputStandard: 'PDF/X-1a',flattenResolution,nonPrinterProfile,checkPDFXandexportPDFX(pages with bleed, or any block). srgboutput is converted as before but is not PDF/X compliant (it never was: sRGB is not a printer profile);checkPDFXsays so. PassnonPrinterProfile: 'reject'to refuse it.- Removed:
ghostscriptArgs. The converter no longer uses Ghostscript, so passing a non-emptyghostscriptArgsthrowsghostscriptArgs is not supported: this build does not use Ghostscript. - Not supported: the
signal,timeoutMs,maxOutputBytesandruntimeoptions added in 1.84. TypeScript rejects them; plain JavaScript ignores them. - The engine uses WebAssembly SIMD, so it needs Safari 16.4+ (CE.SDK itself supports Safari 15.6+); see Loading.
- The package no longer contains AGPL-licensed code. The ICC profile licences
ship in
ICC-PROFILE-LICENSES.md.
The @imgly/plugin-print-ready-pdfs-web 2.0.0-beta.1–4 tarballs from this
repository's GitHub releases were earlier builds of this package: 0.1.0 replaces
2.0.0-beta.4 despite the lower version number. Migrate the same way: uninstall
the -web tarball, install this one and change the import specifiers.
License
See LICENSE.md. This software is based in part on the work of the Independent JPEG Group.
