takumi-pdf 0.14.3 → 0.15.0
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 +26 -219
- package/dist/export.cjs +109 -58
- package/dist/export.d.cts +31 -3
- package/dist/export.d.mts +31 -3
- package/dist/export.mjs +109 -58
- package/package.json +4 -4
- package/pkg/takumi_pdf_wasm_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -7,22 +7,22 @@
|
|
|
7
7
|
|
|
8
8
|
Build invoices and reports with CSS or Tailwind. The renderer writes vector PDF with selectable text.
|
|
9
9
|
|
|
10
|
-
[
|
|
10
|
+
[PDF documentation](https://takumi.kane.tw/docs/pdf) · [Playground](https://takumi.kane.tw/playground)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## How it works
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
`takumi-pdf` runs Takumi's layout and PDF engine in WebAssembly on Node.js, Bun, and Cloudflare Workers. It does not launch a browser process.
|
|
17
17
|
|
|
18
|
-
Pass JSX or a Takumi node tree with CSS. The renderer returns vector PDF bytes with searchable text and embedded subset fonts.
|
|
18
|
+
Pass JSX, an HTML string, or a Takumi node tree with CSS. The renderer returns vector PDF bytes with searchable text and embedded subset fonts.
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
npm install takumi-pdf
|
|
23
|
+
npm install takumi-pdf @takumi-rs/helpers
|
|
24
24
|
# or
|
|
25
|
-
bun add takumi-pdf
|
|
25
|
+
bun add takumi-pdf @takumi-rs/helpers
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Quick start
|
|
@@ -55,224 +55,31 @@ const pdf = await render(
|
|
|
55
55
|
await writeFile("invoice.pdf", pdf);
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
`render()` returns `Promise<Uint8Array>`. Paged output defaults to A4
|
|
58
|
+
`render()` returns `Promise<Uint8Array>`. Paged output defaults to A4, and `margin` defaults to `"auto"` on all sides. Without headers or footers, margins are 37.8px. Top and bottom margins can expand to fit header or footer bands. Content flows across pages automatically.
|
|
59
59
|
|
|
60
|
-
##
|
|
60
|
+
## Choose the next guide
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
73
|
-
| `landscape` | `boolean` | `false` | Swaps page width and height, including explicit sizes. |
|
|
74
|
-
| `margin` | `number` or `{ top?, right?, bottom?, left? }` | `48` | A number applies to all sides. Missing object sides are `0`. |
|
|
75
|
-
|
|
76
|
-
## Headers and footers
|
|
77
|
-
|
|
78
|
-
Headers and footers repeat on every page. `<PageNumber />` and `<TotalPages />` place the counters; the `format` prop picks a CSS counter style.
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
import { render } from "takumi-pdf";
|
|
82
|
-
import { PageNumber, TotalPages } from "takumi-pdf/primitives";
|
|
83
|
-
|
|
84
|
-
const pdf = await render(report, {
|
|
85
|
-
footer: (
|
|
86
|
-
<div style={{ fontSize: 12 }}>
|
|
87
|
-
第 <PageNumber format="trad-chinese-informal" /> 頁,共{" "}
|
|
88
|
-
<TotalPages format="trad-chinese-informal" /> 頁
|
|
89
|
-
</div>
|
|
90
|
-
),
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
The primitives render class hooks, the same `pageNumber` / `totalPages` names Chromium's print templates use, so HTML input writes `<span class="pageNumber"></span>` directly.
|
|
95
|
-
|
|
96
|
-
| Counter style | Example |
|
|
97
|
-
| ------------------------------------------- | ------------- |
|
|
98
|
-
| `decimal` (default) | `12` |
|
|
99
|
-
| `decimal-leading-zero` | `07` |
|
|
100
|
-
| `lower-roman` / `upper-roman` | `xii` / `XII` |
|
|
101
|
-
| `cjk-decimal` | `一二` |
|
|
102
|
-
| `trad-chinese-informal` / `cjk-ideographic` | `十二` |
|
|
62
|
+
| Task | Guide |
|
|
63
|
+
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| Set page size, margins, and runtime imports | [PDF getting started](https://takumi.kane.tw/docs/pdf) |
|
|
65
|
+
| Control page breaks and keep content together | [Pagination](https://takumi.kane.tw/docs/pdf/pagination) |
|
|
66
|
+
| Reserve space for repeated headers and page numbers | [Headers and footers](https://takumi.kane.tw/docs/pdf/headers-and-footers) |
|
|
67
|
+
| Create a certificate, ticket, or receipt | [Single-page output](https://takumi.kane.tw/docs/pdf/single-page) |
|
|
68
|
+
| Load fonts and remote image bytes | [Fonts and images](https://takumi.kane.tw/docs/pdf/fonts-and-images) |
|
|
69
|
+
| Add hyperlinks, bookmarks, and a table of contents | [Links and metadata](https://takumi.kane.tw/docs/pdf/links-and-outline) |
|
|
70
|
+
| Configure archival or accessible output | [PDF/A and PDF/UA](https://takumi.kane.tw/docs/pdf/pdf-a) |
|
|
71
|
+
| Embed invoice XML or another file | [Attachments](https://takumi.kane.tw/docs/pdf/attachments) |
|
|
72
|
+
| Replace a browser or document renderer | [From Puppeteer](https://takumi.kane.tw/docs/pdf/from-puppeteer) · [From react-pdf](https://takumi.kane.tw/docs/pdf/from-react-pdf) |
|
|
103
73
|
|
|
104
|
-
##
|
|
105
|
-
|
|
106
|
-
Use `viewport` for a fixed one-page PDF, such as a certificate or card. Percentage heights resolve against the viewport and overflow is clipped, like an image render.
|
|
107
|
-
|
|
108
|
-
```tsx
|
|
109
|
-
const pdf = await render(<div style={{ width: "100%", height: "100%" }}>Certificate</div>, {
|
|
110
|
-
viewport: { width: 1123, height: 794 },
|
|
111
|
-
});
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
Omit `height` to size the single page to its content, like a thermal receipt. Percentage heights do not resolve there.
|
|
115
|
-
|
|
116
|
-
```tsx
|
|
117
|
-
const pdf = await render(receipt, { viewport: { width: 302 } });
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
`viewport` cannot be combined with `size`, `landscape`, `margin`, `header`, or `footer`.
|
|
121
|
-
|
|
122
|
-
## Fonts
|
|
123
|
-
|
|
124
|
-
Pass a font URL, font bytes, or the `googleFonts` helper. Registered fonts are deduplicated across calls.
|
|
125
|
-
|
|
126
|
-
```tsx
|
|
127
|
-
import { googleFonts } from "@takumi-rs/helpers";
|
|
128
|
-
import { render } from "takumi-pdf";
|
|
129
|
-
|
|
130
|
-
const pdf = await render(doc, {
|
|
131
|
-
fonts: [...(await googleFonts(["Inter"])), { name: "Brand Sans", weight: 700, data: fontBytes }],
|
|
132
|
-
fontFamilies: ["Brand Sans", "Inter", "sans-serif"],
|
|
133
|
-
});
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
Reuse a `PdfRenderer` when an application renders many documents:
|
|
137
|
-
|
|
138
|
-
```tsx
|
|
139
|
-
import { PdfRenderer } from "takumi-pdf";
|
|
140
|
-
|
|
141
|
-
const renderer = new PdfRenderer();
|
|
142
|
-
await renderer.registerFont("https://example.com/Inter-Regular.woff2");
|
|
143
|
-
|
|
144
|
-
const pdf = await renderer.render(doc);
|
|
145
|
-
renderer.free();
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
## Pagination CSS
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
const pdf = await render(
|
|
152
|
-
<article>
|
|
153
|
-
<h1 style={{ breakBefore: "page" }}>Chapter two</h1>
|
|
154
|
-
<section style={{ breakInside: "avoid" }}>Keep this together.</section>
|
|
155
|
-
</article>,
|
|
156
|
-
);
|
|
157
|
-
```
|
|
74
|
+
## Before using an existing template
|
|
158
75
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
| `box-decoration-break: clone` | Repeats borders and backgrounds on every page fragment. |
|
|
165
|
-
|
|
166
|
-
## Tables
|
|
167
|
-
|
|
168
|
-
`<table>` markup lays out on shared column tracks, so column x positions stay identical across pages. A `<thead>` paints again at the top of every page its table continues onto, when it is at most a quarter of the page tall and no header cell spans into the body.
|
|
169
|
-
|
|
170
|
-
```tsx
|
|
171
|
-
const pdf = await render(
|
|
172
|
-
<table>
|
|
173
|
-
<thead>
|
|
174
|
-
<tr>
|
|
175
|
-
<th>Name</th>
|
|
176
|
-
<th>Qty</th>
|
|
177
|
-
</tr>
|
|
178
|
-
</thead>
|
|
179
|
-
<tbody>{rows}</tbody>
|
|
180
|
-
</table>,
|
|
181
|
-
);
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
## Links, outline, and metadata
|
|
185
|
-
|
|
186
|
-
Anchors with an `href` become clickable link annotations. `<TargetPageNumber />` prints the page a link's target lands on, which is what a table of contents needs. `outline: true` builds PDF bookmarks from `h1` through `h6` headings. `metadata` fills the document properties:
|
|
187
|
-
|
|
188
|
-
```tsx
|
|
189
|
-
const pdf = await render(report, {
|
|
190
|
-
outline: true,
|
|
191
|
-
lang: "en",
|
|
192
|
-
metadata: {
|
|
193
|
-
title: "Annual report 2026",
|
|
194
|
-
authors: ["Acme Inc."],
|
|
195
|
-
creationDate: "2026-08-06",
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Omit `metadata` to keep output byte-identical across runs.
|
|
201
|
-
|
|
202
|
-
## Tagged output and PDF/A
|
|
203
|
-
|
|
204
|
-
Output is **tagged by default**: HTML semantics (`h1` through `h6`, `p`, `img` with `alt`, `a`, lists) become a PDF structure tree, like Chromium's print-to-PDF. Set `tagged: "ua1"` to validate against PDF/UA-1, or `tagged: false` to drop the tree when file size matters more than accessibility.
|
|
205
|
-
|
|
206
|
-
`<table>` markup lays out and paints, but carries no `Table` structure elements yet.
|
|
207
|
-
|
|
208
|
-
`pdfa` renders archival output. Validation runs during rendering. A document that cannot conform fails with the violated rule instead of writing a broken file. Every level, and PDF/UA-1, passes [veraPDF](https://verapdf.org).
|
|
209
|
-
|
|
210
|
-
```tsx
|
|
211
|
-
const pdf = await render(report, {
|
|
212
|
-
pdfa: "2a",
|
|
213
|
-
tagged: "ua1",
|
|
214
|
-
lang: "en",
|
|
215
|
-
metadata: { title: "Annual report", creationDate: "2026-08-06" },
|
|
216
|
-
});
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
| Level | What it adds |
|
|
220
|
-
| ------------------------ | ------------------------------------- |
|
|
221
|
-
| `"2b"` / `"2u"` | Basic conformance / Unicode mapping. |
|
|
222
|
-
| `"2a"` / `"3a"` | A tagged structure tree. |
|
|
223
|
-
| `"3b"` / `"3u"` / `"3a"` | Arbitrary file attachments. |
|
|
224
|
-
| `"4"` | The PDF 2.0 revision of the standard. |
|
|
225
|
-
| `"4f"` | PDF 2.0 with file attachments. |
|
|
226
|
-
|
|
227
|
-
Invalid combinations are **TypeScript type errors**. See the [PDF/A docs](https://takumi.kane.tw/docs/pdf/pdf-a) for the structure-tree mapping and required metadata.
|
|
228
|
-
|
|
229
|
-
## Attachments
|
|
230
|
-
|
|
231
|
-
Attach files with `attachments`. They appear in the viewer's attachment panel. Combine with `pdfa: "3b"` for ZUGFeRD and Factur-X electronic invoices:
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
const pdf = await render(invoice, {
|
|
235
|
-
pdfa: "3b",
|
|
236
|
-
metadata: { title: "Invoice 1042", creationDate: "2026-08-06" },
|
|
237
|
-
attachments: [
|
|
238
|
-
{
|
|
239
|
-
name: "factur-x.xml",
|
|
240
|
-
data: xml,
|
|
241
|
-
mimeType: "application/xml",
|
|
242
|
-
description: "Factur-X invoice data",
|
|
243
|
-
relationship: "alternative",
|
|
244
|
-
},
|
|
245
|
-
],
|
|
246
|
-
});
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
The PDF/A-3 levels require `mimeType`, `description`, and a modification date on each attachment. `metadata.creationDate` serves as the date fallback.
|
|
250
|
-
|
|
251
|
-
## Measuring
|
|
252
|
-
|
|
253
|
-
`measure()` lays out a tree without rendering and returns its size in CSS px. Use it to size a header or footer band before setting `margin`:
|
|
254
|
-
|
|
255
|
-
```tsx
|
|
256
|
-
import { measure } from "takumi-pdf";
|
|
257
|
-
|
|
258
|
-
const { height } = await measure(footer, { size: "a4" });
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
## Images and runtimes
|
|
262
|
-
|
|
263
|
-
`takumi-pdf` runs on Node.js, Bun, and Cloudflare Workers.
|
|
264
|
-
|
|
265
|
-
SVG images embed as vectors, not rasterized bitmaps.
|
|
266
|
-
|
|
267
|
-
The renderer does not fetch remote images. Pass pre-fetched bytes for image URLs in the document:
|
|
268
|
-
|
|
269
|
-
```tsx
|
|
270
|
-
const pdf = await render(doc, {
|
|
271
|
-
images: [{ src: "https://example.com/logo.png", data: logoBytes }],
|
|
272
|
-
});
|
|
273
|
-
```
|
|
76
|
+
- **Fonts:** Takumi does not read system fonts. Register fonts that cover your text.
|
|
77
|
+
- **Images:** Fetch remote document images yourself and pass their bytes through `images`.
|
|
78
|
+
- **Page geometry:** Use `size`, `landscape`, and `margin`. CSS `@page` rules are not supported.
|
|
79
|
+
- **Effects:** PDF output rejects CSS `filter: blur()`, `drop-shadow()`, and `backdrop-filter`. Prepare those effects as images before rendering.
|
|
80
|
+
- **Validation:** Tagged PDF is enabled by default. Choose the conformance options your document needs and validate the result.
|
|
274
81
|
|
|
275
|
-
|
|
82
|
+
See the [PDF renderer comparison](https://takumi.kane.tw/docs/pdf/comparison) for recorded benchmarks and rendering differences. Runnable examples cover [invoices and receipts](https://github.com/kane50613/takumi/tree/master/example/generate-invoice) and [Factur-X invoices](https://github.com/kane50613/takumi/tree/master/example/e-invoice).
|
|
276
83
|
|
|
277
84
|
## License
|
|
278
85
|
|
package/dist/export.cjs
CHANGED
|
@@ -103,10 +103,10 @@ function __wbg_get_imports() {
|
|
|
103
103
|
__proto__: null,
|
|
104
104
|
"./takumi_pdf_wasm_bg.js": {
|
|
105
105
|
__proto__: null,
|
|
106
|
-
|
|
106
|
+
__wbg_Error_67e7344beaa85059: function(arg0, arg1) {
|
|
107
107
|
return Error(getStringFromWasm0(arg0, arg1));
|
|
108
108
|
},
|
|
109
|
-
|
|
109
|
+
__wbg_Number_c54e7112a3fa7e3e: function(arg0) {
|
|
110
110
|
return Number(arg0);
|
|
111
111
|
},
|
|
112
112
|
__wbg_String_8564e559799eccda: function(arg0, arg1) {
|
|
@@ -115,55 +115,55 @@ function __wbg_get_imports() {
|
|
|
115
115
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
116
116
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
117
117
|
},
|
|
118
|
-
|
|
118
|
+
__wbg___wbindgen_bigint_get_as_i64_b482365c149396c8: function(arg0, arg1) {
|
|
119
119
|
const v = arg1;
|
|
120
120
|
const ret = typeof v === "bigint" ? v : void 0;
|
|
121
121
|
getDataViewMemory0().setBigInt64(arg0 + 8, isLikeNone(ret) ? BigInt(0) : ret, true);
|
|
122
122
|
getDataViewMemory0().setInt32(arg0 + 0, !isLikeNone(ret), true);
|
|
123
123
|
},
|
|
124
|
-
|
|
124
|
+
__wbg___wbindgen_boolean_get_7a12af2b3f899c5a: function(arg0) {
|
|
125
125
|
const v = arg0;
|
|
126
126
|
const ret = typeof v === "boolean" ? v : void 0;
|
|
127
127
|
return isLikeNone(ret) ? 16777215 : ret ? 1 : 0;
|
|
128
128
|
},
|
|
129
|
-
|
|
129
|
+
__wbg___wbindgen_debug_string_0e68cf47c9cbd9b0: function(arg0, arg1) {
|
|
130
130
|
const ptr1 = passStringToWasm0(debugString(arg1), wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
131
131
|
const len1 = WASM_VECTOR_LEN;
|
|
132
132
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
133
133
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
134
134
|
},
|
|
135
|
-
|
|
135
|
+
__wbg___wbindgen_in_50072d4d6e45c193: function(arg0, arg1) {
|
|
136
136
|
return arg0 in arg1;
|
|
137
137
|
},
|
|
138
|
-
|
|
138
|
+
__wbg___wbindgen_is_bigint_60fc0336cb14f5d7: function(arg0) {
|
|
139
139
|
return typeof arg0 === "bigint";
|
|
140
140
|
},
|
|
141
|
-
|
|
141
|
+
__wbg___wbindgen_is_function_fcda5e3902d732fe: function(arg0) {
|
|
142
142
|
return typeof arg0 === "function";
|
|
143
143
|
},
|
|
144
|
-
|
|
144
|
+
__wbg___wbindgen_is_object_edb6b15aa3afe12e: function(arg0) {
|
|
145
145
|
const val = arg0;
|
|
146
146
|
return typeof val === "object" && val !== null;
|
|
147
147
|
},
|
|
148
|
-
|
|
148
|
+
__wbg___wbindgen_is_string_c4f7cb494a2a21f1: function(arg0) {
|
|
149
149
|
return typeof arg0 === "string";
|
|
150
150
|
},
|
|
151
|
-
|
|
151
|
+
__wbg___wbindgen_is_undefined_8c687d0b90d5b524: function(arg0) {
|
|
152
152
|
return arg0 === void 0;
|
|
153
153
|
},
|
|
154
|
-
|
|
154
|
+
__wbg___wbindgen_jsval_eq_9fdcd3c0a860dd3b: function(arg0, arg1) {
|
|
155
155
|
return arg0 === arg1;
|
|
156
156
|
},
|
|
157
|
-
|
|
157
|
+
__wbg___wbindgen_jsval_loose_eq_3c30021c243b64cd: function(arg0, arg1) {
|
|
158
158
|
return arg0 == arg1;
|
|
159
159
|
},
|
|
160
|
-
|
|
160
|
+
__wbg___wbindgen_number_get_1dc732b810cb937c: function(arg0, arg1) {
|
|
161
161
|
const obj = arg1;
|
|
162
162
|
const ret = typeof obj === "number" ? obj : void 0;
|
|
163
163
|
getDataViewMemory0().setFloat64(arg0 + 8, isLikeNone(ret) ? 0 : ret, true);
|
|
164
164
|
getDataViewMemory0().setInt32(arg0 + 0, !isLikeNone(ret), true);
|
|
165
165
|
},
|
|
166
|
-
|
|
166
|
+
__wbg___wbindgen_string_get_92ab86bb19cbc12f: function(arg0, arg1) {
|
|
167
167
|
const obj = arg1;
|
|
168
168
|
const ret = typeof obj === "string" ? obj : void 0;
|
|
169
169
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
@@ -171,35 +171,35 @@ function __wbg_get_imports() {
|
|
|
171
171
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
172
172
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
173
173
|
},
|
|
174
|
-
|
|
174
|
+
__wbg___wbindgen_throw_5d9e815e6fdf150f: function(arg0, arg1) {
|
|
175
175
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
176
176
|
},
|
|
177
|
-
|
|
177
|
+
__wbg_call_269c5566fbede3eb: function() {
|
|
178
178
|
return handleError(function(arg0, arg1) {
|
|
179
179
|
return arg0.call(arg1);
|
|
180
180
|
}, arguments);
|
|
181
181
|
},
|
|
182
|
-
|
|
182
|
+
__wbg_done_cffed884d87aa22e: function(arg0) {
|
|
183
183
|
return arg0.done;
|
|
184
184
|
},
|
|
185
|
-
|
|
185
|
+
__wbg_entries_972a87586902cf87: function(arg0) {
|
|
186
186
|
return Object.entries(arg0);
|
|
187
187
|
},
|
|
188
|
-
|
|
189
|
-
return arg0[arg1 >>> 0];
|
|
190
|
-
},
|
|
191
|
-
__wbg_get_d173c0308df22d37: function() {
|
|
188
|
+
__wbg_get_6cf5a4d4d8ad3c5a: function() {
|
|
192
189
|
return handleError(function(arg0, arg1) {
|
|
193
190
|
return Reflect.get(arg0, arg1);
|
|
194
191
|
}, arguments);
|
|
195
192
|
},
|
|
196
|
-
|
|
193
|
+
__wbg_get_b1f0ab13c737f856: function(arg0, arg1) {
|
|
194
|
+
return arg0[arg1 >>> 0];
|
|
195
|
+
},
|
|
196
|
+
__wbg_get_unchecked_363572bdd397d473: function(arg0, arg1) {
|
|
197
197
|
return arg0[arg1 >>> 0];
|
|
198
198
|
},
|
|
199
199
|
__wbg_get_with_ref_key_6412cf3094599694: function(arg0, arg1) {
|
|
200
200
|
return arg0[arg1];
|
|
201
201
|
},
|
|
202
|
-
|
|
202
|
+
__wbg_instanceof_ArrayBuffer_d4ff01f8247925ae: function(arg0) {
|
|
203
203
|
let result;
|
|
204
204
|
try {
|
|
205
205
|
result = arg0 instanceof ArrayBuffer;
|
|
@@ -208,7 +208,7 @@ function __wbg_get_imports() {
|
|
|
208
208
|
}
|
|
209
209
|
return result;
|
|
210
210
|
},
|
|
211
|
-
|
|
211
|
+
__wbg_instanceof_Map_1ff6a2b54c899f0d: function(arg0) {
|
|
212
212
|
let result;
|
|
213
213
|
try {
|
|
214
214
|
result = arg0 instanceof Map;
|
|
@@ -217,7 +217,7 @@ function __wbg_get_imports() {
|
|
|
217
217
|
}
|
|
218
218
|
return result;
|
|
219
219
|
},
|
|
220
|
-
|
|
220
|
+
__wbg_instanceof_Uint8Array_598adc0fef426aa8: function(arg0) {
|
|
221
221
|
let result;
|
|
222
222
|
try {
|
|
223
223
|
result = arg0 instanceof Uint8Array;
|
|
@@ -226,63 +226,63 @@ function __wbg_get_imports() {
|
|
|
226
226
|
}
|
|
227
227
|
return result;
|
|
228
228
|
},
|
|
229
|
-
|
|
229
|
+
__wbg_isArray_5674713bb7b79043: function(arg0) {
|
|
230
230
|
return Array.isArray(arg0);
|
|
231
231
|
},
|
|
232
|
-
|
|
232
|
+
__wbg_isSafeInteger_8f51c743827d1ec5: function(arg0) {
|
|
233
233
|
return Number.isSafeInteger(arg0);
|
|
234
234
|
},
|
|
235
|
-
|
|
235
|
+
__wbg_iterator_22ddeb808cf55a6f: function() {
|
|
236
236
|
return Symbol.iterator;
|
|
237
237
|
},
|
|
238
|
-
|
|
238
|
+
__wbg_length_31bdaf014f5fbde2: function(arg0) {
|
|
239
239
|
return arg0.length;
|
|
240
240
|
},
|
|
241
|
-
|
|
241
|
+
__wbg_length_4e1adc0d42e23620: function(arg0) {
|
|
242
242
|
return arg0.length;
|
|
243
243
|
},
|
|
244
|
-
|
|
245
|
-
return new
|
|
244
|
+
__wbg_new_1da3429bc3c4541c: function(arg0) {
|
|
245
|
+
return new Uint8Array(arg0);
|
|
246
246
|
},
|
|
247
|
-
|
|
247
|
+
__wbg_new_a32a1ab6c6655abe: function(arg0, arg1) {
|
|
248
248
|
return new Error(getStringFromWasm0(arg0, arg1));
|
|
249
249
|
},
|
|
250
|
-
|
|
251
|
-
return new Uint8Array(arg0);
|
|
252
|
-
},
|
|
253
|
-
__wbg_new_ebe3e0f6837f0879: function() {
|
|
250
|
+
__wbg_new_bebc3f4757acf305: function() {
|
|
254
251
|
return /* @__PURE__ */ new Object();
|
|
255
252
|
},
|
|
256
|
-
|
|
253
|
+
__wbg_new_ffa92086ea89f79c: function() {
|
|
254
|
+
return new Array();
|
|
255
|
+
},
|
|
256
|
+
__wbg_next_95053e306b1c3aed: function(arg0) {
|
|
257
|
+
return arg0.next;
|
|
258
|
+
},
|
|
259
|
+
__wbg_next_f31ecb8646d2c605: function() {
|
|
257
260
|
return handleError(function(arg0) {
|
|
258
261
|
return arg0.next();
|
|
259
262
|
}, arguments);
|
|
260
263
|
},
|
|
261
|
-
|
|
262
|
-
return arg0.next;
|
|
263
|
-
},
|
|
264
|
-
__wbg_prototypesetcall_de8e0d9553586985: function(arg0, arg1, arg2) {
|
|
264
|
+
__wbg_prototypesetcall_ae9f5e7459250748: function(arg0, arg1, arg2) {
|
|
265
265
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
266
266
|
},
|
|
267
|
+
__wbg_set_13d25b81ab403f5e: function(arg0, arg1, arg2) {
|
|
268
|
+
arg0[arg1 >>> 0] = arg2;
|
|
269
|
+
},
|
|
267
270
|
__wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
|
|
268
271
|
arg0[arg1] = arg2;
|
|
269
272
|
},
|
|
270
|
-
|
|
271
|
-
arg0[arg1 >>> 0] = arg2;
|
|
272
|
-
},
|
|
273
|
-
__wbg_value_1e2369fab29b420e: function(arg0) {
|
|
273
|
+
__wbg_value_c227f843d21da141: function(arg0) {
|
|
274
274
|
return arg0.value;
|
|
275
275
|
},
|
|
276
|
-
|
|
276
|
+
__wbindgen_generic_0000000000000001: function(arg0) {
|
|
277
277
|
return arg0;
|
|
278
278
|
},
|
|
279
|
-
|
|
279
|
+
__wbindgen_generic_0000000000000002: function(arg0) {
|
|
280
280
|
return arg0;
|
|
281
281
|
},
|
|
282
|
-
|
|
282
|
+
__wbindgen_generic_0000000000000003: function(arg0, arg1) {
|
|
283
283
|
return getStringFromWasm0(arg0, arg1);
|
|
284
284
|
},
|
|
285
|
-
|
|
285
|
+
__wbindgen_generic_0000000000000004: function(arg0) {
|
|
286
286
|
return BigInt.asUintN(64, arg0);
|
|
287
287
|
},
|
|
288
288
|
__wbindgen_init_externref_table: function() {
|
|
@@ -529,6 +529,50 @@ function ownCss(css, stylesheets) {
|
|
|
529
529
|
if (stylesheets !== void 0) warnStylesheetsDeprecated();
|
|
530
530
|
return stylesheets ?? [];
|
|
531
531
|
}
|
|
532
|
+
const PAGE_RULES = [
|
|
533
|
+
"first",
|
|
534
|
+
"last",
|
|
535
|
+
"odd",
|
|
536
|
+
"even"
|
|
537
|
+
];
|
|
538
|
+
const PAGE_OVERRIDE_FIELDS = ["header", "footer"];
|
|
539
|
+
function rejectNonObject(value, what) {
|
|
540
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError(`${what} takes an object`);
|
|
541
|
+
}
|
|
542
|
+
function rejectUnknownKeys(object, known, what) {
|
|
543
|
+
const unknown = Object.keys(object).filter((key) => !known.includes(key));
|
|
544
|
+
if (unknown.length > 0) throw new TypeError(`unknown ${what}: ${unknown.join(", ")}`);
|
|
545
|
+
}
|
|
546
|
+
async function resolveRules(input) {
|
|
547
|
+
const resolved = {
|
|
548
|
+
pages: {},
|
|
549
|
+
nodes: [],
|
|
550
|
+
css: []
|
|
551
|
+
};
|
|
552
|
+
rejectNonObject(input, "pages");
|
|
553
|
+
rejectUnknownKeys(input, PAGE_RULES, "page rule");
|
|
554
|
+
for (const rule of PAGE_RULES) {
|
|
555
|
+
const override = input[rule];
|
|
556
|
+
if (override == null) continue;
|
|
557
|
+
rejectNonObject(override, `pages.${rule}`);
|
|
558
|
+
rejectUnknownKeys(override, PAGE_OVERRIDE_FIELDS, `field of pages.${rule}`);
|
|
559
|
+
const page = {};
|
|
560
|
+
for (const band of PAGE_OVERRIDE_FIELDS) {
|
|
561
|
+
const value = override[band];
|
|
562
|
+
if (value == null) continue;
|
|
563
|
+
if (value === false) {
|
|
564
|
+
page[band] = false;
|
|
565
|
+
continue;
|
|
566
|
+
}
|
|
567
|
+
const { node, css } = await resolveNode(value);
|
|
568
|
+
page[band] = node;
|
|
569
|
+
resolved.nodes.push(node);
|
|
570
|
+
resolved.css.push(...css);
|
|
571
|
+
}
|
|
572
|
+
resolved.pages[rule] = page;
|
|
573
|
+
}
|
|
574
|
+
return resolved;
|
|
575
|
+
}
|
|
532
576
|
async function resolveNode(input) {
|
|
533
577
|
if (isNode(input)) return {
|
|
534
578
|
node: input,
|
|
@@ -543,13 +587,18 @@ var PdfRenderer = class {
|
|
|
543
587
|
fonts = new _takumi_rs_helpers_renderer.FontRegistry((font) => this.inner.registerFont(font));
|
|
544
588
|
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
545
589
|
async render(node, options = {}) {
|
|
546
|
-
const { fonts, images, header, footer, css, stylesheets, fontFamilies, ...rest } = options;
|
|
547
|
-
const [main, headerResult, footerResult] = await Promise.all([
|
|
590
|
+
const { fonts, images, header, footer, pages, css, stylesheets, fontFamilies, ...rest } = options;
|
|
591
|
+
const [main, headerResult, footerResult, pagesResult] = await Promise.all([
|
|
548
592
|
resolveNode(node),
|
|
549
|
-
header ===
|
|
550
|
-
footer ===
|
|
593
|
+
header == null || header === false ? void 0 : resolveNode(header),
|
|
594
|
+
footer == null || footer === false ? void 0 : resolveNode(footer),
|
|
595
|
+
pages == null ? void 0 : resolveRules(pages)
|
|
551
596
|
]);
|
|
552
|
-
const bands = [
|
|
597
|
+
const bands = [
|
|
598
|
+
headerResult?.node,
|
|
599
|
+
footerResult?.node,
|
|
600
|
+
...pagesResult?.nodes ?? []
|
|
601
|
+
].filter((band) => band !== void 0);
|
|
553
602
|
const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
|
|
554
603
|
fonts,
|
|
555
604
|
source: [
|
|
@@ -563,12 +612,14 @@ var PdfRenderer = class {
|
|
|
563
612
|
...ownCss(css, stylesheets),
|
|
564
613
|
...main.css,
|
|
565
614
|
...headerResult?.css ?? [],
|
|
566
|
-
...footerResult?.css ?? []
|
|
615
|
+
...footerResult?.css ?? [],
|
|
616
|
+
...pagesResult?.css ?? []
|
|
567
617
|
];
|
|
568
618
|
return this.inner.render(main.node, {
|
|
569
619
|
...rest,
|
|
570
620
|
header: headerResult?.node,
|
|
571
621
|
footer: footerResult?.node,
|
|
622
|
+
pages: pagesResult?.pages,
|
|
572
623
|
css: sheets.length > 0 ? sheets : void 0,
|
|
573
624
|
images: resources.images,
|
|
574
625
|
fontFamilies: resources.fontFamilies
|
package/dist/export.d.cts
CHANGED
|
@@ -48,6 +48,20 @@ declare function __wbg_init(module_or_path?: {
|
|
|
48
48
|
//#region src/export.d.ts
|
|
49
49
|
/** A document input: a takumi node tree, JSX, or an HTML string. */
|
|
50
50
|
type NodeInput = Node | ReactNode | ReactElementLike | string;
|
|
51
|
+
/** A band on a page: a document input, or `false` for none. */
|
|
52
|
+
type BandInput = NodeInput | false;
|
|
53
|
+
/** What some pages draw instead of the document's own bands. A field left out falls through. */
|
|
54
|
+
type PageOverrideInput = {
|
|
55
|
+
header?: BandInput;
|
|
56
|
+
footer?: BandInput;
|
|
57
|
+
};
|
|
58
|
+
/** Overrides keyed by the pages they cover. `first` and `last` win over `odd` and `even`. */
|
|
59
|
+
type PageRulesInput = {
|
|
60
|
+
first?: PageOverrideInput;
|
|
61
|
+
last?: PageOverrideInput;
|
|
62
|
+
odd?: PageOverrideInput;
|
|
63
|
+
even?: PageOverrideInput;
|
|
64
|
+
};
|
|
51
65
|
/** Explicit dimensions in CSS px (96 dpi). */
|
|
52
66
|
type Dimensions = {
|
|
53
67
|
width: number;
|
|
@@ -83,6 +97,8 @@ type PageRange = number | {
|
|
|
83
97
|
from?: number;
|
|
84
98
|
to?: number;
|
|
85
99
|
};
|
|
100
|
+
/** What a character no registered font covers turns into on the page. */
|
|
101
|
+
type UncoveredText = "error" | "placeholder" | "blank";
|
|
86
102
|
/**
|
|
87
103
|
* Paged output (the default): content flows across pages of `size`, like
|
|
88
104
|
* Puppeteer's `page.pdf()`. The layout canvas has unbounded height, so
|
|
@@ -103,9 +119,11 @@ type PagedOptions = {
|
|
|
103
119
|
* templates; add a CSS `@counter-style` name (e.g. `cjk-decimal`,
|
|
104
120
|
* `lower-roman`) to the class list to format it.
|
|
105
121
|
*/
|
|
106
|
-
header?:
|
|
122
|
+
header?: BandInput;
|
|
107
123
|
/** Band repeated at the bottom of every page; same class hooks as `header`. */
|
|
108
|
-
footer?:
|
|
124
|
+
footer?: BandInput;
|
|
125
|
+
/** What some pages draw differently from the rest. */
|
|
126
|
+
pages?: PageRulesInput;
|
|
109
127
|
/**
|
|
110
128
|
* The pages the output keeps, e.g. `[1, { from: 4, to: 8 }]`, like a print
|
|
111
129
|
* dialog's page ranges. Layout and page counters still run over the whole
|
|
@@ -127,6 +145,7 @@ type ViewportOptions = {
|
|
|
127
145
|
margin?: never;
|
|
128
146
|
header?: never;
|
|
129
147
|
footer?: never;
|
|
148
|
+
pages?: never;
|
|
130
149
|
pageRanges?: never;
|
|
131
150
|
};
|
|
132
151
|
/**
|
|
@@ -306,6 +325,15 @@ type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
|
306
325
|
* Unset leaves the page empty, so a viewer shows its own white.
|
|
307
326
|
*/
|
|
308
327
|
backgroundColor?: string;
|
|
328
|
+
/**
|
|
329
|
+
* What a character no registered font covers turns into: `"error"` (default)
|
|
330
|
+
* fails the render naming it, `"placeholder"` draws the font's glyph 0, and
|
|
331
|
+
* `"blank"` draws nothing. Neither of the last two reflows the line.
|
|
332
|
+
*
|
|
333
|
+
* `"placeholder"` is rejected with any `pdfa` level or `tagged: "ua1"` /
|
|
334
|
+
* `"ua2"`, which forbid glyph 0.
|
|
335
|
+
*/
|
|
336
|
+
uncoveredText?: UncoveredText;
|
|
309
337
|
};
|
|
310
338
|
/** A PDF renderer holding registered fonts. Reuse one instance across renders. */
|
|
311
339
|
declare class PdfRenderer {
|
|
@@ -335,4 +363,4 @@ declare function render(node: NodeInput, options?: RenderOptions): Promise<Uint8
|
|
|
335
363
|
/** Measures with a lazily created shared {@link PdfRenderer}. */
|
|
336
364
|
declare function measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
|
|
337
365
|
//#endregion
|
|
338
|
-
export { ArchivalAttachment, Attachment, type CounterProps, type CounterStyle, Dimensions, type FontLoader, type ImagesInput, MeasureOptions, MeasuredSize, NodeInput, PageMargin, PageMarginSide, PageNumber, PageRange, PageSize, PageSizeName, PdfMetadata, PdfRenderer, RenderOptions, TargetPageNumber, TotalPages, ViewportInput, XmpProperty, XmpSchema, __wbg_init as default, initSync, measure, render };
|
|
366
|
+
export { ArchivalAttachment, Attachment, BandInput, type CounterProps, type CounterStyle, Dimensions, type FontLoader, type ImagesInput, MeasureOptions, MeasuredSize, NodeInput, PageMargin, PageMarginSide, PageNumber, PageOverrideInput, PageRange, PageRulesInput, PageSize, PageSizeName, PdfMetadata, PdfRenderer, RenderOptions, TargetPageNumber, TotalPages, UncoveredText, ViewportInput, XmpProperty, XmpSchema, __wbg_init as default, initSync, measure, render };
|
package/dist/export.d.mts
CHANGED
|
@@ -48,6 +48,20 @@ declare function __wbg_init(module_or_path?: {
|
|
|
48
48
|
//#region src/export.d.ts
|
|
49
49
|
/** A document input: a takumi node tree, JSX, or an HTML string. */
|
|
50
50
|
type NodeInput = Node | ReactNode | ReactElementLike | string;
|
|
51
|
+
/** A band on a page: a document input, or `false` for none. */
|
|
52
|
+
type BandInput = NodeInput | false;
|
|
53
|
+
/** What some pages draw instead of the document's own bands. A field left out falls through. */
|
|
54
|
+
type PageOverrideInput = {
|
|
55
|
+
header?: BandInput;
|
|
56
|
+
footer?: BandInput;
|
|
57
|
+
};
|
|
58
|
+
/** Overrides keyed by the pages they cover. `first` and `last` win over `odd` and `even`. */
|
|
59
|
+
type PageRulesInput = {
|
|
60
|
+
first?: PageOverrideInput;
|
|
61
|
+
last?: PageOverrideInput;
|
|
62
|
+
odd?: PageOverrideInput;
|
|
63
|
+
even?: PageOverrideInput;
|
|
64
|
+
};
|
|
51
65
|
/** Explicit dimensions in CSS px (96 dpi). */
|
|
52
66
|
type Dimensions = {
|
|
53
67
|
width: number;
|
|
@@ -83,6 +97,8 @@ type PageRange = number | {
|
|
|
83
97
|
from?: number;
|
|
84
98
|
to?: number;
|
|
85
99
|
};
|
|
100
|
+
/** What a character no registered font covers turns into on the page. */
|
|
101
|
+
type UncoveredText = "error" | "placeholder" | "blank";
|
|
86
102
|
/**
|
|
87
103
|
* Paged output (the default): content flows across pages of `size`, like
|
|
88
104
|
* Puppeteer's `page.pdf()`. The layout canvas has unbounded height, so
|
|
@@ -103,9 +119,11 @@ type PagedOptions = {
|
|
|
103
119
|
* templates; add a CSS `@counter-style` name (e.g. `cjk-decimal`,
|
|
104
120
|
* `lower-roman`) to the class list to format it.
|
|
105
121
|
*/
|
|
106
|
-
header?:
|
|
122
|
+
header?: BandInput;
|
|
107
123
|
/** Band repeated at the bottom of every page; same class hooks as `header`. */
|
|
108
|
-
footer?:
|
|
124
|
+
footer?: BandInput;
|
|
125
|
+
/** What some pages draw differently from the rest. */
|
|
126
|
+
pages?: PageRulesInput;
|
|
109
127
|
/**
|
|
110
128
|
* The pages the output keeps, e.g. `[1, { from: 4, to: 8 }]`, like a print
|
|
111
129
|
* dialog's page ranges. Layout and page counters still run over the whole
|
|
@@ -127,6 +145,7 @@ type ViewportOptions = {
|
|
|
127
145
|
margin?: never;
|
|
128
146
|
header?: never;
|
|
129
147
|
footer?: never;
|
|
148
|
+
pages?: never;
|
|
130
149
|
pageRanges?: never;
|
|
131
150
|
};
|
|
132
151
|
/**
|
|
@@ -306,6 +325,15 @@ type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
|
306
325
|
* Unset leaves the page empty, so a viewer shows its own white.
|
|
307
326
|
*/
|
|
308
327
|
backgroundColor?: string;
|
|
328
|
+
/**
|
|
329
|
+
* What a character no registered font covers turns into: `"error"` (default)
|
|
330
|
+
* fails the render naming it, `"placeholder"` draws the font's glyph 0, and
|
|
331
|
+
* `"blank"` draws nothing. Neither of the last two reflows the line.
|
|
332
|
+
*
|
|
333
|
+
* `"placeholder"` is rejected with any `pdfa` level or `tagged: "ua1"` /
|
|
334
|
+
* `"ua2"`, which forbid glyph 0.
|
|
335
|
+
*/
|
|
336
|
+
uncoveredText?: UncoveredText;
|
|
309
337
|
};
|
|
310
338
|
/** A PDF renderer holding registered fonts. Reuse one instance across renders. */
|
|
311
339
|
declare class PdfRenderer {
|
|
@@ -335,4 +363,4 @@ declare function render(node: NodeInput, options?: RenderOptions): Promise<Uint8
|
|
|
335
363
|
/** Measures with a lazily created shared {@link PdfRenderer}. */
|
|
336
364
|
declare function measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
|
|
337
365
|
//#endregion
|
|
338
|
-
export { ArchivalAttachment, Attachment, type CounterProps, type CounterStyle, Dimensions, type FontLoader, type ImagesInput, MeasureOptions, MeasuredSize, NodeInput, PageMargin, PageMarginSide, PageNumber, PageRange, PageSize, PageSizeName, PdfMetadata, PdfRenderer, RenderOptions, TargetPageNumber, TotalPages, ViewportInput, XmpProperty, XmpSchema, __wbg_init as default, initSync, measure, render };
|
|
366
|
+
export { ArchivalAttachment, Attachment, BandInput, type CounterProps, type CounterStyle, Dimensions, type FontLoader, type ImagesInput, MeasureOptions, MeasuredSize, NodeInput, PageMargin, PageMarginSide, PageNumber, PageOverrideInput, PageRange, PageRulesInput, PageSize, PageSizeName, PdfMetadata, PdfRenderer, RenderOptions, TargetPageNumber, TotalPages, UncoveredText, ViewportInput, XmpProperty, XmpSchema, __wbg_init as default, initSync, measure, render };
|
package/dist/export.mjs
CHANGED
|
@@ -99,10 +99,10 @@ function __wbg_get_imports() {
|
|
|
99
99
|
__proto__: null,
|
|
100
100
|
"./takumi_pdf_wasm_bg.js": {
|
|
101
101
|
__proto__: null,
|
|
102
|
-
|
|
102
|
+
__wbg_Error_67e7344beaa85059: function(arg0, arg1) {
|
|
103
103
|
return Error(getStringFromWasm0(arg0, arg1));
|
|
104
104
|
},
|
|
105
|
-
|
|
105
|
+
__wbg_Number_c54e7112a3fa7e3e: function(arg0) {
|
|
106
106
|
return Number(arg0);
|
|
107
107
|
},
|
|
108
108
|
__wbg_String_8564e559799eccda: function(arg0, arg1) {
|
|
@@ -111,55 +111,55 @@ function __wbg_get_imports() {
|
|
|
111
111
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
112
112
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
113
113
|
},
|
|
114
|
-
|
|
114
|
+
__wbg___wbindgen_bigint_get_as_i64_b482365c149396c8: function(arg0, arg1) {
|
|
115
115
|
const v = arg1;
|
|
116
116
|
const ret = typeof v === "bigint" ? v : void 0;
|
|
117
117
|
getDataViewMemory0().setBigInt64(arg0 + 8, isLikeNone(ret) ? BigInt(0) : ret, true);
|
|
118
118
|
getDataViewMemory0().setInt32(arg0 + 0, !isLikeNone(ret), true);
|
|
119
119
|
},
|
|
120
|
-
|
|
120
|
+
__wbg___wbindgen_boolean_get_7a12af2b3f899c5a: function(arg0) {
|
|
121
121
|
const v = arg0;
|
|
122
122
|
const ret = typeof v === "boolean" ? v : void 0;
|
|
123
123
|
return isLikeNone(ret) ? 16777215 : ret ? 1 : 0;
|
|
124
124
|
},
|
|
125
|
-
|
|
125
|
+
__wbg___wbindgen_debug_string_0e68cf47c9cbd9b0: function(arg0, arg1) {
|
|
126
126
|
const ptr1 = passStringToWasm0(debugString(arg1), wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
127
127
|
const len1 = WASM_VECTOR_LEN;
|
|
128
128
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
129
129
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
130
130
|
},
|
|
131
|
-
|
|
131
|
+
__wbg___wbindgen_in_50072d4d6e45c193: function(arg0, arg1) {
|
|
132
132
|
return arg0 in arg1;
|
|
133
133
|
},
|
|
134
|
-
|
|
134
|
+
__wbg___wbindgen_is_bigint_60fc0336cb14f5d7: function(arg0) {
|
|
135
135
|
return typeof arg0 === "bigint";
|
|
136
136
|
},
|
|
137
|
-
|
|
137
|
+
__wbg___wbindgen_is_function_fcda5e3902d732fe: function(arg0) {
|
|
138
138
|
return typeof arg0 === "function";
|
|
139
139
|
},
|
|
140
|
-
|
|
140
|
+
__wbg___wbindgen_is_object_edb6b15aa3afe12e: function(arg0) {
|
|
141
141
|
const val = arg0;
|
|
142
142
|
return typeof val === "object" && val !== null;
|
|
143
143
|
},
|
|
144
|
-
|
|
144
|
+
__wbg___wbindgen_is_string_c4f7cb494a2a21f1: function(arg0) {
|
|
145
145
|
return typeof arg0 === "string";
|
|
146
146
|
},
|
|
147
|
-
|
|
147
|
+
__wbg___wbindgen_is_undefined_8c687d0b90d5b524: function(arg0) {
|
|
148
148
|
return arg0 === void 0;
|
|
149
149
|
},
|
|
150
|
-
|
|
150
|
+
__wbg___wbindgen_jsval_eq_9fdcd3c0a860dd3b: function(arg0, arg1) {
|
|
151
151
|
return arg0 === arg1;
|
|
152
152
|
},
|
|
153
|
-
|
|
153
|
+
__wbg___wbindgen_jsval_loose_eq_3c30021c243b64cd: function(arg0, arg1) {
|
|
154
154
|
return arg0 == arg1;
|
|
155
155
|
},
|
|
156
|
-
|
|
156
|
+
__wbg___wbindgen_number_get_1dc732b810cb937c: function(arg0, arg1) {
|
|
157
157
|
const obj = arg1;
|
|
158
158
|
const ret = typeof obj === "number" ? obj : void 0;
|
|
159
159
|
getDataViewMemory0().setFloat64(arg0 + 8, isLikeNone(ret) ? 0 : ret, true);
|
|
160
160
|
getDataViewMemory0().setInt32(arg0 + 0, !isLikeNone(ret), true);
|
|
161
161
|
},
|
|
162
|
-
|
|
162
|
+
__wbg___wbindgen_string_get_92ab86bb19cbc12f: function(arg0, arg1) {
|
|
163
163
|
const obj = arg1;
|
|
164
164
|
const ret = typeof obj === "string" ? obj : void 0;
|
|
165
165
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
@@ -167,35 +167,35 @@ function __wbg_get_imports() {
|
|
|
167
167
|
getDataViewMemory0().setInt32(arg0 + 4, len1, true);
|
|
168
168
|
getDataViewMemory0().setInt32(arg0 + 0, ptr1, true);
|
|
169
169
|
},
|
|
170
|
-
|
|
170
|
+
__wbg___wbindgen_throw_5d9e815e6fdf150f: function(arg0, arg1) {
|
|
171
171
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
172
172
|
},
|
|
173
|
-
|
|
173
|
+
__wbg_call_269c5566fbede3eb: function() {
|
|
174
174
|
return handleError(function(arg0, arg1) {
|
|
175
175
|
return arg0.call(arg1);
|
|
176
176
|
}, arguments);
|
|
177
177
|
},
|
|
178
|
-
|
|
178
|
+
__wbg_done_cffed884d87aa22e: function(arg0) {
|
|
179
179
|
return arg0.done;
|
|
180
180
|
},
|
|
181
|
-
|
|
181
|
+
__wbg_entries_972a87586902cf87: function(arg0) {
|
|
182
182
|
return Object.entries(arg0);
|
|
183
183
|
},
|
|
184
|
-
|
|
185
|
-
return arg0[arg1 >>> 0];
|
|
186
|
-
},
|
|
187
|
-
__wbg_get_d173c0308df22d37: function() {
|
|
184
|
+
__wbg_get_6cf5a4d4d8ad3c5a: function() {
|
|
188
185
|
return handleError(function(arg0, arg1) {
|
|
189
186
|
return Reflect.get(arg0, arg1);
|
|
190
187
|
}, arguments);
|
|
191
188
|
},
|
|
192
|
-
|
|
189
|
+
__wbg_get_b1f0ab13c737f856: function(arg0, arg1) {
|
|
190
|
+
return arg0[arg1 >>> 0];
|
|
191
|
+
},
|
|
192
|
+
__wbg_get_unchecked_363572bdd397d473: function(arg0, arg1) {
|
|
193
193
|
return arg0[arg1 >>> 0];
|
|
194
194
|
},
|
|
195
195
|
__wbg_get_with_ref_key_6412cf3094599694: function(arg0, arg1) {
|
|
196
196
|
return arg0[arg1];
|
|
197
197
|
},
|
|
198
|
-
|
|
198
|
+
__wbg_instanceof_ArrayBuffer_d4ff01f8247925ae: function(arg0) {
|
|
199
199
|
let result;
|
|
200
200
|
try {
|
|
201
201
|
result = arg0 instanceof ArrayBuffer;
|
|
@@ -204,7 +204,7 @@ function __wbg_get_imports() {
|
|
|
204
204
|
}
|
|
205
205
|
return result;
|
|
206
206
|
},
|
|
207
|
-
|
|
207
|
+
__wbg_instanceof_Map_1ff6a2b54c899f0d: function(arg0) {
|
|
208
208
|
let result;
|
|
209
209
|
try {
|
|
210
210
|
result = arg0 instanceof Map;
|
|
@@ -213,7 +213,7 @@ function __wbg_get_imports() {
|
|
|
213
213
|
}
|
|
214
214
|
return result;
|
|
215
215
|
},
|
|
216
|
-
|
|
216
|
+
__wbg_instanceof_Uint8Array_598adc0fef426aa8: function(arg0) {
|
|
217
217
|
let result;
|
|
218
218
|
try {
|
|
219
219
|
result = arg0 instanceof Uint8Array;
|
|
@@ -222,63 +222,63 @@ function __wbg_get_imports() {
|
|
|
222
222
|
}
|
|
223
223
|
return result;
|
|
224
224
|
},
|
|
225
|
-
|
|
225
|
+
__wbg_isArray_5674713bb7b79043: function(arg0) {
|
|
226
226
|
return Array.isArray(arg0);
|
|
227
227
|
},
|
|
228
|
-
|
|
228
|
+
__wbg_isSafeInteger_8f51c743827d1ec5: function(arg0) {
|
|
229
229
|
return Number.isSafeInteger(arg0);
|
|
230
230
|
},
|
|
231
|
-
|
|
231
|
+
__wbg_iterator_22ddeb808cf55a6f: function() {
|
|
232
232
|
return Symbol.iterator;
|
|
233
233
|
},
|
|
234
|
-
|
|
234
|
+
__wbg_length_31bdaf014f5fbde2: function(arg0) {
|
|
235
235
|
return arg0.length;
|
|
236
236
|
},
|
|
237
|
-
|
|
237
|
+
__wbg_length_4e1adc0d42e23620: function(arg0) {
|
|
238
238
|
return arg0.length;
|
|
239
239
|
},
|
|
240
|
-
|
|
241
|
-
return new
|
|
240
|
+
__wbg_new_1da3429bc3c4541c: function(arg0) {
|
|
241
|
+
return new Uint8Array(arg0);
|
|
242
242
|
},
|
|
243
|
-
|
|
243
|
+
__wbg_new_a32a1ab6c6655abe: function(arg0, arg1) {
|
|
244
244
|
return new Error(getStringFromWasm0(arg0, arg1));
|
|
245
245
|
},
|
|
246
|
-
|
|
247
|
-
return new Uint8Array(arg0);
|
|
248
|
-
},
|
|
249
|
-
__wbg_new_ebe3e0f6837f0879: function() {
|
|
246
|
+
__wbg_new_bebc3f4757acf305: function() {
|
|
250
247
|
return /* @__PURE__ */ new Object();
|
|
251
248
|
},
|
|
252
|
-
|
|
249
|
+
__wbg_new_ffa92086ea89f79c: function() {
|
|
250
|
+
return new Array();
|
|
251
|
+
},
|
|
252
|
+
__wbg_next_95053e306b1c3aed: function(arg0) {
|
|
253
|
+
return arg0.next;
|
|
254
|
+
},
|
|
255
|
+
__wbg_next_f31ecb8646d2c605: function() {
|
|
253
256
|
return handleError(function(arg0) {
|
|
254
257
|
return arg0.next();
|
|
255
258
|
}, arguments);
|
|
256
259
|
},
|
|
257
|
-
|
|
258
|
-
return arg0.next;
|
|
259
|
-
},
|
|
260
|
-
__wbg_prototypesetcall_de8e0d9553586985: function(arg0, arg1, arg2) {
|
|
260
|
+
__wbg_prototypesetcall_ae9f5e7459250748: function(arg0, arg1, arg2) {
|
|
261
261
|
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
262
262
|
},
|
|
263
|
+
__wbg_set_13d25b81ab403f5e: function(arg0, arg1, arg2) {
|
|
264
|
+
arg0[arg1 >>> 0] = arg2;
|
|
265
|
+
},
|
|
263
266
|
__wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
|
|
264
267
|
arg0[arg1] = arg2;
|
|
265
268
|
},
|
|
266
|
-
|
|
267
|
-
arg0[arg1 >>> 0] = arg2;
|
|
268
|
-
},
|
|
269
|
-
__wbg_value_1e2369fab29b420e: function(arg0) {
|
|
269
|
+
__wbg_value_c227f843d21da141: function(arg0) {
|
|
270
270
|
return arg0.value;
|
|
271
271
|
},
|
|
272
|
-
|
|
272
|
+
__wbindgen_generic_0000000000000001: function(arg0) {
|
|
273
273
|
return arg0;
|
|
274
274
|
},
|
|
275
|
-
|
|
275
|
+
__wbindgen_generic_0000000000000002: function(arg0) {
|
|
276
276
|
return arg0;
|
|
277
277
|
},
|
|
278
|
-
|
|
278
|
+
__wbindgen_generic_0000000000000003: function(arg0, arg1) {
|
|
279
279
|
return getStringFromWasm0(arg0, arg1);
|
|
280
280
|
},
|
|
281
|
-
|
|
281
|
+
__wbindgen_generic_0000000000000004: function(arg0) {
|
|
282
282
|
return BigInt.asUintN(64, arg0);
|
|
283
283
|
},
|
|
284
284
|
__wbindgen_init_externref_table: function() {
|
|
@@ -525,6 +525,50 @@ function ownCss(css, stylesheets) {
|
|
|
525
525
|
if (stylesheets !== void 0) warnStylesheetsDeprecated();
|
|
526
526
|
return stylesheets ?? [];
|
|
527
527
|
}
|
|
528
|
+
const PAGE_RULES = [
|
|
529
|
+
"first",
|
|
530
|
+
"last",
|
|
531
|
+
"odd",
|
|
532
|
+
"even"
|
|
533
|
+
];
|
|
534
|
+
const PAGE_OVERRIDE_FIELDS = ["header", "footer"];
|
|
535
|
+
function rejectNonObject(value, what) {
|
|
536
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new TypeError(`${what} takes an object`);
|
|
537
|
+
}
|
|
538
|
+
function rejectUnknownKeys(object, known, what) {
|
|
539
|
+
const unknown = Object.keys(object).filter((key) => !known.includes(key));
|
|
540
|
+
if (unknown.length > 0) throw new TypeError(`unknown ${what}: ${unknown.join(", ")}`);
|
|
541
|
+
}
|
|
542
|
+
async function resolveRules(input) {
|
|
543
|
+
const resolved = {
|
|
544
|
+
pages: {},
|
|
545
|
+
nodes: [],
|
|
546
|
+
css: []
|
|
547
|
+
};
|
|
548
|
+
rejectNonObject(input, "pages");
|
|
549
|
+
rejectUnknownKeys(input, PAGE_RULES, "page rule");
|
|
550
|
+
for (const rule of PAGE_RULES) {
|
|
551
|
+
const override = input[rule];
|
|
552
|
+
if (override == null) continue;
|
|
553
|
+
rejectNonObject(override, `pages.${rule}`);
|
|
554
|
+
rejectUnknownKeys(override, PAGE_OVERRIDE_FIELDS, `field of pages.${rule}`);
|
|
555
|
+
const page = {};
|
|
556
|
+
for (const band of PAGE_OVERRIDE_FIELDS) {
|
|
557
|
+
const value = override[band];
|
|
558
|
+
if (value == null) continue;
|
|
559
|
+
if (value === false) {
|
|
560
|
+
page[band] = false;
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
const { node, css } = await resolveNode(value);
|
|
564
|
+
page[band] = node;
|
|
565
|
+
resolved.nodes.push(node);
|
|
566
|
+
resolved.css.push(...css);
|
|
567
|
+
}
|
|
568
|
+
resolved.pages[rule] = page;
|
|
569
|
+
}
|
|
570
|
+
return resolved;
|
|
571
|
+
}
|
|
528
572
|
async function resolveNode(input) {
|
|
529
573
|
if (isNode(input)) return {
|
|
530
574
|
node: input,
|
|
@@ -539,13 +583,18 @@ var PdfRenderer = class {
|
|
|
539
583
|
fonts = new FontRegistry((font) => this.inner.registerFont(font));
|
|
540
584
|
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
541
585
|
async render(node, options = {}) {
|
|
542
|
-
const { fonts, images, header, footer, css, stylesheets, fontFamilies, ...rest } = options;
|
|
543
|
-
const [main, headerResult, footerResult] = await Promise.all([
|
|
586
|
+
const { fonts, images, header, footer, pages, css, stylesheets, fontFamilies, ...rest } = options;
|
|
587
|
+
const [main, headerResult, footerResult, pagesResult] = await Promise.all([
|
|
544
588
|
resolveNode(node),
|
|
545
|
-
header ===
|
|
546
|
-
footer ===
|
|
589
|
+
header == null || header === false ? void 0 : resolveNode(header),
|
|
590
|
+
footer == null || footer === false ? void 0 : resolveNode(footer),
|
|
591
|
+
pages == null ? void 0 : resolveRules(pages)
|
|
547
592
|
]);
|
|
548
|
-
const bands = [
|
|
593
|
+
const bands = [
|
|
594
|
+
headerResult?.node,
|
|
595
|
+
footerResult?.node,
|
|
596
|
+
...pagesResult?.nodes ?? []
|
|
597
|
+
].filter((band) => band !== void 0);
|
|
549
598
|
const resources = await this.fonts.resolveResources(fonts && subsetFonts({
|
|
550
599
|
fonts,
|
|
551
600
|
source: [
|
|
@@ -559,12 +608,14 @@ var PdfRenderer = class {
|
|
|
559
608
|
...ownCss(css, stylesheets),
|
|
560
609
|
...main.css,
|
|
561
610
|
...headerResult?.css ?? [],
|
|
562
|
-
...footerResult?.css ?? []
|
|
611
|
+
...footerResult?.css ?? [],
|
|
612
|
+
...pagesResult?.css ?? []
|
|
563
613
|
];
|
|
564
614
|
return this.inner.render(main.node, {
|
|
565
615
|
...rest,
|
|
566
616
|
header: headerResult?.node,
|
|
567
617
|
footer: footerResult?.node,
|
|
618
|
+
pages: pagesResult?.pages,
|
|
568
619
|
css: sheets.length > 0 ? sheets : void 0,
|
|
569
620
|
images: resources.images,
|
|
570
621
|
fontFamilies: resources.fontFamilies
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takumi-pdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Render paged PDFs from JSX, HTML, and CSS. No headless browser.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chromium-free",
|
|
@@ -143,12 +143,12 @@
|
|
|
143
143
|
"publish-lint": "attw --pack . && publint --strict ."
|
|
144
144
|
},
|
|
145
145
|
"dependencies": {
|
|
146
|
-
"@takumi-rs/helpers": "2.
|
|
146
|
+
"@takumi-rs/helpers": "2.14.0"
|
|
147
147
|
},
|
|
148
148
|
"devDependencies": {
|
|
149
|
-
"@types/bun": "^1.4.
|
|
149
|
+
"@types/bun": "^1.4.1",
|
|
150
150
|
"@types/react": "19.2.18",
|
|
151
|
-
"tsdown": "0.
|
|
151
|
+
"tsdown": "0.23.0"
|
|
152
152
|
},
|
|
153
153
|
"peerDependencies": {
|
|
154
154
|
"react": "^18.0.0 || ^19.0.0"
|
|
Binary file
|