renderpdf-js 0.1.0 → 0.2.1
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 +251 -178
- package/dist/api-types.d.ts +63 -4
- package/dist/diagnostics.d.ts +1 -1
- package/dist/export-options.d.ts +12 -0
- package/dist/image-geometry.d.ts +19 -0
- package/dist/image-input.d.ts +19 -0
- package/dist/image-pdf.d.ts +7 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1659 -363
- package/dist/layout.d.ts +4 -0
- package/dist/page-bands.d.ts +24 -0
- package/dist/page.d.ts +7 -3
- package/dist/pagination.d.ts +5 -1
- package/dist/pdf.d.ts +10 -1
- package/dist/progress.d.ts +11 -0
- package/dist/table-borders.d.ts +52 -0
- package/dist/text.d.ts +9 -0
- package/dist/tiff.d.ts +23 -0
- package/dist/types.d.ts +27 -1
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -4,221 +4,294 @@
|
|
|
4
4
|
|
|
5
5
|
# RenderPDF.js
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
with selectable text, local raster fallbacks and automatic pagination. The browser
|
|
9
|
-
calculates layout; RenderPDF.js uses its measured text, box, image and table
|
|
10
|
-
coordinates to write the PDF. Conversion runs entirely on the client.
|
|
7
|
+
**Convert HTML, PNG, JPEG and multipage TIFF to PDF in the browser.**
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/renderpdf-js)
|
|
10
|
+
[](https://github.com/MichalekJan93/renderPDF.js/actions/workflows/check.yml)
|
|
11
|
+
[](https://github.com/MichalekJan93/renderPDF.js/blob/main/LICENSE)
|
|
15
12
|
|
|
16
|
-
|
|
13
|
+
HTML exports use the browser's layout, keep text selectable and split content
|
|
14
|
+
across pages. Conversion runs locally, without a conversion server.
|
|
15
|
+
|
|
16
|
+
**Experimental.** Chromium is the verified browser. Firefox and Safari have not
|
|
17
|
+
been verified. HTML rendering supports the [subset described below](#supported-scope).
|
|
18
|
+
|
|
19
|
+
## Features
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
- Selectable HTML text with embedded fonts, native boxes, images and tables.
|
|
22
|
+
- Automatic pagination, repeated table headers, page headers and page numbers.
|
|
23
|
+
- PNG/JPEG conversion and one PDF page per frame of a multipage TIFF.
|
|
24
|
+
- Paper sizes, margins, document properties, progress events and cancellation.
|
|
25
|
+
- ESM package with TypeScript declarations.
|
|
26
|
+
|
|
27
|
+
## Getting started
|
|
19
28
|
|
|
20
29
|
```sh
|
|
21
30
|
npm install renderpdf-js
|
|
22
31
|
```
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[playground](https://github.com/MichalekJan93/renderPDF.js/tree/main/playground).
|
|
33
|
+
Use the package in a browser application with an ESM bundler, such as Vite.
|
|
34
|
+
The [playground](https://github.com/MichalekJan93/renderPDF.js/tree/main/playground)
|
|
35
|
+
provides an HTML editor, preview and PDF download from a source checkout.
|
|
28
36
|
|
|
29
|
-
##
|
|
37
|
+
## HTML usage
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
Register a font, select an existing element and export it:
|
|
32
40
|
|
|
33
41
|
```ts
|
|
34
|
-
import { registerFont, renderPDF
|
|
42
|
+
import { registerFont, renderPDF } from 'renderpdf-js';
|
|
35
43
|
|
|
36
|
-
//
|
|
44
|
+
// Supply a licensed static TTF/OTF file from your application.
|
|
37
45
|
const response = await fetch('/fonts/MyFont-Regular.ttf');
|
|
38
46
|
if (!response.ok) throw new Error('The document font could not be loaded.');
|
|
39
|
-
|
|
47
|
+
|
|
40
48
|
const regular = await registerFont({
|
|
41
49
|
family: 'Document Sans',
|
|
42
50
|
data: await response.arrayBuffer(),
|
|
43
51
|
});
|
|
44
|
-
|
|
52
|
+
|
|
45
53
|
const source = document.querySelector<HTMLElement>('#invoice');
|
|
46
54
|
if (!source) throw new Error('Invoice element was not found.');
|
|
47
55
|
source.style.fontFamily = 'Document Sans';
|
|
48
56
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
rasterScale: 2,
|
|
57
|
-
fallback: 'auto',
|
|
58
|
-
pageBreak: 'css',
|
|
59
|
-
onWarning: (warning) => console.info(warning.code, warning.message),
|
|
60
|
-
});
|
|
61
|
-
await pdf.download('invoice.pdf');
|
|
62
|
-
// Independent byte and Blob forms do not render the source again.
|
|
63
|
-
const bytes = await pdf.toUint8Array();
|
|
64
|
-
// Applications can preview, store or upload this Blob themselves if required.
|
|
65
|
-
const blob = await pdf.toBlob();
|
|
66
|
-
console.info(pdf.pageCount, bytes.byteLength, blob.type);
|
|
67
|
-
} catch (error) {
|
|
68
|
-
if (error instanceof RenderPDFError) console.error(error.code, error.message);
|
|
69
|
-
else throw error;
|
|
70
|
-
}
|
|
57
|
+
const pdf = await renderPDF(source, {
|
|
58
|
+
fonts: [regular],
|
|
59
|
+
format: 'A4',
|
|
60
|
+
margin: 24,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await pdf.download('invoice.pdf');
|
|
71
64
|
```
|
|
72
65
|
|
|
73
|
-
Register
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
Register every font family, weight and style used by the source, including bold
|
|
67
|
+
and italic faces. For example, add `weight: 700` when registering a bold font.
|
|
68
|
+
The first computed CSS font family must match a registered face. Static TTF/OTF
|
|
69
|
+
files are required; system fonts, variable fonts, WOFF/WOFF2 and font collections
|
|
70
|
+
are unsupported.
|
|
71
|
+
|
|
72
|
+
Keep the source connected to the document and unchanged during export. Its width
|
|
73
|
+
and wrapping are preserved, so it must already fit the page's content width:
|
|
74
|
+
about **745.7 CSS pixels** for A4 with the default margins. Oversized HTML is not
|
|
75
|
+
automatically scaled down.
|
|
76
|
+
|
|
77
|
+
## Standalone image files
|
|
78
|
+
|
|
79
|
+
`imageToPDF` accepts a `File`, `Blob`, `ArrayBuffer` or `Uint8Array`. It detects
|
|
80
|
+
the format from the file contents and requires no HTML element or fonts.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { imageToPDF } from 'renderpdf-js';
|
|
84
|
+
|
|
85
|
+
const fileInput = document.querySelector<HTMLInputElement>('#image');
|
|
86
|
+
const file = fileInput?.files?.[0];
|
|
87
|
+
if (!file) throw new Error('Select a PNG, JPEG or TIFF file.');
|
|
88
|
+
|
|
89
|
+
const pdf = await imageToPDF(file, { format: 'A4', margin: 24 });
|
|
90
|
+
await pdf.download('document.pdf');
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
PNG and JPEG produce one page. Each main TIFF frame produces a page in file order.
|
|
94
|
+
Images are centered and scaled to fit within the margins, preserving their aspect
|
|
95
|
+
ratio; small images can be enlarged. TIFF/EXIF orientations, including mirrored
|
|
96
|
+
orientations and PNG `eXIf`, are applied. JPEG compressed bytes are preserved.
|
|
97
|
+
Image text remains a bitmap; there is no OCR.
|
|
98
|
+
|
|
99
|
+
See [image format limits](#image-format-limits) for supported TIFF profiles.
|
|
100
|
+
TIFF support applies to this API; HTML `<img>` elements accept PNG/JPEG.
|
|
101
|
+
|
|
102
|
+
## Options
|
|
103
|
+
|
|
104
|
+
Both conversion functions accept these settings:
|
|
105
|
+
|
|
106
|
+
| Option | Default | Description |
|
|
107
|
+
| ------------- | ----------------------- | --------------------------------------------------------------------- |
|
|
108
|
+
| `format` | `'A4'` | `'A4'`, `'A3'`, `'Letter'` or `{ width, height }`. |
|
|
109
|
+
| `orientation` | `'portrait'` | `'portrait'` or `'landscape'`. |
|
|
110
|
+
| `margin` | `24` | One value or `{ top, right, bottom, left }`. |
|
|
111
|
+
| `metadata` | Title: `'RenderPDF.js'` | Unicode `title`, `author`, `subject` and `keywords` (a string array). |
|
|
112
|
+
| `onProgress` | — | Receives `{ stage, completed, total }`. |
|
|
113
|
+
| `signal` | — | An `AbortSignal` for cancellation. |
|
|
114
|
+
|
|
115
|
+
Dimensions and margins use **CSS pixels**: `1 px = 0.75 PDF pt`. Custom paper
|
|
116
|
+
dimensions include margins; landscape swaps the supplied width and height.
|
|
117
|
+
|
|
118
|
+
HTML exports also accept:
|
|
119
|
+
|
|
120
|
+
| Option | Default | Description |
|
|
121
|
+
| -------------------- | -------- | -------------------------------------------------------------------------------------- |
|
|
122
|
+
| `fonts` | Required | Registered faces used by the source and page text. |
|
|
123
|
+
| `pageBreak` | `'css'` | Honor supported CSS breaks, or use `'auto'` for geometry alone. |
|
|
124
|
+
| `repeatTableHeaders` | `false` | Repeat native `thead` groups on continuation pages. |
|
|
125
|
+
| `header`, `footer` | — | One plain text line in a reserved area on every page. |
|
|
126
|
+
| `fallback` | `'auto'` | Rasterize supported local effects; `'strict'` requires explicit `data-raster` regions. |
|
|
127
|
+
| `rasterScale` | `2` | Raster pixels per CSS pixel. |
|
|
128
|
+
| `onWarning` | — | Receives export warnings. |
|
|
129
|
+
|
|
130
|
+
### Repeated table headers and page text
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const pdf = await renderPDF(source, {
|
|
134
|
+
fonts: [regular],
|
|
135
|
+
repeatTableHeaders: true,
|
|
136
|
+
header: { text: 'Account statement', height: 32 },
|
|
137
|
+
footer: {
|
|
138
|
+
text: 'Page {pageNumber} of {pageCount}',
|
|
139
|
+
height: 28,
|
|
140
|
+
fontSize: 11,
|
|
141
|
+
align: 'right',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
await pdf.download('statement.pdf');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Header and footer `height` is required and reserves space **in addition to** the
|
|
148
|
+
outer margins. Each accepts one plain Latin text line, including Czech diacritics,
|
|
149
|
+
with `{pageNumber}` and `{pageCount}` placeholders. Text stays selectable and does
|
|
150
|
+
not wrap. `fontSize` defaults to `12`, `align` to `'left'`, and `font` to the first
|
|
151
|
+
face in `fonts`. Alignment can also be `'center'` or `'right'`. Text that does not
|
|
152
|
+
fit fails explicitly. HTML page templates and per-page callbacks are unsupported.
|
|
153
|
+
|
|
154
|
+
### Export progress and document properties
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const pdf = await renderPDF(source, {
|
|
158
|
+
fonts: [regular],
|
|
159
|
+
metadata: { title: 'Account statement', author: 'Example Company' },
|
|
160
|
+
onProgress: ({ stage, completed, total }) => {
|
|
161
|
+
console.log(stage, completed, total);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Counters describe work within the current stage, rather than elapsed-time
|
|
167
|
+
percentages. HTML stages are `preparing`, `layout`, `pagination`, `resources`,
|
|
168
|
+
`pages`, `saving` and `complete`. Image conversion omits `layout` and `pagination`.
|
|
169
|
+
Callbacks are synchronous; a thrown callback error rejects the export. Cancellation
|
|
170
|
+
is cooperative between stages and rejects with `AbortError`, without a partial PDF.
|
|
171
|
+
|
|
172
|
+
## Output and errors
|
|
173
|
+
|
|
174
|
+
Both functions return the same result:
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
await pdf.download('document.pdf');
|
|
178
|
+
const blob = await pdf.toBlob();
|
|
179
|
+
const bytes = await pdf.toUint8Array();
|
|
180
|
+
console.log(pdf.pageCount, pdf.warnings);
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
These output methods reuse the completed PDF. `RenderPDFError`, exported from the
|
|
184
|
+
package, exposes a `code` and `message` for conversion failures. Warnings are
|
|
185
|
+
available through `onWarning` for HTML exports and `pdf.warnings`. Unsupported
|
|
186
|
+
input fails explicitly instead of silently producing a whole-page screenshot.
|
|
82
187
|
|
|
83
188
|
## Supported scope
|
|
84
189
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
and
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
apparently successful export.
|
|
160
|
-
Direct text overlapping later visible paint is also rejected when the simple
|
|
161
|
-
ordered paint list cannot reproduce the browser's block/inline paint phases.
|
|
190
|
+
HTML rendering supports static blocks, inline content, nonoverlapping Flexbox and
|
|
191
|
+
Grid layouts, horizontal Latin text (including Czech diacritics), solid backgrounds,
|
|
192
|
+
rectangular borders and native tables with `rowspan` and `colspan`.
|
|
193
|
+
|
|
194
|
+
PNG/JPEG resources can use data, blob, same-origin or CORS-readable URLs. External
|
|
195
|
+
images may be fetched by the browser; documents are never sent to a conversion
|
|
196
|
+
service. JPEG orientation in HTML must be absent or `1`; normalize rotated pixels
|
|
197
|
+
before using them in an `<img>` element.
|
|
198
|
+
|
|
199
|
+
Gradients, rounded corners, inline bitmap backgrounds, inset shadows and opacity
|
|
200
|
+
can use local raster fallback on supported rectangular blocks. `data-raster`
|
|
201
|
+
selects a region explicitly. Regions are captured once in paint order; descendant
|
|
202
|
+
text gets an extraction layer where safe. Raster resources must be inline bitmaps;
|
|
203
|
+
external resources, transforms, backdrop effects and effects outside the border
|
|
204
|
+
box are unsupported. Wrapped inline backgrounds or borders require a containing
|
|
205
|
+
raster region; inline and table-internal raster boundaries are unsupported.
|
|
206
|
+
|
|
207
|
+
### Pagination and tables
|
|
208
|
+
|
|
209
|
+
The default `pageBreak: 'css'` respects block/table-row `break-before: page`,
|
|
210
|
+
`break-after: page`, their legacy `page-break-*: always` aliases and
|
|
211
|
+
`break-inside: avoid/avoid-page`. Before/after avoidance keeps adjacent complete
|
|
212
|
+
block siblings together when they fit.
|
|
213
|
+
|
|
214
|
+
Text lines, images, raster regions, table rows and spanning cells stay whole.
|
|
215
|
+
Content taller than a page, or a forced break through an indivisible item, fails
|
|
216
|
+
with `PAGINATION_FAILED`. An avoid preference that cannot be honored can be relaxed
|
|
217
|
+
with a `BREAK_AVOID_RELAXED` warning. Parity/column breaks, inline/cell break rules,
|
|
218
|
+
widow/orphan policies and cloned page decorations are unsupported.
|
|
219
|
+
|
|
220
|
+
<details>
|
|
221
|
+
<summary>Table restrictions</summary>
|
|
222
|
+
|
|
223
|
+
Collapsed tables support solid, none and hidden borders on cells and the outer
|
|
224
|
+
table, including different widths, colors and transparency. Shared borders are
|
|
225
|
+
painted once. Row, row-group, column and column-group border contributions, other
|
|
226
|
+
border styles, captions, nested collapsed tables and altered table-part display
|
|
227
|
+
modes are unsupported.
|
|
228
|
+
|
|
229
|
+
Repeated headers require a visible native `thead` followed by body rows. The
|
|
230
|
+
header reserves space on continuation pages and stays with the first body row.
|
|
231
|
+
Headers and rows must fit on a page. Nested tables, raster headers, overlapping
|
|
232
|
+
table ranges, header rowspans and cells spanning the header/body boundary are
|
|
233
|
+
unsupported. Header paint must fit its measured box. Table footers are not repeated.
|
|
234
|
+
Collapsed tables also require matching resolved horizontal borders at every
|
|
235
|
+
possible header/body continuation boundary.
|
|
236
|
+
|
|
237
|
+
</details>
|
|
238
|
+
|
|
239
|
+
### Text and layout limits
|
|
240
|
+
|
|
241
|
+
Default kerning, ligatures and combining marks are supported. Keep shaped words in
|
|
242
|
+
one text node; cross-inline ligatures and zero-width fragments are unsupported.
|
|
243
|
+
Complex scripts, bidirectional text, custom font features/variants, stretched
|
|
244
|
+
faces, font-size adjustment, automatic hyphenation and soft hyphens are unsupported.
|
|
245
|
+
Exact text appearance can vary between shaping engines.
|
|
246
|
+
|
|
247
|
+
Arbitrary CSS stacking and overlapping paint are unsupported. Pause animations
|
|
248
|
+
and keep source styles, geometry and registered fonts stable during export.
|
|
249
|
+
Changes to the source fail with `SOURCE_CHANGED`.
|
|
250
|
+
|
|
251
|
+
### Image format limits
|
|
252
|
+
|
|
253
|
+
- **PNG:** static images only; APNG is rejected.
|
|
254
|
+
- **JPEG:** 8-bit baseline, extended and progressive grayscale, RGB or CMYK.
|
|
255
|
+
- **TIFF:** classic stripped TIFF in either byte order; common bilevel/grayscale,
|
|
256
|
+
palette and 8-bit RGB/RGBA profiles. Compression: uncompressed, CCITT RLE/Group
|
|
257
|
+
3/Group 4, LZW, PackBits and Deflate. Limited to **40 million pixels per frame**
|
|
258
|
+
and **1,000 main frames**.
|
|
259
|
+
|
|
260
|
+
BigTIFF, tiled TIFF, SubIFDs/RAW layouts, planar-separated samples, 16-bit/float
|
|
261
|
+
samples and JPEG-compressed TIFF fail with `UNSUPPORTED_IMAGE`. The TIFF decoder
|
|
262
|
+
loads only when needed. Structural checks reject malformed input, but cannot
|
|
263
|
+
identify every damaged JPEG scan or CCITT bitstream.
|
|
162
264
|
|
|
163
265
|
## Development
|
|
164
266
|
|
|
165
|
-
|
|
166
|
-
|
|
267
|
+
Use Node.js 22.18+ (22.x), 24.11+ (24.x) or 26+. `.node-version` records the
|
|
268
|
+
verified runtime.
|
|
167
269
|
|
|
168
270
|
```sh
|
|
169
271
|
npm ci
|
|
170
272
|
npm run build
|
|
273
|
+
npm run check
|
|
171
274
|
```
|
|
172
275
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
the
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
The playground deliberately uses one explicitly stated font family;
|
|
188
|
-
the reusable API supports multiple families. Private documents and local system
|
|
189
|
-
font programs belong only in ignored `artifacts/`; regression tests use synthetic
|
|
190
|
-
documents and do not require them.
|
|
191
|
-
|
|
192
|
-
Run `npm run check` before submitting a change. It checks types, lint, unit tests,
|
|
193
|
-
browser tests, builds, formatting and package contents. Browser tests require an installed Google
|
|
194
|
-
Chrome and use synthetic fixtures, Playwright and PDF.js; those tools never run in
|
|
195
|
-
conversion code. Generated PDFs, screenshots and reports stay outside versioned
|
|
196
|
-
source files.
|
|
197
|
-
|
|
198
|
-
Typography regressions compare tight browser/PDF text crops for Noto Sans regular,
|
|
199
|
-
bold and italic plus Noto Serif, including Czech accents, ligatures, kerning and
|
|
200
|
-
wrapped mixed-font lines on multiple pages. The [benchmark guide](https://github.com/MichalekJan93/renderPDF.js/blob/main/BENCHMARKS.md)
|
|
201
|
-
describes repeatable exports of small, medium, large and hybrid documents.
|
|
202
|
-
Run `npm run benchmark` to record timings separately from correctness checks.
|
|
203
|
-
GitHub Actions runs the checks and preserves rendered comparisons and timing reports.
|
|
204
|
-
|
|
205
|
-
### Local package
|
|
206
|
-
|
|
207
|
-
`npm pack --pack-destination artifacts` builds the library and checks its contents
|
|
208
|
-
before creating a local archive. Create the `artifacts/` directory first if it is
|
|
209
|
-
absent. The package includes the ESM entry, TypeScript declarations, package metadata,
|
|
210
|
-
README, MIT license and README logo. Demos, test fonts, source files and local
|
|
211
|
-
documents are excluded by an explicit `files` allowlist.
|
|
212
|
-
|
|
213
|
-
`npm run check:package` checks the current build through npm's dry-run inventory;
|
|
214
|
-
run `npm run build:library` first when no build exists. The check rejects missing
|
|
215
|
-
entry points, empty files and unexpected contents. Packaging does not publish the
|
|
216
|
-
library. Maintainers publish a reviewed archive with
|
|
217
|
-
`npm publish ./artifacts/renderpdf-js-<version>.tgz --access public` after updating
|
|
218
|
-
the package version and verifying the packed consumer.
|
|
276
|
+
`npm run check` runs formatting, lint, types, unit tests, browser tests, build and
|
|
277
|
+
package checks. Google Chrome must be installed for browser tests. Vite+ provides
|
|
278
|
+
the development toolchain; Playwright and PDF.js are used for testing.
|
|
279
|
+
|
|
280
|
+
Run `npm run dev` to serve synthetic test fixtures. The independent
|
|
281
|
+
[playground](https://github.com/MichalekJan93/renderPDF.js/tree/main/playground)
|
|
282
|
+
tests the packaged library. See the
|
|
283
|
+
[benchmark guide](https://github.com/MichalekJan93/renderPDF.js/blob/main/BENCHMARKS.md)
|
|
284
|
+
for `npm run benchmark` and timing reports.
|
|
285
|
+
|
|
286
|
+
To create a local package, create `artifacts/` if needed, then run
|
|
287
|
+
`npm pack --pack-destination artifacts`. Only the library build, declarations,
|
|
288
|
+
package metadata, README, license and logo are packaged. Keep private documents
|
|
289
|
+
and generated files out of Git.
|
|
219
290
|
|
|
220
291
|
## License
|
|
221
292
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
293
|
+
[MIT](https://github.com/MichalekJan93/renderPDF.js/blob/main/LICENSE).
|
|
294
|
+
Third-party dependencies retain their own licenses: `utif2` uses MIT and `pako`
|
|
295
|
+
retains MIT/Zlib notices. Noto Sans and Noto Serif test fonts retain the
|
|
296
|
+
[SIL Open Font License](https://github.com/MichalekJan93/renderPDF.js/blob/main/public/fonts/README.md)
|
|
297
|
+
and are not included in the npm package.
|
package/dist/api-types.d.ts
CHANGED
|
@@ -48,26 +48,85 @@ export interface CustomPageSize {
|
|
|
48
48
|
/** Base paper height in CSS pixels, including margins. */
|
|
49
49
|
height: number;
|
|
50
50
|
}
|
|
51
|
-
/**
|
|
52
|
-
export interface
|
|
53
|
-
/**
|
|
54
|
-
|
|
51
|
+
/** One selectable line repeated in a reserved area above or below each page's content. */
|
|
52
|
+
export interface PageTextOptions {
|
|
53
|
+
/** Plain Latin text; {pageNumber} and {pageCount} expand after pagination. */
|
|
54
|
+
text: string;
|
|
55
|
+
/** Reserved height in CSS pixels, in addition to the page's outer margins. */
|
|
56
|
+
height: number;
|
|
57
|
+
/** Exact face included in fonts; defaults to its first registered face. */
|
|
58
|
+
font?: RegisteredFont;
|
|
59
|
+
/** Text size in CSS pixels, defaulting to 12. */
|
|
60
|
+
fontSize?: number;
|
|
61
|
+
/** Horizontal alignment within the page's content width, defaulting to left. */
|
|
62
|
+
align?: 'left' | 'center' | 'right';
|
|
63
|
+
}
|
|
64
|
+
/** Document properties stored in the PDF, independent of visible page content. */
|
|
65
|
+
export interface PDFMetadata {
|
|
66
|
+
/** Human-readable document title; defaults to RenderPDF.js when omitted. */
|
|
67
|
+
title?: string;
|
|
68
|
+
/** Author displayed in PDF document properties. */
|
|
69
|
+
author?: string;
|
|
70
|
+
/** Short description of the document's subject. */
|
|
71
|
+
subject?: string;
|
|
72
|
+
/** Search keywords copied before export begins. */
|
|
73
|
+
keywords?: readonly string[];
|
|
74
|
+
}
|
|
75
|
+
/** Observable export stages; counters describe work within one stage, never elapsed-time estimates. */
|
|
76
|
+
export type RenderStage = 'preparing' | 'layout' | 'pagination' | 'resources' | 'pages' | 'saving' | 'complete';
|
|
77
|
+
/** Immutable progress notification delivered synchronously to the application's callback. */
|
|
78
|
+
export interface RenderProgress {
|
|
79
|
+
/** Current stage, in pipeline order. */
|
|
80
|
+
readonly stage: RenderStage;
|
|
81
|
+
/** Finished work units within the current stage. */
|
|
82
|
+
readonly completed: number;
|
|
83
|
+
/** Known work units in this stage; page totals are available after pagination. */
|
|
84
|
+
readonly total: number;
|
|
85
|
+
}
|
|
86
|
+
/** Shared physical paper settings for HTML and standalone image conversion. */
|
|
87
|
+
export interface PDFPageOptions {
|
|
55
88
|
/** Standard page size (default A4) or explicit physical dimensions in CSS pixels. */
|
|
56
89
|
format?: 'A4' | 'A3' | 'Letter' | CustomPageSize;
|
|
57
90
|
/** Page orientation, defaulting to portrait. */
|
|
58
91
|
orientation?: 'portrait' | 'landscape';
|
|
59
92
|
/** CSS-pixel margins, defaulting to 24 on every edge; content is never implicitly rescaled. */
|
|
60
93
|
margin?: number | PageMargins;
|
|
94
|
+
}
|
|
95
|
+
/** Small supported API surface; unsupported layout fails explicitly. */
|
|
96
|
+
export interface RenderPDFOptions extends PDFPageOptions {
|
|
97
|
+
/** Explicit registered faces used by the supplied source; no implicit font substitution. */
|
|
98
|
+
fonts: readonly RegisteredFont[];
|
|
61
99
|
/** Physical pixels per CSS pixel in selected local raster regions, defaulting to 2. */
|
|
62
100
|
rasterScale?: number;
|
|
63
101
|
/** Automatically rasterize safe local effects (default auto); strict requires explicit data-raster. */
|
|
64
102
|
fallback?: 'auto' | 'strict';
|
|
65
103
|
/** Honor supported CSS page breaks (default css), or use geometry-only automatic cuts. */
|
|
66
104
|
pageBreak?: 'auto' | 'css';
|
|
105
|
+
/** Repeat native THEAD groups on table continuation pages; defaults to false. */
|
|
106
|
+
repeatTableHeaders?: boolean;
|
|
107
|
+
/** Plain text vertically centered in a reserved area above the source on every page. */
|
|
108
|
+
header?: PageTextOptions;
|
|
109
|
+
/** Plain text vertically centered in a reserved area below the source on every page. */
|
|
110
|
+
footer?: PageTextOptions;
|
|
111
|
+
/** Unicode document properties; all supplied values are copied before asynchronous preparation. */
|
|
112
|
+
metadata?: PDFMetadata;
|
|
67
113
|
/** Stop preparation and subsequent rendering stages without producing a partial PDF. */
|
|
68
114
|
signal?: AbortSignal;
|
|
69
115
|
/** Observe documented approximations, raster choices and relaxed pagination preferences. */
|
|
70
116
|
onWarning?: (warning: RenderWarning) => void;
|
|
117
|
+
/** Observe stage-local work counts; the renderer yields for browser updates when provided. */
|
|
118
|
+
onProgress?: (progress: RenderProgress) => void;
|
|
119
|
+
}
|
|
120
|
+
/** One caller-owned image file or its complete binary bytes; the signature determines its format. */
|
|
121
|
+
export type ImageSource = Blob | ArrayBuffer | Uint8Array;
|
|
122
|
+
/** Convert one PNG/JPEG or all main image frames of a TIFF, without HTML or font registration. */
|
|
123
|
+
export interface ImagePDFOptions extends PDFPageOptions {
|
|
124
|
+
/** Copied Unicode PDF properties. */
|
|
125
|
+
metadata?: PDFMetadata;
|
|
126
|
+
/** Cancel between input reading, frame decoding, image embedding and page writing stages. */
|
|
127
|
+
signal?: AbortSignal;
|
|
128
|
+
/** Frozen stage-local counters; image conversion omits HTML layout/pagination stages. */
|
|
129
|
+
onProgress?: (progress: RenderProgress) => void;
|
|
71
130
|
}
|
|
72
131
|
/** Complete PDF result with independently usable browser output forms. */
|
|
73
132
|
export interface RenderPDFResult {
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Machine-readable failure reasons for the supported browser rendering pipeline. */
|
|
2
|
-
export type RenderErrorCode = 'INVALID_OPTIONS' | 'INVALID_SOURCE' | 'FONT_LOAD_FAILED' | 'MISSING_FONT' | 'MISSING_GLYPH' | 'UNSUPPORTED_CSS' | 'UNSUPPORTED_ELEMENT' | 'RESOURCE_LOAD_FAILED' | 'SOURCE_CHANGED' | 'SOURCE_OVERFLOW' | 'PAGINATION_FAILED' | 'RASTER_FAILED' | 'PDF_WRITE_FAILED';
|
|
2
|
+
export type RenderErrorCode = 'INVALID_OPTIONS' | 'INVALID_SOURCE' | 'FONT_LOAD_FAILED' | 'MISSING_FONT' | 'MISSING_GLYPH' | 'UNSUPPORTED_CSS' | 'UNSUPPORTED_ELEMENT' | 'UNSUPPORTED_IMAGE' | 'RESOURCE_LOAD_FAILED' | 'SOURCE_CHANGED' | 'SOURCE_OVERFLOW' | 'PAGINATION_FAILED' | 'RASTER_FAILED' | 'PDF_WRITE_FAILED';
|
|
3
3
|
/** A rendering failure with a stable code and an actionable English explanation. */
|
|
4
4
|
export declare class RenderPDFError extends Error {
|
|
5
5
|
/** Stable category that callers can branch on without parsing message text. */
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PDFMetadata } from './api-types.js';
|
|
2
|
+
import type { PDFDocument } from 'pdf-lib';
|
|
3
|
+
/** Validate and own metadata before the caller can mutate nested settings during an export. */
|
|
4
|
+
export declare function resolveMetadata(
|
|
5
|
+
/** Optional caller-owned PDF document properties. */
|
|
6
|
+
value: PDFMetadata | undefined): Readonly<PDFMetadata> | undefined;
|
|
7
|
+
/** Apply the same document properties for HTML and standalone image exports. */
|
|
8
|
+
export declare function applyPDFMetadata(
|
|
9
|
+
/** PDF document owning these Info dictionary values. */
|
|
10
|
+
pdf: PDFDocument,
|
|
11
|
+
/** Validated, copied properties; omitted fields retain the shared defaults. */
|
|
12
|
+
metadata: Readonly<PDFMetadata> | undefined): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PageGeometry } from './api-types.js';
|
|
2
|
+
/** Bound per-frame decoding allocations while allowing typical 600-DPI A4 scans. */
|
|
3
|
+
export declare const MAX_IMAGE_PIXELS = 40000000;
|
|
4
|
+
/** Reject invalid and excessive dimensions before a decoder allocates pixel buffers. */
|
|
5
|
+
export declare function assertImageSize(
|
|
6
|
+
/** Encoded pixel width, before orientation. */
|
|
7
|
+
width: number,
|
|
8
|
+
/** Encoded pixel height, before orientation. */
|
|
9
|
+
height: number): void;
|
|
10
|
+
/** Fit and orient an image's unit square inside the page, returning a CSS-pixel PDF matrix. */
|
|
11
|
+
export declare function imagePlacement(
|
|
12
|
+
/** Original encoded image width. */
|
|
13
|
+
width: number,
|
|
14
|
+
/** Original encoded image height. */
|
|
15
|
+
height: number,
|
|
16
|
+
/** TIFF/EXIF orientation, including mirrored variants. */
|
|
17
|
+
orientation: number,
|
|
18
|
+
/** Physical page with validated margins. */
|
|
19
|
+
page: PageGeometry): [number, number, number, number, number, number];
|