takumi-pdf 0.4.1 → 0.5.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/dist/export.cjs +32 -11
- package/dist/export.d.cts +18 -14
- package/dist/export.d.mts +18 -14
- package/dist/export.mjs +32 -11
- package/package.json +2 -2
- package/pkg/takumi_pdf_wasm_bg.wasm +0 -0
package/dist/export.cjs
CHANGED
|
@@ -2,8 +2,10 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
+
let _takumi_rs_helpers_html = require("@takumi-rs/helpers/html");
|
|
5
6
|
let _takumi_rs_helpers_jsx = require("@takumi-rs/helpers/jsx");
|
|
6
7
|
let _takumi_rs_helpers_renderer = require("@takumi-rs/helpers/renderer");
|
|
8
|
+
let _takumi_rs_helpers = require("@takumi-rs/helpers");
|
|
7
9
|
//#region pkg/takumi_pdf_wasm.js
|
|
8
10
|
/**
|
|
9
11
|
* A PDF renderer holding registered fonts and a decoded-resource cache.
|
|
@@ -496,28 +498,40 @@ async function __wbg_init(module_or_path) {
|
|
|
496
498
|
}
|
|
497
499
|
//#endregion
|
|
498
500
|
//#region src/export.ts
|
|
501
|
+
/** Every character a page counter can produce, so subsetting keeps the fonts a band needs. */
|
|
502
|
+
const COUNTER_DIGITS = "0123456789";
|
|
499
503
|
function isNode(value) {
|
|
500
504
|
return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
|
|
501
505
|
}
|
|
502
506
|
async function resolveNode(input) {
|
|
503
|
-
|
|
507
|
+
if (isNode(input)) return {
|
|
504
508
|
node: input,
|
|
505
509
|
stylesheets: []
|
|
506
|
-
}
|
|
510
|
+
};
|
|
511
|
+
if (typeof input === "string") return (0, _takumi_rs_helpers_html.fromHtml)(input);
|
|
512
|
+
return (0, _takumi_rs_helpers_jsx.fromJsx)(input);
|
|
507
513
|
}
|
|
508
514
|
/** A PDF renderer holding registered fonts. Reuse one instance across renders. */
|
|
509
515
|
var PdfRenderer = class {
|
|
510
516
|
inner = new PdfRenderer$1();
|
|
511
517
|
fonts = new _takumi_rs_helpers_renderer.FontRegistry((font) => this.inner.registerFont(font));
|
|
512
|
-
/** Renders a node tree or
|
|
518
|
+
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
513
519
|
async render(node, options = {}) {
|
|
514
520
|
const { fonts, images, header, footer, stylesheets, fontFamilies, ...rest } = options;
|
|
515
|
-
const [main, headerResult, footerResult
|
|
521
|
+
const [main, headerResult, footerResult] = await Promise.all([
|
|
516
522
|
resolveNode(node),
|
|
517
523
|
header === void 0 ? void 0 : resolveNode(header),
|
|
518
|
-
footer === void 0 ? void 0 : resolveNode(footer)
|
|
519
|
-
this.fonts.resolveResources(fonts, images, fontFamilies)
|
|
524
|
+
footer === void 0 ? void 0 : resolveNode(footer)
|
|
520
525
|
]);
|
|
526
|
+
const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
|
|
527
|
+
const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
|
|
528
|
+
fonts,
|
|
529
|
+
source: bands.length > 0 ? [
|
|
530
|
+
main.node,
|
|
531
|
+
...bands,
|
|
532
|
+
COUNTER_DIGITS
|
|
533
|
+
] : main.node
|
|
534
|
+
}), images, fontFamilies);
|
|
521
535
|
const sheets = [
|
|
522
536
|
...stylesheets ?? [],
|
|
523
537
|
...main.stylesheets,
|
|
@@ -536,14 +550,21 @@ var PdfRenderer = class {
|
|
|
536
550
|
/**
|
|
537
551
|
* Lays out a node tree without rendering and returns its size in CSS px.
|
|
538
552
|
*
|
|
539
|
-
* With page options the tree lays out
|
|
540
|
-
* height, exactly how {@link render} measures a header or footer
|
|
541
|
-
* (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
542
|
-
* so the height tells you how much margin a band needs.
|
|
553
|
+
* With page options the tree lays out against the full page width with
|
|
554
|
+
* unbounded height, exactly how {@link render} measures a header or footer
|
|
555
|
+
* band (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
556
|
+
* counters), so the height tells you how much margin a band needs.
|
|
557
|
+
*
|
|
558
|
+
* The returned size is the tree's own, not the space it was laid out
|
|
559
|
+
* against: a box with `width: 100px` measures 100 wide on any page.
|
|
543
560
|
*/
|
|
544
561
|
async measure(node, options = {}) {
|
|
545
562
|
const { fonts, images, stylesheets, fontFamilies, ...rest } = options;
|
|
546
|
-
const
|
|
563
|
+
const main = await resolveNode(node);
|
|
564
|
+
const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
|
|
565
|
+
fonts,
|
|
566
|
+
source: [main.node, COUNTER_DIGITS]
|
|
567
|
+
}), images, fontFamilies);
|
|
547
568
|
const sheets = [...stylesheets ?? [], ...main.stylesheets];
|
|
548
569
|
return this.inner.measure(main.node, {
|
|
549
570
|
...rest,
|
package/dist/export.d.cts
CHANGED
|
@@ -46,8 +46,8 @@ declare module "react" {
|
|
|
46
46
|
tw?: string;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
/** A document input: a takumi node tree or
|
|
50
|
-
type NodeInput = Node | ReactNode | ReactElementLike;
|
|
49
|
+
/** A document input: a takumi node tree, JSX, or an HTML string. */
|
|
50
|
+
type NodeInput = Node | ReactNode | ReactElementLike | string;
|
|
51
51
|
/** Explicit dimensions in CSS px (96 dpi). */
|
|
52
52
|
type Dimensions = {
|
|
53
53
|
width: number;
|
|
@@ -211,14 +211,15 @@ type ArchivalAttachment = Attachment & {
|
|
|
211
211
|
};
|
|
212
212
|
/**
|
|
213
213
|
* Standards conformance. Invalid combinations are type errors: the `a` levels
|
|
214
|
-
* imply a structure tree so `tagged: false` is rejected, PDF/
|
|
215
|
-
*
|
|
216
|
-
* PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
|
|
214
|
+
* imply a structure tree so `tagged: false` is rejected, PDF/UA-1 is PDF
|
|
215
|
+
* 1.7-only and PDF/UA-2 is PDF 2.0-only so each pairs with its own PDF/A
|
|
216
|
+
* levels, and only the PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
|
|
217
|
+
* attachments.
|
|
217
218
|
*/
|
|
218
219
|
type ConformanceOptions = {
|
|
219
220
|
pdfa?: never;
|
|
220
|
-
/** Structure tree: off, on (default), or validated against PDF/UA
|
|
221
|
-
tagged?: boolean | "ua1";
|
|
221
|
+
/** Structure tree: off, on (default), or validated against PDF/UA. */
|
|
222
|
+
tagged?: boolean | "ua1" | "ua2";
|
|
222
223
|
/** Files attached to the document. */
|
|
223
224
|
attachments?: Attachment[];
|
|
224
225
|
} | {
|
|
@@ -240,11 +241,11 @@ type ConformanceOptions = {
|
|
|
240
241
|
attachments?: ArchivalAttachment[];
|
|
241
242
|
} | {
|
|
242
243
|
pdfa: "4";
|
|
243
|
-
tagged?: boolean;
|
|
244
|
+
tagged?: boolean | "ua2";
|
|
244
245
|
attachments?: never;
|
|
245
246
|
} | {
|
|
246
247
|
pdfa: "4f";
|
|
247
|
-
tagged?: boolean;
|
|
248
|
+
tagged?: boolean | "ua2";
|
|
248
249
|
attachments?: ArchivalAttachment[];
|
|
249
250
|
};
|
|
250
251
|
type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
@@ -270,15 +271,18 @@ type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
|
270
271
|
declare class PdfRenderer {
|
|
271
272
|
private inner;
|
|
272
273
|
private fonts;
|
|
273
|
-
/** Renders a node tree or
|
|
274
|
+
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
274
275
|
render(node: NodeInput, options?: RenderOptions): Promise<Uint8Array>;
|
|
275
276
|
/**
|
|
276
277
|
* Lays out a node tree without rendering and returns its size in CSS px.
|
|
277
278
|
*
|
|
278
|
-
* With page options the tree lays out
|
|
279
|
-
* height, exactly how {@link render} measures a header or footer
|
|
280
|
-
* (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
281
|
-
* so the height tells you how much margin a band needs.
|
|
279
|
+
* With page options the tree lays out against the full page width with
|
|
280
|
+
* unbounded height, exactly how {@link render} measures a header or footer
|
|
281
|
+
* band (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
282
|
+
* counters), so the height tells you how much margin a band needs.
|
|
283
|
+
*
|
|
284
|
+
* The returned size is the tree's own, not the space it was laid out
|
|
285
|
+
* against: a box with `width: 100px` measures 100 wide on any page.
|
|
282
286
|
*/
|
|
283
287
|
measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
|
|
284
288
|
/** Registers a font ahead of time, deduped against earlier registrations. */
|
package/dist/export.d.mts
CHANGED
|
@@ -46,8 +46,8 @@ declare module "react" {
|
|
|
46
46
|
tw?: string;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
/** A document input: a takumi node tree or
|
|
50
|
-
type NodeInput = Node | ReactNode | ReactElementLike;
|
|
49
|
+
/** A document input: a takumi node tree, JSX, or an HTML string. */
|
|
50
|
+
type NodeInput = Node | ReactNode | ReactElementLike | string;
|
|
51
51
|
/** Explicit dimensions in CSS px (96 dpi). */
|
|
52
52
|
type Dimensions = {
|
|
53
53
|
width: number;
|
|
@@ -211,14 +211,15 @@ type ArchivalAttachment = Attachment & {
|
|
|
211
211
|
};
|
|
212
212
|
/**
|
|
213
213
|
* Standards conformance. Invalid combinations are type errors: the `a` levels
|
|
214
|
-
* imply a structure tree so `tagged: false` is rejected, PDF/
|
|
215
|
-
*
|
|
216
|
-
* PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
|
|
214
|
+
* imply a structure tree so `tagged: false` is rejected, PDF/UA-1 is PDF
|
|
215
|
+
* 1.7-only and PDF/UA-2 is PDF 2.0-only so each pairs with its own PDF/A
|
|
216
|
+
* levels, and only the PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
|
|
217
|
+
* attachments.
|
|
217
218
|
*/
|
|
218
219
|
type ConformanceOptions = {
|
|
219
220
|
pdfa?: never;
|
|
220
|
-
/** Structure tree: off, on (default), or validated against PDF/UA
|
|
221
|
-
tagged?: boolean | "ua1";
|
|
221
|
+
/** Structure tree: off, on (default), or validated against PDF/UA. */
|
|
222
|
+
tagged?: boolean | "ua1" | "ua2";
|
|
222
223
|
/** Files attached to the document. */
|
|
223
224
|
attachments?: Attachment[];
|
|
224
225
|
} | {
|
|
@@ -240,11 +241,11 @@ type ConformanceOptions = {
|
|
|
240
241
|
attachments?: ArchivalAttachment[];
|
|
241
242
|
} | {
|
|
242
243
|
pdfa: "4";
|
|
243
|
-
tagged?: boolean;
|
|
244
|
+
tagged?: boolean | "ua2";
|
|
244
245
|
attachments?: never;
|
|
245
246
|
} | {
|
|
246
247
|
pdfa: "4f";
|
|
247
|
-
tagged?: boolean;
|
|
248
|
+
tagged?: boolean | "ua2";
|
|
248
249
|
attachments?: ArchivalAttachment[];
|
|
249
250
|
};
|
|
250
251
|
type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
@@ -270,15 +271,18 @@ type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
|
|
|
270
271
|
declare class PdfRenderer {
|
|
271
272
|
private inner;
|
|
272
273
|
private fonts;
|
|
273
|
-
/** Renders a node tree or
|
|
274
|
+
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
274
275
|
render(node: NodeInput, options?: RenderOptions): Promise<Uint8Array>;
|
|
275
276
|
/**
|
|
276
277
|
* Lays out a node tree without rendering and returns its size in CSS px.
|
|
277
278
|
*
|
|
278
|
-
* With page options the tree lays out
|
|
279
|
-
* height, exactly how {@link render} measures a header or footer
|
|
280
|
-
* (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
281
|
-
* so the height tells you how much margin a band needs.
|
|
279
|
+
* With page options the tree lays out against the full page width with
|
|
280
|
+
* unbounded height, exactly how {@link render} measures a header or footer
|
|
281
|
+
* band (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
282
|
+
* counters), so the height tells you how much margin a band needs.
|
|
283
|
+
*
|
|
284
|
+
* The returned size is the tree's own, not the space it was laid out
|
|
285
|
+
* against: a box with `width: 100px` measures 100 wide on any page.
|
|
282
286
|
*/
|
|
283
287
|
measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
|
|
284
288
|
/** Registers a font ahead of time, deduped against earlier registrations. */
|
package/dist/export.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { fromHtml } from "@takumi-rs/helpers/html";
|
|
1
2
|
import { fromJsx } from "@takumi-rs/helpers/jsx";
|
|
2
3
|
import { FontRegistry } from "@takumi-rs/helpers/renderer";
|
|
4
|
+
import { subsetFonts } from "@takumi-rs/helpers";
|
|
3
5
|
//#region pkg/takumi_pdf_wasm.js
|
|
4
6
|
/**
|
|
5
7
|
* A PDF renderer holding registered fonts and a decoded-resource cache.
|
|
@@ -492,28 +494,40 @@ async function __wbg_init(module_or_path) {
|
|
|
492
494
|
}
|
|
493
495
|
//#endregion
|
|
494
496
|
//#region src/export.ts
|
|
497
|
+
/** Every character a page counter can produce, so subsetting keeps the fonts a band needs. */
|
|
498
|
+
const COUNTER_DIGITS = "0123456789";
|
|
495
499
|
function isNode(value) {
|
|
496
500
|
return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
|
|
497
501
|
}
|
|
498
502
|
async function resolveNode(input) {
|
|
499
|
-
|
|
503
|
+
if (isNode(input)) return {
|
|
500
504
|
node: input,
|
|
501
505
|
stylesheets: []
|
|
502
|
-
}
|
|
506
|
+
};
|
|
507
|
+
if (typeof input === "string") return fromHtml(input);
|
|
508
|
+
return fromJsx(input);
|
|
503
509
|
}
|
|
504
510
|
/** A PDF renderer holding registered fonts. Reuse one instance across renders. */
|
|
505
511
|
var PdfRenderer = class {
|
|
506
512
|
inner = new PdfRenderer$1();
|
|
507
513
|
fonts = new FontRegistry((font) => this.inner.registerFont(font));
|
|
508
|
-
/** Renders a node tree or
|
|
514
|
+
/** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
|
|
509
515
|
async render(node, options = {}) {
|
|
510
516
|
const { fonts, images, header, footer, stylesheets, fontFamilies, ...rest } = options;
|
|
511
|
-
const [main, headerResult, footerResult
|
|
517
|
+
const [main, headerResult, footerResult] = await Promise.all([
|
|
512
518
|
resolveNode(node),
|
|
513
519
|
header === void 0 ? void 0 : resolveNode(header),
|
|
514
|
-
footer === void 0 ? void 0 : resolveNode(footer)
|
|
515
|
-
this.fonts.resolveResources(fonts, images, fontFamilies)
|
|
520
|
+
footer === void 0 ? void 0 : resolveNode(footer)
|
|
516
521
|
]);
|
|
522
|
+
const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
|
|
523
|
+
const resources = await this.fonts.resolveResources(fonts && subsetFonts({
|
|
524
|
+
fonts,
|
|
525
|
+
source: bands.length > 0 ? [
|
|
526
|
+
main.node,
|
|
527
|
+
...bands,
|
|
528
|
+
COUNTER_DIGITS
|
|
529
|
+
] : main.node
|
|
530
|
+
}), images, fontFamilies);
|
|
517
531
|
const sheets = [
|
|
518
532
|
...stylesheets ?? [],
|
|
519
533
|
...main.stylesheets,
|
|
@@ -532,14 +546,21 @@ var PdfRenderer = class {
|
|
|
532
546
|
/**
|
|
533
547
|
* Lays out a node tree without rendering and returns its size in CSS px.
|
|
534
548
|
*
|
|
535
|
-
* With page options the tree lays out
|
|
536
|
-
* height, exactly how {@link render} measures a header or footer
|
|
537
|
-
* (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
538
|
-
* so the height tells you how much margin a band needs.
|
|
549
|
+
* With page options the tree lays out against the full page width with
|
|
550
|
+
* unbounded height, exactly how {@link render} measures a header or footer
|
|
551
|
+
* band (`pageNumber` / `totalPages` hooks are filled with three-digit
|
|
552
|
+
* counters), so the height tells you how much margin a band needs.
|
|
553
|
+
*
|
|
554
|
+
* The returned size is the tree's own, not the space it was laid out
|
|
555
|
+
* against: a box with `width: 100px` measures 100 wide on any page.
|
|
539
556
|
*/
|
|
540
557
|
async measure(node, options = {}) {
|
|
541
558
|
const { fonts, images, stylesheets, fontFamilies, ...rest } = options;
|
|
542
|
-
const
|
|
559
|
+
const main = await resolveNode(node);
|
|
560
|
+
const resources = await this.fonts.resolveResources(fonts && subsetFonts({
|
|
561
|
+
fonts,
|
|
562
|
+
source: [main.node, COUNTER_DIGITS]
|
|
563
|
+
}), images, fontFamilies);
|
|
543
564
|
const sheets = [...stylesheets ?? [], ...main.stylesheets];
|
|
544
565
|
return this.inner.measure(main.node, {
|
|
545
566
|
...rest,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takumi-pdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "HTML/JSX to paged, selectable-text PDF, powered by takumi. WebAssembly, no Chromium.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"css",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"publish-lint": "attw --pack . && publint --strict ."
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@takumi-rs/helpers": "2.
|
|
86
|
+
"@takumi-rs/helpers": "2.6.0"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
89
|
"@types/bun": "^1.3.14",
|
|
Binary file
|