takumi-pdf 0.4.2 → 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 CHANGED
@@ -3,9 +3,9 @@
3
3
 
4
4
  # takumi-pdf
5
5
 
6
- **Render JSX to paged, selectable-text PDF. WebAssembly, no Chromium.**
6
+ **Render paged PDFs from JSX, HTML, and CSS. No headless browser.**
7
7
 
8
- Invoices, reports, and receipts from the Takumi renderer, with CSS layout and vector PDF output.
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 brings the Chromium serverless tax: browser cold starts, browser memory, a large browser binary, and headless-browser work before a document can render. It is a capable screenshot pipeline, but it is still a browser.
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
- `takumi-pdf` uses Takumi's own layout and PDF rendering primitives, compiled to WebAssembly. There is no browser process. Render JSX or a Takumi node tree with CSS and Tailwind classes, then receive vector PDF bytes with selectable, searchable text and embedded subset fonts.
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`–`h6` headings. `metadata` fills the document properties:
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`–`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.
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
@@ -5,6 +5,7 @@ Object.defineProperties(exports, {
5
5
  let _takumi_rs_helpers_html = require("@takumi-rs/helpers/html");
6
6
  let _takumi_rs_helpers_jsx = require("@takumi-rs/helpers/jsx");
7
7
  let _takumi_rs_helpers_renderer = require("@takumi-rs/helpers/renderer");
8
+ let _takumi_rs_helpers = require("@takumi-rs/helpers");
8
9
  //#region pkg/takumi_pdf_wasm.js
9
10
  /**
10
11
  * A PDF renderer holding registered fonts and a decoded-resource cache.
@@ -103,6 +104,32 @@ var PdfRenderer$1 = class {
103
104
  }
104
105
  };
105
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
+ }
106
133
  function __wbg_get_imports() {
107
134
  return {
108
135
  __proto__: null,
@@ -382,6 +409,13 @@ let heap_next = heap.length;
382
409
  function isLikeNone(x) {
383
410
  return x === void 0 || x === null;
384
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
+ }
385
419
  function passStringToWasm0(arg, malloc, realloc) {
386
420
  if (realloc === void 0) {
387
421
  const buf = cachedTextEncoder.encode(arg);
@@ -497,6 +531,18 @@ async function __wbg_init(module_or_path) {
497
531
  }
498
532
  //#endregion
499
533
  //#region src/export.ts
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
+ }
500
546
  function isNode(value) {
501
547
  return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
502
548
  }
@@ -515,12 +561,20 @@ var PdfRenderer = class {
515
561
  /** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
516
562
  async render(node, options = {}) {
517
563
  const { fonts, images, header, footer, stylesheets, fontFamilies, ...rest } = options;
518
- const [main, headerResult, footerResult, resources] = await Promise.all([
564
+ const [main, headerResult, footerResult] = await Promise.all([
519
565
  resolveNode(node),
520
566
  header === void 0 ? void 0 : resolveNode(header),
521
- footer === void 0 ? void 0 : resolveNode(footer),
522
- this.fonts.resolveResources(fonts, images, fontFamilies)
567
+ footer === void 0 ? void 0 : resolveNode(footer)
523
568
  ]);
569
+ const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
570
+ const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
571
+ fonts,
572
+ source: [
573
+ main.node,
574
+ ...bands,
575
+ counterCharacters([main.node, ...bands].flatMap((tree) => classNames(tree)))
576
+ ]
577
+ }), images, fontFamilies);
524
578
  const sheets = [
525
579
  ...stylesheets ?? [],
526
580
  ...main.stylesheets,
@@ -539,14 +593,21 @@ var PdfRenderer = class {
539
593
  /**
540
594
  * Lays out a node tree without rendering and returns its size in CSS px.
541
595
  *
542
- * With page options the tree lays out at the full page width with unbounded
543
- * height, exactly how {@link render} measures a header or footer band
544
- * (`pageNumber` / `totalPages` hooks are filled with three-digit counters),
545
- * so the height tells you how much margin a band needs.
596
+ * With page options the tree lays out against the full page width with
597
+ * unbounded height, exactly how {@link render} measures a header or footer
598
+ * band (`pageNumber` / `totalPages` hooks are filled with three-digit
599
+ * counters), so the height tells you how much margin a band needs.
600
+ *
601
+ * The returned size is the tree's own, not the space it was laid out
602
+ * against: a box with `width: 100px` measures 100 wide on any page.
546
603
  */
547
604
  async measure(node, options = {}) {
548
605
  const { fonts, images, stylesheets, fontFamilies, ...rest } = options;
549
- const [main, resources] = await Promise.all([resolveNode(node), this.fonts.resolveResources(fonts, images, fontFamilies)]);
606
+ const main = await resolveNode(node);
607
+ const resources = await this.fonts.resolveResources(fonts && (0, _takumi_rs_helpers.subsetFonts)({
608
+ fonts,
609
+ source: [main.node, counterCharacters(classNames(main.node))]
610
+ }), images, fontFamilies);
550
611
  const sheets = [...stylesheets ?? [], ...main.stylesheets];
551
612
  return this.inner.measure(main.node, {
552
613
  ...rest,
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;
@@ -211,14 +212,15 @@ type ArchivalAttachment = Attachment & {
211
212
  };
212
213
  /**
213
214
  * Standards conformance. Invalid combinations are type errors: the `a` levels
214
- * imply a structure tree so `tagged: false` is rejected, PDF/A-4 is PDF 2.0
215
- * while PDF/UA-1 is PDF 1.7-only so they cannot combine, and only the
216
- * PDF/A-3 levels, PDF/A-4f (or plain PDF) accept attachments.
215
+ * imply a structure tree so `tagged: false` is rejected, PDF/UA-1 is PDF
216
+ * 1.7-only and PDF/UA-2 is PDF 2.0-only so each pairs with its own PDF/A
217
+ * levels, and only the PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
218
+ * attachments.
217
219
  */
218
220
  type ConformanceOptions = {
219
221
  pdfa?: never;
220
- /** Structure tree: off, on (default), or validated against PDF/UA-1. */
221
- tagged?: boolean | "ua1";
222
+ /** Structure tree: off, on (default), or validated against PDF/UA. */
223
+ tagged?: boolean | "ua1" | "ua2";
222
224
  /** Files attached to the document. */
223
225
  attachments?: Attachment[];
224
226
  } | {
@@ -240,11 +242,11 @@ type ConformanceOptions = {
240
242
  attachments?: ArchivalAttachment[];
241
243
  } | {
242
244
  pdfa: "4";
243
- tagged?: boolean;
245
+ tagged?: boolean | "ua2";
244
246
  attachments?: never;
245
247
  } | {
246
248
  pdfa: "4f";
247
- tagged?: boolean;
249
+ tagged?: boolean | "ua2";
248
250
  attachments?: ArchivalAttachment[];
249
251
  };
250
252
  type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
@@ -275,10 +277,13 @@ declare class PdfRenderer {
275
277
  /**
276
278
  * Lays out a node tree without rendering and returns its size in CSS px.
277
279
  *
278
- * With page options the tree lays out at the full page width with unbounded
279
- * height, exactly how {@link render} measures a header or footer band
280
- * (`pageNumber` / `totalPages` hooks are filled with three-digit counters),
281
- * so the height tells you how much margin a band needs.
280
+ * With page options the tree lays out against the full page width with
281
+ * unbounded height, exactly how {@link render} measures a header or footer
282
+ * band (`pageNumber` / `totalPages` hooks are filled with three-digit
283
+ * counters), so the height tells you how much margin a band needs.
284
+ *
285
+ * The returned size is the tree's own, not the space it was laid out
286
+ * against: a box with `width: 100px` measures 100 wide on any page.
282
287
  */
283
288
  measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
284
289
  /** Registers a font ahead of time, deduped against earlier registrations. */
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;
@@ -211,14 +212,15 @@ type ArchivalAttachment = Attachment & {
211
212
  };
212
213
  /**
213
214
  * Standards conformance. Invalid combinations are type errors: the `a` levels
214
- * imply a structure tree so `tagged: false` is rejected, PDF/A-4 is PDF 2.0
215
- * while PDF/UA-1 is PDF 1.7-only so they cannot combine, and only the
216
- * PDF/A-3 levels, PDF/A-4f (or plain PDF) accept attachments.
215
+ * imply a structure tree so `tagged: false` is rejected, PDF/UA-1 is PDF
216
+ * 1.7-only and PDF/UA-2 is PDF 2.0-only so each pairs with its own PDF/A
217
+ * levels, and only the PDF/A-3 levels, PDF/A-4f (or plain PDF) accept
218
+ * attachments.
217
219
  */
218
220
  type ConformanceOptions = {
219
221
  pdfa?: never;
220
- /** Structure tree: off, on (default), or validated against PDF/UA-1. */
221
- tagged?: boolean | "ua1";
222
+ /** Structure tree: off, on (default), or validated against PDF/UA. */
223
+ tagged?: boolean | "ua1" | "ua2";
222
224
  /** Files attached to the document. */
223
225
  attachments?: Attachment[];
224
226
  } | {
@@ -240,11 +242,11 @@ type ConformanceOptions = {
240
242
  attachments?: ArchivalAttachment[];
241
243
  } | {
242
244
  pdfa: "4";
243
- tagged?: boolean;
245
+ tagged?: boolean | "ua2";
244
246
  attachments?: never;
245
247
  } | {
246
248
  pdfa: "4f";
247
- tagged?: boolean;
249
+ tagged?: boolean | "ua2";
248
250
  attachments?: ArchivalAttachment[];
249
251
  };
250
252
  type RenderOptions = (PagedOptions | ViewportOptions) & ConformanceOptions & {
@@ -275,10 +277,13 @@ declare class PdfRenderer {
275
277
  /**
276
278
  * Lays out a node tree without rendering and returns its size in CSS px.
277
279
  *
278
- * With page options the tree lays out at the full page width with unbounded
279
- * height, exactly how {@link render} measures a header or footer band
280
- * (`pageNumber` / `totalPages` hooks are filled with three-digit counters),
281
- * so the height tells you how much margin a band needs.
280
+ * With page options the tree lays out against the full page width with
281
+ * unbounded height, exactly how {@link render} measures a header or footer
282
+ * band (`pageNumber` / `totalPages` hooks are filled with three-digit
283
+ * counters), so the height tells you how much margin a band needs.
284
+ *
285
+ * The returned size is the tree's own, not the space it was laid out
286
+ * against: a box with `width: 100px` measures 100 wide on any page.
282
287
  */
283
288
  measure(node: NodeInput, options?: MeasureOptions): Promise<MeasuredSize>;
284
289
  /** Registers a font ahead of time, deduped against earlier registrations. */
package/dist/export.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { fromHtml } from "@takumi-rs/helpers/html";
2
2
  import { fromJsx } from "@takumi-rs/helpers/jsx";
3
3
  import { FontRegistry } from "@takumi-rs/helpers/renderer";
4
+ import { subsetFonts } from "@takumi-rs/helpers";
4
5
  //#region pkg/takumi_pdf_wasm.js
5
6
  /**
6
7
  * A PDF renderer holding registered fonts and a decoded-resource cache.
@@ -99,6 +100,32 @@ var PdfRenderer$1 = class {
99
100
  }
100
101
  };
101
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
+ }
102
129
  function __wbg_get_imports() {
103
130
  return {
104
131
  __proto__: null,
@@ -378,6 +405,13 @@ let heap_next = heap.length;
378
405
  function isLikeNone(x) {
379
406
  return x === void 0 || x === null;
380
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
+ }
381
415
  function passStringToWasm0(arg, malloc, realloc) {
382
416
  if (realloc === void 0) {
383
417
  const buf = cachedTextEncoder.encode(arg);
@@ -493,6 +527,18 @@ async function __wbg_init(module_or_path) {
493
527
  }
494
528
  //#endregion
495
529
  //#region src/export.ts
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
+ }
496
542
  function isNode(value) {
497
543
  return typeof value === "object" && value !== null && "type" in value && !("$$typeof" in value);
498
544
  }
@@ -511,12 +557,20 @@ var PdfRenderer = class {
511
557
  /** Renders a node tree, JSX, or an HTML string to PDF bytes. See {@link RenderOptions}. */
512
558
  async render(node, options = {}) {
513
559
  const { fonts, images, header, footer, stylesheets, fontFamilies, ...rest } = options;
514
- const [main, headerResult, footerResult, resources] = await Promise.all([
560
+ const [main, headerResult, footerResult] = await Promise.all([
515
561
  resolveNode(node),
516
562
  header === void 0 ? void 0 : resolveNode(header),
517
- footer === void 0 ? void 0 : resolveNode(footer),
518
- this.fonts.resolveResources(fonts, images, fontFamilies)
563
+ footer === void 0 ? void 0 : resolveNode(footer)
519
564
  ]);
565
+ const bands = [headerResult?.node, footerResult?.node].filter((band) => band !== void 0);
566
+ const resources = await this.fonts.resolveResources(fonts && subsetFonts({
567
+ fonts,
568
+ source: [
569
+ main.node,
570
+ ...bands,
571
+ counterCharacters([main.node, ...bands].flatMap((tree) => classNames(tree)))
572
+ ]
573
+ }), images, fontFamilies);
520
574
  const sheets = [
521
575
  ...stylesheets ?? [],
522
576
  ...main.stylesheets,
@@ -535,14 +589,21 @@ var PdfRenderer = class {
535
589
  /**
536
590
  * Lays out a node tree without rendering and returns its size in CSS px.
537
591
  *
538
- * With page options the tree lays out at the full page width with unbounded
539
- * height, exactly how {@link render} measures a header or footer band
540
- * (`pageNumber` / `totalPages` hooks are filled with three-digit counters),
541
- * so the height tells you how much margin a band needs.
592
+ * With page options the tree lays out against the full page width with
593
+ * unbounded height, exactly how {@link render} measures a header or footer
594
+ * band (`pageNumber` / `totalPages` hooks are filled with three-digit
595
+ * counters), so the height tells you how much margin a band needs.
596
+ *
597
+ * The returned size is the tree's own, not the space it was laid out
598
+ * against: a box with `width: 100px` measures 100 wide on any page.
542
599
  */
543
600
  async measure(node, options = {}) {
544
601
  const { fonts, images, stylesheets, fontFamilies, ...rest } = options;
545
- const [main, resources] = await Promise.all([resolveNode(node), this.fonts.resolveResources(fonts, images, fontFamilies)]);
602
+ const main = await resolveNode(node);
603
+ const resources = await this.fonts.resolveResources(fonts && subsetFonts({
604
+ fonts,
605
+ source: [main.node, counterCharacters(classNames(main.node))]
606
+ }), images, fontFamilies);
546
607
  const sheets = [...stylesheets ?? [], ...main.stylesheets];
547
608
  return this.inner.measure(main.node, {
548
609
  ...rest,
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "takumi-pdf",
3
- "version": "0.4.2",
4
- "description": "HTML/JSX to paged, selectable-text PDF, powered by takumi. WebAssembly, no Chromium.",
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
- "rendering",
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.5.11"
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;