blitz-pdf 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +292 -12
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/document-options.d.ts +36 -0
- package/dist/document-options.d.ts.map +1 -0
- package/dist/document-options.js +236 -0
- package/dist/document-options.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/options.d.ts +35 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +21 -14
- package/dist/options.js.map +1 -1
- package/dist/types.d.ts +71 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +7 -0
- package/dist/validation.js.map +1 -0
- package/docs/pagination-regressions.md +88 -0
- package/examples/zugferd.mjs +41 -0
- package/licenses/RUST_DEPENDENCIES.txt +27 -0
- package/package.json +4 -2
- package/src/browser.ts +1 -1
- package/src/document-options.ts +218 -0
- package/src/node.ts +1 -1
- package/src/options.ts +18 -13
- package/src/types.ts +76 -1
- package/src/validation.ts +6 -0
- package/vendor/README.md +27 -2
- package/vendor/krilla/.cargo-ok +1 -0
- package/vendor/krilla/.cargo_vcs_info.json +6 -0
- package/vendor/krilla/Cargo.lock +1357 -0
- package/vendor/krilla/Cargo.toml +165 -0
- package/vendor/krilla/LICENSE_APACHE +202 -0
- package/vendor/krilla/LICENSE_MIT +21 -0
- package/vendor/krilla/README.md +156 -0
- package/vendor/krilla/examples/basic.rs +117 -0
- package/vendor/krilla/examples/empty_document.rs +25 -0
- package/vendor/krilla/examples/parley.rs +174 -0
- package/vendor/krilla/examples/simple_text.rs +118 -0
- package/vendor/krilla/examples/stream_builder.rs +93 -0
- package/vendor/krilla/icc/LICENSE +116 -0
- package/vendor/krilla/icc/README.md +1 -0
- package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sGrey-v4.icc +0 -0
- package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sRGB-v4.icc +0 -0
- package/vendor/krilla/src/chunk_container.rs +503 -0
- package/vendor/krilla/src/configure/PDF_A1.md +227 -0
- package/vendor/krilla/src/configure/PDF_A2.md +269 -0
- package/vendor/krilla/src/configure/PDF_A3.md +31 -0
- package/vendor/krilla/src/configure/PDF_A4.md +211 -0
- package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
- package/vendor/krilla/src/configure/README.md +23 -0
- package/vendor/krilla/src/configure/mod.rs +197 -0
- package/vendor/krilla/src/configure/validate.rs +1244 -0
- package/vendor/krilla/src/configure/version.rs +134 -0
- package/vendor/krilla/src/content.rs +1352 -0
- package/vendor/krilla/src/data.rs +49 -0
- package/vendor/krilla/src/document.rs +156 -0
- package/vendor/krilla/src/error.rs +170 -0
- package/vendor/krilla/src/geom.rs +341 -0
- package/vendor/krilla/src/graphics/blend.rs +46 -0
- package/vendor/krilla/src/graphics/color.rs +552 -0
- package/vendor/krilla/src/graphics/graphic.rs +30 -0
- package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
- package/vendor/krilla/src/graphics/icc.rs +218 -0
- package/vendor/krilla/src/graphics/image.rs +835 -0
- package/vendor/krilla/src/graphics/mask.rs +128 -0
- package/vendor/krilla/src/graphics/mod.rs +14 -0
- package/vendor/krilla/src/graphics/paint.rs +434 -0
- package/vendor/krilla/src/graphics/separation.rs +86 -0
- package/vendor/krilla/src/graphics/shading_function.rs +865 -0
- package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
- package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
- package/vendor/krilla/src/graphics/xobject.rs +150 -0
- package/vendor/krilla/src/interactive/action.rs +68 -0
- package/vendor/krilla/src/interactive/annotation.rs +283 -0
- package/vendor/krilla/src/interactive/destination.rs +289 -0
- package/vendor/krilla/src/interactive/mod.rs +3 -0
- package/vendor/krilla/src/interchange/embed.rs +240 -0
- package/vendor/krilla/src/interchange/metadata.rs +564 -0
- package/vendor/krilla/src/interchange/mod.rs +4 -0
- package/vendor/krilla/src/interchange/outline.rs +263 -0
- package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
- package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
- package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
- package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
- package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
- package/vendor/krilla/src/lib.rs +179 -0
- package/vendor/krilla/src/num.rs +26 -0
- package/vendor/krilla/src/page.rs +612 -0
- package/vendor/krilla/src/pdf.rs +313 -0
- package/vendor/krilla/src/resource.rs +436 -0
- package/vendor/krilla/src/serialize.rs +1101 -0
- package/vendor/krilla/src/stream.rs +368 -0
- package/vendor/krilla/src/surface.rs +664 -0
- package/vendor/krilla/src/text/cid.rs +488 -0
- package/vendor/krilla/src/text/font.rs +351 -0
- package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
- package/vendor/krilla/src/text/glyph/colr.rs +581 -0
- package/vendor/krilla/src/text/glyph/mod.rs +205 -0
- package/vendor/krilla/src/text/glyph/outline.rs +72 -0
- package/vendor/krilla/src/text/glyph/svg.rs +34 -0
- package/vendor/krilla/src/text/group.rs +463 -0
- package/vendor/krilla/src/text/mod.rs +232 -0
- package/vendor/krilla/src/text/shape.rs +102 -0
- package/vendor/krilla/src/text/type3.rs +514 -0
- package/vendor/krilla/src/util.rs +286 -0
- package/vendor/stylo/properties/longhands.toml +0 -1
- package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
- package/wasm/blitz_pdf.js +10 -5
- package/wasm/blitz_pdf_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -80,13 +80,17 @@ cross-origin isolation are not required.
|
|
|
80
80
|
|
|
81
81
|
| Option | Default | Meaning |
|
|
82
82
|
| --- | --- | --- |
|
|
83
|
-
| `format` | `"A4"` | `
|
|
83
|
+
| `format` | `"A4"` | `A0`–`A6`, `Letter`, `Legal`, `Tabloid`, or `Ledger` |
|
|
84
84
|
| `width`, `height` | From format | Supply both for custom dimensions; omit `format` |
|
|
85
85
|
| `landscape` | `false` | Swap width and height |
|
|
86
|
+
| `preferCSSPageSize` | `false` | Let CSS `@page size` override an explicit format or dimensions |
|
|
86
87
|
| `margin` | `0` | One length or `{ top, right, bottom, left }`; omitted sides are zero |
|
|
87
88
|
| `media` | `"print"` | CSS media queries: `print` or `screen` |
|
|
88
|
-
| `title` | Unset | PDF metadata title |
|
|
89
|
+
| `title` | Unset | PDF metadata title; `metadata.title` takes precedence |
|
|
90
|
+
| `metadata` | `{}` | Author, subject, keywords, dates, language, document ID, and custom XMP schemas |
|
|
91
|
+
| `attachments` | `[]` | Direct embedded files with MIME types and PDF/A relationships |
|
|
89
92
|
| `pageNumbers` | `false` | `true` or `{ template, align, fontSize }` for an automatic text footer |
|
|
93
|
+
| `headerTemplate` / `footerTemplate` | Unset | HTML repeated in the top/bottom page margin, with `.pageNumber` and `.totalPages` placeholders |
|
|
90
94
|
| `baseUrl` | `https://blitz-pdf.invalid/` | Resolve relative asset URLs |
|
|
91
95
|
| `assets` | `{}` | Resource map or `(url) => data / Promise<data>`; data is a UTF-8 string, `Uint8Array`, or `ArrayBuffer` |
|
|
92
96
|
| `fonts` | `[]` | Additional static TTF, OTF, WOFF, or WOFF2 font bytes |
|
|
@@ -97,6 +101,203 @@ Lengths accept numbers in CSS pixels (96 px = 1 inch), or strings with `px`,
|
|
|
97
101
|
are limited to 19200 CSS pixels; margins must leave printable content.
|
|
98
102
|
`getEngineVersion()` returns the package version and pinned Blitz revision.
|
|
99
103
|
|
|
104
|
+
## CSS page settings
|
|
105
|
+
|
|
106
|
+
Unqualified `@page` rules support `size`, `margin`, and the four individual
|
|
107
|
+
margin properties. For example, this label uses a 105 mm by 148 mm page:
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const pdf = await renderPdf(`
|
|
111
|
+
<style>
|
|
112
|
+
@page { size: 105mm 148mm; margin: 5mm; margin-bottom: 8mm; }
|
|
113
|
+
html, body { margin: 0; }
|
|
114
|
+
</style>
|
|
115
|
+
<h1>Shipping label</h1>
|
|
116
|
+
`);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
`size: A4 landscape`, `size: landscape`, square sizes such as `size: 100mm`,
|
|
120
|
+
and absolute length calculations are supported. Rules follow stylesheet and
|
|
121
|
+
`@import` order, honor `!important`, and use the selected `print`/`screen` media.
|
|
122
|
+
CSS page margins override the corresponding option margins; unspecified sides
|
|
123
|
+
keep their option values. Percentages resolve against the corresponding page
|
|
124
|
+
dimension. Margins must be non-negative and leave printable content.
|
|
125
|
+
|
|
126
|
+
CSS size is used automatically when neither `format` nor `width`/`height` is
|
|
127
|
+
provided. Explicit dimensions take precedence by default. Set
|
|
128
|
+
`preferCSSPageSize: true` to let CSS size override them. `size: auto` keeps the
|
|
129
|
+
option size, or A4 when no size was supplied. Content is laid out again at the
|
|
130
|
+
chosen dimensions; it is not scaled from an A4 layout.
|
|
131
|
+
|
|
132
|
+
Named formats are `A0`, `A1`, `A2`, `A3`, `A4`, `A5`, `A6`, `Letter`, `Legal`,
|
|
133
|
+
`Tabloid` (11 by 17 inches), and `Ledger` (17 by 11 inches). `landscape: true`
|
|
134
|
+
swaps the option dimensions. An explicit CSS orientation takes precedence when
|
|
135
|
+
CSS controls the size.
|
|
136
|
+
|
|
137
|
+
The page geometry is uniform throughout a document. Named pages, `:first`,
|
|
138
|
+
`:left`/`:right` page selectors, CSS page margin boxes, cascade layers, and
|
|
139
|
+
custom-property substitution inside `@page` are not implemented.
|
|
140
|
+
|
|
141
|
+
## Document metadata
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
const pdf = await renderPdf(html, {
|
|
145
|
+
metadata: {
|
|
146
|
+
title: "Project report",
|
|
147
|
+
author: ["Ada Example", "Example GmbH"], // A single string also works.
|
|
148
|
+
subject: "Project delivery and supporting documents",
|
|
149
|
+
keywords: ["project", "delivery"],
|
|
150
|
+
creator: "My application",
|
|
151
|
+
language: "de-DE",
|
|
152
|
+
creationDate: "2026-10-13T10:00:00+02:00",
|
|
153
|
+
modificationDate: new Date("2026-10-14T08:00:00Z"),
|
|
154
|
+
documentId: "project-42-report", // Stable identity across revisions.
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Standard metadata is synchronized between the PDF information dictionary and
|
|
160
|
+
XMP. `language` also sets the document catalog's language. `producer` defaults
|
|
161
|
+
to `blitz-pdf` and its version and can be overridden. Creation time defaults to
|
|
162
|
+
the start of the render; modification time defaults to creation time and must
|
|
163
|
+
not precede it. Dates accept a valid `Date` or a timestamp with an explicit
|
|
164
|
+
timezone, with at most three fractional-second digits. They are stored in UTC
|
|
165
|
+
at whole-second precision. `documentId` is a stable input from which the engine
|
|
166
|
+
derives the PDF document ID; it is not copied literally into the ID field.
|
|
167
|
+
|
|
168
|
+
The original top-level `title` option remains supported. `metadata.title`
|
|
169
|
+
overrides it, including an empty string to omit the title. Metadata strings must
|
|
170
|
+
contain valid XML characters and fit in 16 KiB of UTF-8 per field. Author and
|
|
171
|
+
keyword lists allow up to 256 entries and 16 KiB when joined. CR/CRLF line endings
|
|
172
|
+
are normalized to LF to keep Info and XMP consistent.
|
|
173
|
+
|
|
174
|
+
## Embedded files
|
|
175
|
+
|
|
176
|
+
```js
|
|
177
|
+
const pdf = await renderPdf(html, {
|
|
178
|
+
attachments: [
|
|
179
|
+
{
|
|
180
|
+
name: "data.xml",
|
|
181
|
+
data: xmlString, // UTF-8 text, Uint8Array/Buffer, or ArrayBuffer.
|
|
182
|
+
mimeType: "text/xml",
|
|
183
|
+
description: "Structured document data",
|
|
184
|
+
relationship: "Alternative",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "supporting-data.csv",
|
|
188
|
+
data: "item,quantity\nExample,2\n",
|
|
189
|
+
mimeType: "text/csv",
|
|
190
|
+
relationship: "Supplement",
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Files are embedded directly, without going through the HTML asset resolver.
|
|
197
|
+
`data` is the file's content, never a filename or URL to load. Use `readFile`,
|
|
198
|
+
`fetch(...).arrayBuffer()`, or `File.arrayBuffer()` before calling `renderPdf`.
|
|
199
|
+
The library snapshots supplied bytes and metadata before asynchronous work.
|
|
200
|
+
|
|
201
|
+
Each attachment has a Unicode filename, a MIME type, an uncompressed size and
|
|
202
|
+
modification date, and a document-level `/AFRelationship`. It appears both in
|
|
203
|
+
the catalog's `/AF` array and in the `/EmbeddedFiles` name tree used by PDF
|
|
204
|
+
viewers. `relationship` accepts `Source`, `Data`, `Alternative`, `Supplement`,
|
|
205
|
+
or `Unspecified` (the default). MIME type defaults to `application/octet-stream`,
|
|
206
|
+
description to the filename, and modification date to the document's modification
|
|
207
|
+
date. MIME parameters such as `; charset=utf-8` are not accepted. Set
|
|
208
|
+
`compress: true` or `false` to control compression; by default the engine chooses.
|
|
209
|
+
|
|
210
|
+
Up to 100 files and 64 MiB of combined attachment contents are allowed, separately
|
|
211
|
+
from HTML asset limits. Filenames must be at most 255 UTF-8 bytes, without
|
|
212
|
+
directories, colons, or control characters. Duplicate filenames, including
|
|
213
|
+
Unicode normalization equivalents, are rejected. Zero-byte files are supported.
|
|
214
|
+
Attachment contents are preserved without interpreting or validating their format.
|
|
215
|
+
|
|
216
|
+
## Custom XMP schemas
|
|
217
|
+
|
|
218
|
+
`metadata.xmp` adds application-specific text properties and their PDF/A extension
|
|
219
|
+
schema descriptions to the existing XMP packet. Standard metadata and PDF/A
|
|
220
|
+
identification remain present.
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
const pdf = await renderPdf(html, {
|
|
224
|
+
metadata: {
|
|
225
|
+
xmp: [{
|
|
226
|
+
name: "Project metadata",
|
|
227
|
+
namespaceUri: "urn:example:project:1.0#",
|
|
228
|
+
prefix: "project",
|
|
229
|
+
properties: [{
|
|
230
|
+
name: "ProjectId",
|
|
231
|
+
value: "PR-0042",
|
|
232
|
+
description: "Identifier of the project this document belongs to",
|
|
233
|
+
category: "external", // Default; use internal for content-derived values.
|
|
234
|
+
}],
|
|
235
|
+
}],
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Every property is declared as XMP `Text`; values and descriptions are escaped
|
|
241
|
+
as XML. Schema names and property descriptions must be non-empty. Prefixes and
|
|
242
|
+
property names use ASCII XML names without colons or an `xml` prefix. Namespace
|
|
243
|
+
URIs must be absolute ASCII URIs with whitespace and XML delimiters percent-encoded.
|
|
244
|
+
Built-in namespaces/prefixes are reserved. Duplicate prefixes, namespace URIs,
|
|
245
|
+
or property names within one schema are rejected. Each schema requires at least
|
|
246
|
+
one property. Limits are 32 schemas, 256 properties in total, and 1 MiB of combined
|
|
247
|
+
schema text, in addition to the per-field limit. Structured XMP values and raw
|
|
248
|
+
XMP packet replacement are not currently exposed.
|
|
249
|
+
|
|
250
|
+
### Factur-X / ZUGFeRD example
|
|
251
|
+
|
|
252
|
+
The generic attachment and XMP APIs can express Factur-X/ZUGFeRD packaging. For
|
|
253
|
+
example, with matching HTML and already-validated **EN 16931** CII invoice XML:
|
|
254
|
+
|
|
255
|
+
```js
|
|
256
|
+
const pdf = await renderPdf(invoiceHtml, {
|
|
257
|
+
attachments: [{
|
|
258
|
+
name: "factur-x.xml", data: invoiceXml, mimeType: "text/xml",
|
|
259
|
+
description: "Invoice XML", relationship: "Alternative",
|
|
260
|
+
}],
|
|
261
|
+
metadata: {
|
|
262
|
+
title: "Invoice RE-0042", language: "de-DE",
|
|
263
|
+
xmp: [{
|
|
264
|
+
name: "Factur-X PDFA Extension Schema",
|
|
265
|
+
namespaceUri: "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#",
|
|
266
|
+
prefix: "fx",
|
|
267
|
+
properties: [
|
|
268
|
+
{ name: "DocumentFileName", value: "factur-x.xml", description: "Embedded invoice filename" },
|
|
269
|
+
{ name: "DocumentType", value: "INVOICE", description: "Document type" },
|
|
270
|
+
{ name: "Version", value: "1.0", description: "Schema version" },
|
|
271
|
+
{ name: "ConformanceLevel", value: "EN 16931", description: "Invoice profile" },
|
|
272
|
+
],
|
|
273
|
+
}],
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
These settings follow the [PDF embedding and XMP requirements](https://www.pdflib.com/pdf-knowledge-base/zugferd-and-factur-x/)
|
|
279
|
+
for Factur-X 1.x / ZUGFeRD 2.1+. The XMP `Version` is `1.0`, not the release number.
|
|
280
|
+
Choose the profile and relationship for your document: `Data` for MINIMUM/BASIC WL;
|
|
281
|
+
normally `Alternative` for BASIC, EN 16931, or EXTENDED. `Source` applies in the
|
|
282
|
+
specified cases where the PDF is derived from XML and the recipient is outside
|
|
283
|
+
Germany. The XML filename and XMP `DocumentFileName` must agree. See the
|
|
284
|
+
[FeRD specification and validation artifacts](https://www.ferd-net.de/publikationen-produkte/publikationen/detailseite/zugferd-252-english)
|
|
285
|
+
for the version/profile you use.
|
|
286
|
+
|
|
287
|
+
The renderer does not generate invoice XML, validate XSD/Schematron rules, infer
|
|
288
|
+
profiles, or check agreement between PDF and XML. Applications supply and validate
|
|
289
|
+
these inputs. PDF/A conformance alone does not establish invoice conformance.
|
|
290
|
+
|
|
291
|
+
The runnable example accepts your HTML, XML, and profile:
|
|
292
|
+
|
|
293
|
+
```sh
|
|
294
|
+
npm run example:zugferd -- invoice.html invoice.xml "EN 16931" output/pdf/invoice.pdf
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`PdfAttachment`, `AttachmentRelationship`, `PdfMetadata`, `PdfDate`,
|
|
298
|
+
`PdfXmpSchema`, and `PdfXmpProperty` are exported TypeScript types in Node/Bun
|
|
299
|
+
and browser entry points.
|
|
300
|
+
|
|
100
301
|
## Resources and fonts
|
|
101
302
|
|
|
102
303
|
The renderer requests resources through `assets` or decodes data URLs. Supply an
|
|
@@ -162,7 +363,7 @@ system font discovery. Fonts passed in `fonts` use their internal family names;
|
|
|
162
363
|
use `@font-face` with an asset URL for a CSS alias. Supply fonts for scripts not
|
|
163
364
|
covered by the bundled family.
|
|
164
365
|
|
|
165
|
-
Input limits: 16 MiB HTML, 64 MiB supplied assets, 32 MiB supplied fonts, and 1024
|
|
366
|
+
Input limits: 16 MiB HTML, 64 MiB supplied assets, 64 MiB attachments, 32 MiB supplied fonts, and 1024
|
|
166
367
|
resource requests. These are practical limits, not a complete sandbox; isolate
|
|
167
368
|
untrusted documents in a terminable worker with application limits.
|
|
168
369
|
|
|
@@ -207,6 +408,7 @@ vertical flow include:
|
|
|
207
408
|
`page-break-after`, and `page-break-inside` aliases.
|
|
208
409
|
- Inherited `widows` and `orphans` (positive integers; default 2).
|
|
209
410
|
- Automatic protection of text lines, table rows, images, and SVG boxes.
|
|
411
|
+
- Repeated table header and footer groups, with space reserved before splitting rows.
|
|
210
412
|
|
|
211
413
|
```html
|
|
212
414
|
<style>
|
|
@@ -229,6 +431,44 @@ relaxed to make progress. A text line that cannot fit the printable height
|
|
|
229
431
|
fails explicitly. Keep-with-next protects a heading even when the following
|
|
230
432
|
paragraph spans multiple pages.
|
|
231
433
|
|
|
434
|
+
Trailing `<br>` elements and preserved blank lines keep their layout height;
|
|
435
|
+
the extra cursor line emitted by the text engine after a final break is not
|
|
436
|
+
paginated. Overflow clips constrain line, glyph, and table-row fragmentation.
|
|
437
|
+
Fully clipped glyph runs are omitted from the PDF's selectable text.
|
|
438
|
+
|
|
439
|
+
Pagination failures include a code at the start of `Error.message`:
|
|
440
|
+
|
|
441
|
+
- `PAGINATION_LINE_TOO_TALL`: a line exceeds the available printable height.
|
|
442
|
+
- `PAGINATION_NO_PROGRESS`: no valid advancing break exists, including chains
|
|
443
|
+
of overlapping lines that individually fit the page.
|
|
444
|
+
- `PAGINATION_FORCED_BREAK_INTERSECTS_LINE`: an explicit break cuts a line.
|
|
445
|
+
- `PAGINATION_TABLE_GROUPS_TOO_TALL`: repeated groups leave no room for rows.
|
|
446
|
+
|
|
447
|
+
These messages include the zero-based page index, document-space page top,
|
|
448
|
+
available height, and, when associated with a DOM line, element tag/ID, internal
|
|
449
|
+
node ID, zero-based line index and measured visible line range. Coordinates and
|
|
450
|
+
heights are CSS pixels. Painted glyph runs without a DOM association and errors
|
|
451
|
+
without a blocking line report those fields as `unavailable`.
|
|
452
|
+
|
|
453
|
+
The pinned Blitz table layout still differs from Chromium for `td { max-width: 0 }`:
|
|
454
|
+
it can constrain the cell itself to zero content width and wrap short text by
|
|
455
|
+
character, while Chromium distributes the table width across the columns.
|
|
456
|
+
Height-limited containers now paginate their visible content without failing,
|
|
457
|
+
but this does not resolve that separate width-compatibility issue. See the
|
|
458
|
+
[reproduction and investigation](docs/pagination-regressions.md).
|
|
459
|
+
|
|
460
|
+
The first `<thead>` and `<tfoot>` (or elements styled as `table-header-group`
|
|
461
|
+
and `table-footer-group`) repeat on every fragment of their table. Their actual
|
|
462
|
+
layout, column widths, backgrounds, and selectable text are retained. Use
|
|
463
|
+
`display: table-row-group` to disable repetition. Headers stay with the first
|
|
464
|
+
body row and footers with the last where they fit. Repetition stops when the
|
|
465
|
+
table ends, and the extra space counts toward `maxPages`. Nested tables remain
|
|
466
|
+
part of their containing row rather than independently repeating their groups.
|
|
467
|
+
|
|
468
|
+
Pagination accounts for the subpixel difference between CSS dimensions and
|
|
469
|
+
Blitz's rounded box edges, avoiding an extra page for an exactly fitting
|
|
470
|
+
fractional-height label.
|
|
471
|
+
|
|
232
472
|
### Page numbers
|
|
233
473
|
|
|
234
474
|
```js
|
|
@@ -255,6 +495,42 @@ intentional blanks. The footer uses embedded DejaVu Sans and the same Unicode
|
|
|
255
495
|
shaping as body text, preserving selectable text and PDF/A-3u. It works with
|
|
256
496
|
async assets in every runtime. `PageNumberOptions` is an exported TypeScript type.
|
|
257
497
|
|
|
498
|
+
### Repeated HTML headers and footers
|
|
499
|
+
|
|
500
|
+
```js
|
|
501
|
+
const pdf = await renderPdf(reportHtml, {
|
|
502
|
+
margin: { top: "18mm", bottom: "15mm", left: "12mm", right: "12mm" },
|
|
503
|
+
headerTemplate: `
|
|
504
|
+
<div style="font: 10pt/14pt sans-serif; padding-top: 4mm">
|
|
505
|
+
<img src="logo.svg" width="24" height="24"> Quarterly report
|
|
506
|
+
</div>`,
|
|
507
|
+
footerTemplate: `
|
|
508
|
+
<div style="font: 9pt/12pt sans-serif; text-align: right">
|
|
509
|
+
Page <span class="pageNumber"></span> of <span class="totalPages"></span>
|
|
510
|
+
</div>`,
|
|
511
|
+
assets: { "logo.svg": logoSvg },
|
|
512
|
+
});
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
Templates occupy the top/bottom margins between the left and right margins,
|
|
516
|
+
including on intentional blank pages. Supply enough margin height for each
|
|
517
|
+
template; overflow fails with an error. Both start at the top of their margin
|
|
518
|
+
band, so use CSS padding or flex layout to position their contents within it.
|
|
519
|
+
Body content does not overlap those bands. `pageNumbers` can also be used; its
|
|
520
|
+
automatic footer remains above the bottom margin.
|
|
521
|
+
|
|
522
|
+
Each template is a separate HTML document with zero default body margin and a
|
|
523
|
+
transparent background. Template-local inline styles, `<style>`, and linked
|
|
524
|
+
stylesheets are supported. Body CSS does not cascade into templates. They share
|
|
525
|
+
the document's asset resolver, loaded font collection, supplied fonts, base URL,
|
|
526
|
+
and media type. URLs are resolved and deduplicated across the whole render,
|
|
527
|
+
including async CSS, fonts, and images. Scripts are not run. Text stays selectable
|
|
528
|
+
and graphics use the same vector PDF pipeline as the body.
|
|
529
|
+
|
|
530
|
+
Elements with class `pageNumber` or `totalPages` have their contents replaced
|
|
531
|
+
with the final page number/count before layout. Templates are limited to 1 MiB
|
|
532
|
+
of HTML each. Omit a template or pass an empty string to disable it.
|
|
533
|
+
|
|
258
534
|
## German invoice example
|
|
259
535
|
|
|
260
536
|
```sh
|
|
@@ -273,7 +549,8 @@ alongside the PDF for inspection.
|
|
|
273
549
|
|
|
274
550
|
The [example source and scope](examples/german-invoice/README.md) explain the
|
|
275
551
|
fictitious data and the German invoice fields. This is a **PDF/A-3u example
|
|
276
|
-
without embedded XML
|
|
552
|
+
without embedded XML**. Use the generic [attachment and XMP APIs](#factur-x--zugferd-example)
|
|
553
|
+
with independently generated, matching invoice XML for a structured e-invoice. Its 2026 domestic
|
|
277
554
|
B2B scenario assumes the recipient agrees to PDF delivery under the applicable
|
|
278
555
|
transition rule. [§ 14 UStG](https://www.gesetze-im-internet.de/ustg_1980/__14.html),
|
|
279
556
|
[§ 27(38) UStG](https://www.gesetze-im-internet.de/ustg_1980/__27.html).
|
|
@@ -284,9 +561,9 @@ transition rule. [§ 14 UStG](https://www.gesetze-im-internet.de/ustg_1980/__14.
|
|
|
284
561
|
- Text retains shaped glyphs and Unicode cluster mappings, including ligatures.
|
|
285
562
|
Unrecognized or ambiguous text runs are rejected rather than assigned guessed
|
|
286
563
|
Unicode.
|
|
287
|
-
- Pagination fragments one continuous vertical layout.
|
|
288
|
-
|
|
289
|
-
fragmentation of parallel flex/grid flows are not implemented. Oversized
|
|
564
|
+
- Pagination fragments one continuous vertical layout. Per-page geometry,
|
|
565
|
+
repeated fixed-position body elements, nested multicolumn fragmentation, and
|
|
566
|
+
independent fragmentation of parallel flex/grid flows are not implemented. Oversized
|
|
290
567
|
boxes/images may span pages; box decorations are sliced rather than cloned.
|
|
291
568
|
- CSS filters, blurred shadows, non-default variable font instances, and
|
|
292
569
|
repeating radial gradients are rejected. Use static font faces. There is no
|
|
@@ -318,8 +595,9 @@ the tarball; it does not publish. Install locally using
|
|
|
318
595
|
`npm install ./blitz-pdf-<version>.tgz`.
|
|
319
596
|
|
|
320
597
|
The pinned Stylo source in `vendor/stylo` enables paged-media properties in the
|
|
321
|
-
Servo build
|
|
322
|
-
|
|
598
|
+
Servo build. `vendor/krilla` adds custom XMP schema support and independent
|
|
599
|
+
modification dates. `vendor/README.md` records both patches; the sources and
|
|
600
|
+
licenses are included in the npm archive.
|
|
323
601
|
|
|
324
602
|
`bun test` exercises the compiled module through its public package export. Tests
|
|
325
603
|
extract Unicode with PDF.js and inspect embedded fonts, vector paths, absence
|
|
@@ -341,8 +619,10 @@ Publishing uses [npm trusted publishing](https://docs.npmjs.com/trusted-publishe
|
|
|
341
619
|
with GitHub OIDC and provenance. The npm trust must permit direct publishing from
|
|
342
620
|
`iteufel/blitz-pdf`, workflow `publish.yml`, with no environment restriction.
|
|
343
621
|
No `NPM_TOKEN` repository secret is needed. Stable versions use the npm `latest`
|
|
344
|
-
tag; prereleases use `next`. After publishing, the workflow
|
|
345
|
-
the exact archive it
|
|
622
|
+
tag; prereleases use `next`. After publishing, the workflow allows up to five
|
|
623
|
+
minutes for registry propagation and checks that npm serves the exact archive it
|
|
624
|
+
built, comparing SHA-512 integrity. Retrying an already-published version succeeds
|
|
625
|
+
only when its archive is identical; a different archive fails.
|
|
346
626
|
|
|
347
627
|
For the next patch release:
|
|
348
628
|
|
|
@@ -360,7 +640,7 @@ git push origin main "v$RELEASE_VERSION"
|
|
|
360
640
|
```
|
|
361
641
|
|
|
362
642
|
To retry a failed release, rerun its GitHub Actions run or use
|
|
363
|
-
`gh workflow run publish.yml --ref
|
|
643
|
+
`gh workflow run publish.yml --ref v<version>`. Manual runs require a matching version
|
|
364
644
|
tag too. Published npm versions cannot be overwritten; subsequent releases need
|
|
365
645
|
a new version.
|
|
366
646
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -15,8 +15,10 @@ The resolved dependency inventory and upstream license notices are in
|
|
|
15
15
|
Upstream sources are available at the repository links in that inventory and
|
|
16
16
|
through crates.io. Stylo 0.22.0 is patched to expose paged-media CSS properties
|
|
17
17
|
in its Servo build. Its full modified MPL-2.0 source and license are included in
|
|
18
|
-
`vendor/stylo
|
|
19
|
-
|
|
18
|
+
`vendor/stylo`. Krilla 0.8.2 is patched for custom XMP extension schemas and
|
|
19
|
+
independent modification dates; its source and MIT/Apache-2.0 licenses are in
|
|
20
|
+
`vendor/krilla`. `vendor/README.md` lists both patches. Other dependencies are
|
|
21
|
+
used without source modifications.
|
|
20
22
|
|
|
21
23
|
Bundled DejaVu fonts use the Bitstream Vera / DejaVu license reproduced in
|
|
22
24
|
`licenses/DejaVu.txt`. The regular WOFF2 comes from Blitz's
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export type { AssetData, AssetMap, AssetResolver, BinaryData, InitOptions, Length, PageFormat, PageNumberOptions, PdfOptions, WasmSource } from "./types.js";
|
|
1
|
+
export type { AssetData, AssetMap, AssetResolver, AttachmentRelationship, BinaryData, InitOptions, Length, PageFormat, PageNumberOptions, PdfAttachment, PdfDate, PdfMetadata, PdfOptions, PdfXmpProperty, PdfXmpSchema, WasmSource } from "./types.js";
|
|
2
2
|
export declare const init: (options?: import("./types.js").InitOptions) => Promise<void>, renderPdf: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, getEngineVersion: () => Promise<string>;
|
|
3
3
|
//# sourceMappingURL=browser.d.ts.map
|
package/dist/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxP,eAAO,MAAQ,IAAI,iEAAE,SAAS,oFAAE,gBAAgB,uBAE/C,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { AttachmentRelationship, PdfOptions } from "./types.js";
|
|
2
|
+
export declare function normalizeDocumentOptions(options: PdfOptions): {
|
|
3
|
+
metadata: {
|
|
4
|
+
title: string | null;
|
|
5
|
+
authors: string[];
|
|
6
|
+
subject: string | null;
|
|
7
|
+
keywords: string[];
|
|
8
|
+
creator: string | null;
|
|
9
|
+
producer: string | null;
|
|
10
|
+
language: string | null;
|
|
11
|
+
creationDate: number;
|
|
12
|
+
modificationDate: number;
|
|
13
|
+
documentId: string | null;
|
|
14
|
+
xmp: {
|
|
15
|
+
name: string;
|
|
16
|
+
prefix: string;
|
|
17
|
+
namespaceUri: string;
|
|
18
|
+
properties: {
|
|
19
|
+
name: string;
|
|
20
|
+
value: string;
|
|
21
|
+
description: string;
|
|
22
|
+
category: any;
|
|
23
|
+
}[];
|
|
24
|
+
}[];
|
|
25
|
+
};
|
|
26
|
+
attachments: {
|
|
27
|
+
name: string;
|
|
28
|
+
data: Uint8Array<ArrayBufferLike>;
|
|
29
|
+
mimeType: string;
|
|
30
|
+
description: string;
|
|
31
|
+
relationship: AttachmentRelationship;
|
|
32
|
+
modificationDate: number;
|
|
33
|
+
compress: boolean | null;
|
|
34
|
+
}[];
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=document-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-options.d.ts","sourceRoot":"","sources":["../src/document-options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAa,sBAAsB,EAA0B,UAAU,EAAgB,MAAM,YAAY,CAAC;AAuJtH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAyDxB,sBAAsB;;;;EAOzD"}
|