takumi-pdf 0.5.0 → 0.6.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 +6 -6
- package/dist/export.cjs +49 -6
- package/dist/export.d.cts +1 -0
- package/dist/export.d.mts +1 -0
- package/dist/export.mjs +49 -6
- package/package.json +9 -4
- package/pkg/takumi_pdf_wasm_bg.wasm +0 -0
- package/pkg/takumi_pdf_wasm_bg.wasm.d.ts +1 -0
package/README.md
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
# takumi-pdf
|
|
5
5
|
|
|
6
|
-
**Render
|
|
6
|
+
**Render paged PDFs from JSX, HTML, and CSS. No headless browser.**
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Build invoices and reports with CSS or Tailwind. The renderer writes vector PDF with selectable text.
|
|
9
9
|
|
|
10
10
|
[Documentation](https://takumi.kane.tw/docs/) · [Playground](https://takumi.kane.tw/playground)
|
|
11
11
|
|
|
@@ -13,9 +13,9 @@ Invoices, reports, and receipts from the Takumi renderer, with CSS layout and ve
|
|
|
13
13
|
|
|
14
14
|
## Why
|
|
15
15
|
|
|
16
|
-
Browser-based PDF generation
|
|
16
|
+
Browser-based PDF generation starts a browser process and ships a Chrome installation. `takumi-pdf` compiles Takumi's layout and PDF code to WebAssembly.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Pass JSX 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
|
|
|
@@ -168,7 +168,7 @@ const pdf = await render(
|
|
|
168
168
|
|
|
169
169
|
## Links, outline, and metadata
|
|
170
170
|
|
|
171
|
-
Anchors with an `href` become clickable link annotations. `outline: true` builds PDF bookmarks from `h1
|
|
171
|
+
Anchors with an `href` become clickable link annotations. `outline: true` builds PDF bookmarks from `h1` through `h6` headings. `metadata` fills the document properties:
|
|
172
172
|
|
|
173
173
|
```tsx
|
|
174
174
|
const pdf = await render(report, {
|
|
@@ -186,7 +186,7 @@ Omit `metadata` to keep output byte-identical across runs.
|
|
|
186
186
|
|
|
187
187
|
## Tagged output and PDF/A
|
|
188
188
|
|
|
189
|
-
Output is **tagged by default**: HTML semantics (`h1
|
|
189
|
+
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.
|
|
190
190
|
|
|
191
191
|
`<table>` markup is not supported, and a table built out of flex rows carries no `Table` structure elements.
|
|
192
192
|
|
package/dist/export.cjs
CHANGED
|
@@ -104,6 +104,32 @@ var PdfRenderer$1 = class {
|
|
|
104
104
|
}
|
|
105
105
|
};
|
|
106
106
|
if (Symbol.dispose) PdfRenderer$1.prototype[Symbol.dispose] = PdfRenderer$1.prototype.free;
|
|
107
|
+
/**
|
|
108
|
+
* The characters the page counters named by these class names can produce.
|
|
109
|
+
*
|
|
110
|
+
* A counter's characters appear nowhere in the document, so a caller choosing
|
|
111
|
+
* which faces to load has no other way to learn it needs, say, Thai digits.
|
|
112
|
+
* @param {string[]} classes
|
|
113
|
+
* @returns {string}
|
|
114
|
+
*/
|
|
115
|
+
function counterCharacters(classes) {
|
|
116
|
+
let deferred2_0;
|
|
117
|
+
let deferred2_1;
|
|
118
|
+
try {
|
|
119
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
120
|
+
const ptr0 = passArrayJsValueToWasm0(classes, wasm.__wbindgen_export);
|
|
121
|
+
const len0 = WASM_VECTOR_LEN;
|
|
122
|
+
wasm.counterCharacters(retptr, ptr0, len0);
|
|
123
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 0, true);
|
|
124
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4, true);
|
|
125
|
+
deferred2_0 = r0;
|
|
126
|
+
deferred2_1 = r1;
|
|
127
|
+
return getStringFromWasm0(r0, r1);
|
|
128
|
+
} finally {
|
|
129
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
130
|
+
wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
107
133
|
function __wbg_get_imports() {
|
|
108
134
|
return {
|
|
109
135
|
__proto__: null,
|
|
@@ -383,6 +409,13 @@ let heap_next = heap.length;
|
|
|
383
409
|
function isLikeNone(x) {
|
|
384
410
|
return x === void 0 || x === null;
|
|
385
411
|
}
|
|
412
|
+
function passArrayJsValueToWasm0(array, malloc) {
|
|
413
|
+
const ptr = malloc(array.length * 4, 4) >>> 0;
|
|
414
|
+
const mem = getDataViewMemory0();
|
|
415
|
+
for (let i = 0; i < array.length; i++) mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
|
|
416
|
+
WASM_VECTOR_LEN = array.length;
|
|
417
|
+
return ptr;
|
|
418
|
+
}
|
|
386
419
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
387
420
|
if (realloc === void 0) {
|
|
388
421
|
const buf = cachedTextEncoder.encode(arg);
|
|
@@ -498,8 +531,18 @@ async function __wbg_init(module_or_path) {
|
|
|
498
531
|
}
|
|
499
532
|
//#endregion
|
|
500
533
|
//#region src/export.ts
|
|
501
|
-
/** Every
|
|
502
|
-
|
|
534
|
+
/** Every class name in a tree, so the renderer can say what its counters draw. */
|
|
535
|
+
function classNames(node) {
|
|
536
|
+
const into = [];
|
|
537
|
+
collectClassNames(node, into);
|
|
538
|
+
return into;
|
|
539
|
+
}
|
|
540
|
+
function collectClassNames(node, into) {
|
|
541
|
+
if (typeof node !== "object" || node === null) return;
|
|
542
|
+
const { className, children } = node;
|
|
543
|
+
if (typeof className === "string") into.push(...className.split(/\s+/).filter(Boolean));
|
|
544
|
+
if (Array.isArray(children)) for (const child of children) collectClassNames(child, into);
|
|
545
|
+
}
|
|
503
546
|
function isNode(value) {
|
|
504
547
|
return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
|
|
505
548
|
}
|
|
@@ -526,11 +569,11 @@ var PdfRenderer = class {
|
|
|
526
569
|
const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
|
|
527
570
|
const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
|
|
528
571
|
fonts,
|
|
529
|
-
source:
|
|
572
|
+
source: [
|
|
530
573
|
main.node,
|
|
531
574
|
...bands,
|
|
532
|
-
|
|
533
|
-
]
|
|
575
|
+
counterCharacters([main.node, ...bands].flatMap((tree) => classNames(tree)))
|
|
576
|
+
]
|
|
534
577
|
}), images, fontFamilies);
|
|
535
578
|
const sheets = [
|
|
536
579
|
...stylesheets ?? [],
|
|
@@ -563,7 +606,7 @@ var PdfRenderer = class {
|
|
|
563
606
|
const main = await resolveNode(node);
|
|
564
607
|
const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
|
|
565
608
|
fonts,
|
|
566
|
-
source: [main.node,
|
|
609
|
+
source: [main.node, counterCharacters(classNames(main.node))]
|
|
567
610
|
}), images, fontFamilies);
|
|
568
611
|
const sheets = [...stylesheets ?? [], ...main.stylesheets];
|
|
569
612
|
return this.inner.measure(main.node, {
|
package/dist/export.d.cts
CHANGED
|
@@ -6,6 +6,7 @@ type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Modul
|
|
|
6
6
|
interface InitOutput {
|
|
7
7
|
readonly memory: WebAssembly.Memory;
|
|
8
8
|
readonly __wbg_pdfrenderer_free: (a: number, b: number) => void;
|
|
9
|
+
readonly counterCharacters: (a: number, b: number, c: number) => void;
|
|
9
10
|
readonly pdfrenderer_measure: (a: number, b: number, c: number, d: number) => void;
|
|
10
11
|
readonly pdfrenderer_new: (a: number) => void;
|
|
11
12
|
readonly pdfrenderer_registerFont: (a: number, b: number, c: number) => void;
|
package/dist/export.d.mts
CHANGED
|
@@ -6,6 +6,7 @@ type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Modul
|
|
|
6
6
|
interface InitOutput {
|
|
7
7
|
readonly memory: WebAssembly.Memory;
|
|
8
8
|
readonly __wbg_pdfrenderer_free: (a: number, b: number) => void;
|
|
9
|
+
readonly counterCharacters: (a: number, b: number, c: number) => void;
|
|
9
10
|
readonly pdfrenderer_measure: (a: number, b: number, c: number, d: number) => void;
|
|
10
11
|
readonly pdfrenderer_new: (a: number) => void;
|
|
11
12
|
readonly pdfrenderer_registerFont: (a: number, b: number, c: number) => void;
|
package/dist/export.mjs
CHANGED
|
@@ -100,6 +100,32 @@ var PdfRenderer$1 = class {
|
|
|
100
100
|
}
|
|
101
101
|
};
|
|
102
102
|
if (Symbol.dispose) PdfRenderer$1.prototype[Symbol.dispose] = PdfRenderer$1.prototype.free;
|
|
103
|
+
/**
|
|
104
|
+
* The characters the page counters named by these class names can produce.
|
|
105
|
+
*
|
|
106
|
+
* A counter's characters appear nowhere in the document, so a caller choosing
|
|
107
|
+
* which faces to load has no other way to learn it needs, say, Thai digits.
|
|
108
|
+
* @param {string[]} classes
|
|
109
|
+
* @returns {string}
|
|
110
|
+
*/
|
|
111
|
+
function counterCharacters(classes) {
|
|
112
|
+
let deferred2_0;
|
|
113
|
+
let deferred2_1;
|
|
114
|
+
try {
|
|
115
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
116
|
+
const ptr0 = passArrayJsValueToWasm0(classes, wasm.__wbindgen_export);
|
|
117
|
+
const len0 = WASM_VECTOR_LEN;
|
|
118
|
+
wasm.counterCharacters(retptr, ptr0, len0);
|
|
119
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 0, true);
|
|
120
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4, true);
|
|
121
|
+
deferred2_0 = r0;
|
|
122
|
+
deferred2_1 = r1;
|
|
123
|
+
return getStringFromWasm0(r0, r1);
|
|
124
|
+
} finally {
|
|
125
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
126
|
+
wasm.__wbindgen_export4(deferred2_0, deferred2_1, 1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
103
129
|
function __wbg_get_imports() {
|
|
104
130
|
return {
|
|
105
131
|
__proto__: null,
|
|
@@ -379,6 +405,13 @@ let heap_next = heap.length;
|
|
|
379
405
|
function isLikeNone(x) {
|
|
380
406
|
return x === void 0 || x === null;
|
|
381
407
|
}
|
|
408
|
+
function passArrayJsValueToWasm0(array, malloc) {
|
|
409
|
+
const ptr = malloc(array.length * 4, 4) >>> 0;
|
|
410
|
+
const mem = getDataViewMemory0();
|
|
411
|
+
for (let i = 0; i < array.length; i++) mem.setUint32(ptr + 4 * i, addHeapObject(array[i]), true);
|
|
412
|
+
WASM_VECTOR_LEN = array.length;
|
|
413
|
+
return ptr;
|
|
414
|
+
}
|
|
382
415
|
function passStringToWasm0(arg, malloc, realloc) {
|
|
383
416
|
if (realloc === void 0) {
|
|
384
417
|
const buf = cachedTextEncoder.encode(arg);
|
|
@@ -494,8 +527,18 @@ async function __wbg_init(module_or_path) {
|
|
|
494
527
|
}
|
|
495
528
|
//#endregion
|
|
496
529
|
//#region src/export.ts
|
|
497
|
-
/** Every
|
|
498
|
-
|
|
530
|
+
/** Every class name in a tree, so the renderer can say what its counters draw. */
|
|
531
|
+
function classNames(node) {
|
|
532
|
+
const into = [];
|
|
533
|
+
collectClassNames(node, into);
|
|
534
|
+
return into;
|
|
535
|
+
}
|
|
536
|
+
function collectClassNames(node, into) {
|
|
537
|
+
if (typeof node !== "object" || node === null) return;
|
|
538
|
+
const { className, children } = node;
|
|
539
|
+
if (typeof className === "string") into.push(...className.split(/\s+/).filter(Boolean));
|
|
540
|
+
if (Array.isArray(children)) for (const child of children) collectClassNames(child, into);
|
|
541
|
+
}
|
|
499
542
|
function isNode(value) {
|
|
500
543
|
return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
|
|
501
544
|
}
|
|
@@ -522,11 +565,11 @@ var PdfRenderer = class {
|
|
|
522
565
|
const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
|
|
523
566
|
const resources = await this.fonts.resolveResources(fonts && subsetFonts({
|
|
524
567
|
fonts,
|
|
525
|
-
source:
|
|
568
|
+
source: [
|
|
526
569
|
main.node,
|
|
527
570
|
...bands,
|
|
528
|
-
|
|
529
|
-
]
|
|
571
|
+
counterCharacters([main.node, ...bands].flatMap((tree) => classNames(tree)))
|
|
572
|
+
]
|
|
530
573
|
}), images, fontFamilies);
|
|
531
574
|
const sheets = [
|
|
532
575
|
...stylesheets ?? [],
|
|
@@ -559,7 +602,7 @@ var PdfRenderer = class {
|
|
|
559
602
|
const main = await resolveNode(node);
|
|
560
603
|
const resources = await this.fonts.resolveResources(fonts && subsetFonts({
|
|
561
604
|
fonts,
|
|
562
|
-
source: [main.node,
|
|
605
|
+
source: [main.node, counterCharacters(classNames(main.node))]
|
|
563
606
|
}), images, fontFamilies);
|
|
564
607
|
const sheets = [...stylesheets ?? [], ...main.stylesheets];
|
|
565
608
|
return this.inner.measure(main.node, {
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takumi-pdf",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "Render paged PDFs from JSX, HTML, and CSS. No headless browser.",
|
|
5
5
|
"keywords": [
|
|
6
|
+
"chromium-free",
|
|
7
|
+
"cjk",
|
|
6
8
|
"css",
|
|
9
|
+
"html-to-pdf",
|
|
7
10
|
"invoice",
|
|
8
11
|
"jsx",
|
|
9
12
|
"pdf",
|
|
13
|
+
"pdf-generation",
|
|
10
14
|
"react",
|
|
11
|
-
"
|
|
15
|
+
"receipt",
|
|
16
|
+
"tailwind",
|
|
12
17
|
"webassembly"
|
|
13
18
|
],
|
|
14
19
|
"homepage": "https://takumi.kane.tw/docs/",
|
|
@@ -83,7 +88,7 @@
|
|
|
83
88
|
"publish-lint": "attw --pack . && publint --strict ."
|
|
84
89
|
},
|
|
85
90
|
"dependencies": {
|
|
86
|
-
"@takumi-rs/helpers": "2.6.
|
|
91
|
+
"@takumi-rs/helpers": "2.6.1"
|
|
87
92
|
},
|
|
88
93
|
"devDependencies": {
|
|
89
94
|
"@types/bun": "^1.3.14",
|
|
Binary file
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
export const memory: WebAssembly.Memory;
|
|
4
4
|
export const __wbg_pdfrenderer_free: (a: number, b: number) => void;
|
|
5
|
+
export const counterCharacters: (a: number, b: number, c: number) => void;
|
|
5
6
|
export const pdfrenderer_measure: (a: number, b: number, c: number, d: number) => void;
|
|
6
7
|
export const pdfrenderer_new: (a: number) => void;
|
|
7
8
|
export const pdfrenderer_registerFont: (a: number, b: number, c: number) => void;
|