blitz-pdf 0.1.3 → 0.1.5

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.
Files changed (114) hide show
  1. package/README.md +35 -6
  2. package/THIRD_PARTY_NOTICES.md +5 -2
  3. package/dist/api.d.ts +9 -1
  4. package/dist/api.d.ts.map +1 -1
  5. package/dist/api.js +25 -27
  6. package/dist/api.js.map +1 -1
  7. package/dist/browser.d.ts +1 -1
  8. package/dist/browser.d.ts.map +1 -1
  9. package/dist/browser.js +13 -1
  10. package/dist/browser.js.map +1 -1
  11. package/dist/node-worker.d.ts +2 -0
  12. package/dist/node-worker.d.ts.map +1 -0
  13. package/dist/node-worker.js +10 -0
  14. package/dist/node-worker.js.map +1 -0
  15. package/dist/node.d.ts +1 -1
  16. package/dist/node.d.ts.map +1 -1
  17. package/dist/node.js +18 -6
  18. package/dist/node.js.map +1 -1
  19. package/dist/render.d.ts +8 -0
  20. package/dist/render.d.ts.map +1 -0
  21. package/dist/render.js +28 -0
  22. package/dist/render.js.map +1 -0
  23. package/dist/wasm.d.ts +3 -0
  24. package/dist/wasm.d.ts.map +1 -0
  25. package/dist/wasm.js +18 -0
  26. package/dist/wasm.js.map +1 -0
  27. package/dist/worker-host.d.ts +16 -0
  28. package/dist/worker-host.d.ts.map +1 -0
  29. package/dist/worker-host.js +31 -0
  30. package/dist/worker-host.js.map +1 -0
  31. package/dist/worker-protocol.d.ts +22 -0
  32. package/dist/worker-protocol.d.ts.map +1 -0
  33. package/dist/worker-protocol.js +2 -0
  34. package/dist/worker-protocol.js.map +1 -0
  35. package/dist/worker-runtime.d.ts +8 -0
  36. package/dist/worker-runtime.d.ts.map +1 -0
  37. package/dist/worker-runtime.js +34 -0
  38. package/dist/worker-runtime.js.map +1 -0
  39. package/dist/worker.d.ts +2 -0
  40. package/dist/worker.d.ts.map +1 -0
  41. package/dist/worker.js +7 -0
  42. package/dist/worker.js.map +1 -0
  43. package/docs/layout-regressions.md +65 -0
  44. package/docs/pagination-regressions.md +7 -6
  45. package/package.json +5 -2
  46. package/src/api.ts +33 -22
  47. package/src/browser.ts +13 -3
  48. package/src/node-worker.ts +9 -0
  49. package/src/node.ts +13 -4
  50. package/src/render.ts +28 -0
  51. package/src/wasm.ts +17 -0
  52. package/src/worker-host.ts +45 -0
  53. package/src/worker-protocol.ts +10 -0
  54. package/src/worker-runtime.ts +35 -0
  55. package/src/worker.ts +12 -0
  56. package/vendor/README.md +35 -0
  57. package/vendor/blitz-dom/Cargo.toml +113 -0
  58. package/vendor/blitz-dom/LICENSE-APACHE +176 -0
  59. package/vendor/blitz-dom/LICENSE-MIT +23 -0
  60. package/vendor/blitz-dom/assets/default.css +1142 -0
  61. package/vendor/blitz-dom/assets/moz-bullet-font.otf +0 -0
  62. package/vendor/blitz-dom/src/accessibility.rs +255 -0
  63. package/vendor/blitz-dom/src/config.rs +97 -0
  64. package/vendor/blitz-dom/src/cssom.rs +971 -0
  65. package/vendor/blitz-dom/src/debug.rs +206 -0
  66. package/vendor/blitz-dom/src/document.rs +3395 -0
  67. package/vendor/blitz-dom/src/events/driver.rs +427 -0
  68. package/vendor/blitz-dom/src/events/focus.rs +40 -0
  69. package/vendor/blitz-dom/src/events/ime.rs +31 -0
  70. package/vendor/blitz-dom/src/events/keyboard.rs +174 -0
  71. package/vendor/blitz-dom/src/events/mod.rs +315 -0
  72. package/vendor/blitz-dom/src/events/pointer.rs +849 -0
  73. package/vendor/blitz-dom/src/font_metrics.rs +177 -0
  74. package/vendor/blitz-dom/src/form.rs +463 -0
  75. package/vendor/blitz-dom/src/html.rs +38 -0
  76. package/vendor/blitz-dom/src/iframe.rs +186 -0
  77. package/vendor/blitz-dom/src/layout/construct.rs +1328 -0
  78. package/vendor/blitz-dom/src/layout/damage.rs +642 -0
  79. package/vendor/blitz-dom/src/layout/inline.rs +1160 -0
  80. package/vendor/blitz-dom/src/layout/list.rs +237 -0
  81. package/vendor/blitz-dom/src/layout/mod.rs +969 -0
  82. package/vendor/blitz-dom/src/layout/paint_tree.rs +462 -0
  83. package/vendor/blitz-dom/src/layout/replaced.rs +439 -0
  84. package/vendor/blitz-dom/src/layout/table.rs +967 -0
  85. package/vendor/blitz-dom/src/layout/text_transform.rs +979 -0
  86. package/vendor/blitz-dom/src/layout/writing_mode.rs +437 -0
  87. package/vendor/blitz-dom/src/lib.rs +160 -0
  88. package/vendor/blitz-dom/src/mutator.rs +1818 -0
  89. package/vendor/blitz-dom/src/net.rs +649 -0
  90. package/vendor/blitz-dom/src/node/attributes.rs +60 -0
  91. package/vendor/blitz-dom/src/node/custom_widget.rs +178 -0
  92. package/vendor/blitz-dom/src/node/element.rs +1106 -0
  93. package/vendor/blitz-dom/src/node/mod.rs +30 -0
  94. package/vendor/blitz-dom/src/node/node.rs +2036 -0
  95. package/vendor/blitz-dom/src/node/scrollbar.rs +237 -0
  96. package/vendor/blitz-dom/src/node/serialize.rs +225 -0
  97. package/vendor/blitz-dom/src/node/stylo_data.rs +142 -0
  98. package/vendor/blitz-dom/src/node/svg.rs +265 -0
  99. package/vendor/blitz-dom/src/node/text.rs +804 -0
  100. package/vendor/blitz-dom/src/query_selector.rs +275 -0
  101. package/vendor/blitz-dom/src/resolve.rs +474 -0
  102. package/vendor/blitz-dom/src/resolved_style.rs +797 -0
  103. package/vendor/blitz-dom/src/scrolling.rs +780 -0
  104. package/vendor/blitz-dom/src/selection.rs +122 -0
  105. package/vendor/blitz-dom/src/stylo.rs +1518 -0
  106. package/vendor/blitz-dom/src/stylo_device.rs +88 -0
  107. package/vendor/blitz-dom/src/stylo_to_cursor_icon.rs +49 -0
  108. package/vendor/blitz-dom/src/stylo_to_kurbo.rs +129 -0
  109. package/vendor/blitz-dom/src/stylo_to_parley.rs +655 -0
  110. package/vendor/blitz-dom/src/traversal.rs +600 -0
  111. package/vendor/blitz-dom/src/tree.rs +136 -0
  112. package/vendor/blitz-dom/src/url.rs +63 -0
  113. package/vendor/blitz-dom/src/util.rs +256 -0
  114. package/wasm/blitz_pdf_bg.wasm +0 -0
package/README.md CHANGED
@@ -74,6 +74,35 @@ CPU work. Use a Web Worker or server worker thread when the calling thread must
74
74
  stay responsive. Each worker gets its own WASM instance. Shared memory and
75
75
  cross-origin isolation are not required.
76
76
 
77
+ ## Rendering in a worker
78
+
79
+ `renderPdfInWorker` has the same signature as `renderPdf`, but layout and PDF
80
+ serialization run in a new worker: a Web Worker in browsers and a
81
+ `worker_threads` worker in Node.js and Bun. The calling thread stays responsive:
82
+
83
+ ```js
84
+ import { renderPdfInWorker } from "blitz-pdf"; // or "blitz-pdf/browser"
85
+
86
+ const pdfs = await Promise.all(documents.map(html =>
87
+ renderPdfInWorker(html, { format: "A4", assets: async url => (await fetch(url)).arrayBuffer() })));
88
+ ```
89
+
90
+ The WASM is compiled once into a `WebAssembly.Module` and posted to
91
+ every worker. Workers only instantiate it, so they skip WASM compilation.
92
+ `init({ wasm })` sets the source for this shared module as well. Each call
93
+ starts a separate worker and terminates it after the render, so its memory is
94
+ freed and concurrent calls run in parallel. Limit concurrency yourself, for
95
+ example to `navigator.hardwareConcurrency` or `os.availableParallelism()`.
96
+
97
+ Options are validated on the calling thread. An `assets` function also runs
98
+ there, so it can use closures, credentials, and caches; the worker receives
99
+ only the returned bytes. Errors are reported the same way as for `renderPdf`.
100
+ Bundlers must emit `dist/worker.js` through its `new Worker(new URL(...,
101
+ import.meta.url))` reference; Vite and webpack do this automatically.
102
+
103
+ To manage your own workers, post the shared module from `getWasmModule()` and
104
+ pass it to `init({ wasm: module })` inside the worker.
105
+
77
106
  ## Options
78
107
 
79
108
  `renderPdf(html: string, options?: PdfOptions): Promise<Uint8Array>`
@@ -450,12 +479,12 @@ node ID, zero-based line index and measured visible line range. Coordinates and
450
479
  heights are CSS pixels. Painted glyph runs without a DOM association and errors
451
480
  without a blocking line report those fields as `unavailable`.
452
481
 
453
- The pinned Blitz table layout still differs from Chromium for `td { max-width: 0 }`:
454
- it can constrain the cell itself to zero content width and wrap short text by
455
- character, while Chromium distributes the table width across the columns.
456
- Height-limited containers now paginate their visible content without failing,
457
- but this does not resolve that separate width-compatibility issue. See the
458
- [reproduction and investigation](docs/pagination-regressions.md).
482
+ The local Blitz layout patch preserves fractional page geometry, corrects
483
+ table-cell line spacing and empty-paragraph margin collapse, and stretches
484
+ `td { max-width: 0 }` cells to the columns allocated by the table. Ordinary
485
+ content inside `display: table` containers receives anonymous row/cell wrappers.
486
+ See the [layout regressions](docs/layout-regressions.md) and
487
+ [pagination investigation](docs/pagination-regressions.md).
459
488
 
460
489
  The first `<thead>` and `<tfoot>` (or elements styled as `table-header-group`
461
490
  and `table-footer-group`) repeat on every fragment of their table. Their actual
@@ -17,8 +17,11 @@ through crates.io. Stylo 0.22.0 is patched to expose paged-media CSS properties
17
17
  in its Servo build. Its full modified MPL-2.0 source and license are included in
18
18
  `vendor/stylo`. Krilla 0.8.2 is patched for custom XMP extension schemas and
19
19
  independent modification dates; its source and MIT/Apache-2.0 licenses are in
20
- `vendor/krilla`. `vendor/README.md` lists both patches. Other dependencies are
21
- used without source modifications.
20
+ `vendor/krilla`. Blitz's DOM crate is patched for fractional PDF geometry,
21
+ table-cell sizing/spacing, anonymous table wrappers, and paragraph margin
22
+ collapse; its source and MIT/Apache-2.0 licenses are in `vendor/blitz-dom`.
23
+ `vendor/README.md` lists these patches. Other dependencies are used without
24
+ source modifications.
22
25
 
23
26
  Bundled DejaVu fonts use the Bitstream Vera / DejaVu license reproduced in
24
27
  `licenses/DejaVu.txt`. The regular WOFF2 comes from Blitz's
package/dist/api.d.ts CHANGED
@@ -1,7 +1,15 @@
1
+ import { type SpawnWorker } from "./worker-host.js";
1
2
  import type { InitOptions, PdfOptions, WasmSource } from "./types.js";
2
- export declare function createApi(defaultSource: () => Promise<WasmSource> | WasmSource, prepare?: (source: WasmSource) => Promise<WasmSource>): {
3
+ export interface ApiConfig {
4
+ defaultSource: () => Promise<WasmSource> | WasmSource;
5
+ prepare?: (source: WasmSource) => Promise<WasmSource>;
6
+ spawnWorker: SpawnWorker;
7
+ }
8
+ export declare function createApi({ defaultSource, prepare, spawnWorker }: ApiConfig): {
3
9
  init: (options?: InitOptions) => Promise<void>;
4
10
  renderPdf: (html: string, options?: PdfOptions) => Promise<Uint8Array>;
11
+ renderPdfInWorker: (html: string, options?: PdfOptions) => Promise<Uint8Array>;
12
+ getWasmModule: () => Promise<WebAssembly.Module>;
5
13
  getEngineVersion: () => Promise<string>;
6
14
  };
7
15
  //# sourceMappingURL=api.d.ts.map
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,wBAAgB,SAAS,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,EAC7E,OAAO,GAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAA0B;qBAItD,WAAW,KAAQ,OAAO,CAAC,IAAI,CAAC;sBAUxB,MAAM,YAAW,UAAU,KAAQ,OAAO,CAAC,UAAU,CAAC;4BAqBlD,OAAO,CAAC,MAAM,CAAC;EAEnD"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAKA,OAAO,EAAkB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC;IACtD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IACtD,WAAW,EAAE,WAAW,CAAC;CAC1B;AAED,wBAAgB,SAAS,CAAC,EAAE,aAAa,EAAE,OAAgC,EAAE,WAAW,EAAE,EAAE,SAAS;qBAY5E,WAAW,KAAQ,OAAO,CAAC,IAAI,CAAC;sBAYxB,MAAM,YAAW,UAAU,KAAQ,OAAO,CAAC,UAAU,CAAC;8BAQ9C,MAAM,YAAW,UAAU,KAAQ,OAAO,CAAC,UAAU,CAAC;yBAXnE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC;4BAiBlB,OAAO,CAAC,MAAM,CAAC;EAEnD"}
package/dist/api.js CHANGED
@@ -1,46 +1,44 @@
1
- import loadWasm, { render_pdf, engine_version, RenderJob } from "../wasm/blitz_pdf.js";
1
+ import loadWasm, { engine_version } from "../wasm/blitz_pdf.js";
2
2
  import { createAssetLoader } from "./assets.js";
3
3
  import { normalizeOptions } from "./options.js";
4
- export function createApi(defaultSource, prepare = async (source) => source) {
4
+ import { render, validateHtml } from "./render.js";
5
+ import { compileWasm } from "./wasm.js";
6
+ import { renderInWorker } from "./worker-host.js";
7
+ export function createApi({ defaultSource, prepare = async (source) => source, spawnWorker }) {
8
+ let compiled;
5
9
  let ready;
10
+ function compile(source) {
11
+ if (compiled)
12
+ return compiled;
13
+ compiled = (async () => compileWasm(await prepare(source ?? await defaultSource())))()
14
+ .catch((error) => { compiled = undefined; throw error; });
15
+ return compiled;
16
+ }
6
17
  /** Initialize once. Concurrent callers share initialization; failed loads can be retried. */
7
18
  function init(options = {}) {
8
19
  if (ready)
9
20
  return ready;
10
21
  ready = (async () => {
11
- const source = await prepare(options.wasm ?? await defaultSource());
12
- await loadWasm({ module_or_path: source });
22
+ await loadWasm({ module_or_path: await compile(options.wasm) });
13
23
  })().catch((error) => { ready = undefined; throw error; });
14
24
  return ready;
15
25
  }
26
+ /** The compiled WASM module, compiled once and shared with every worker. It can be posted to your own workers. */
27
+ function getWasmModule() { return compile(); }
16
28
  /** Render HTML/CSS to a vector PDF/A-3u with embedded fonts and selectable text. */
17
29
  async function renderPdf(html, options = {}) {
18
- if (typeof html !== "string")
19
- throw new TypeError("html must be a string");
20
- if (new TextEncoder().encode(html).byteLength > 16 * 1024 * 1024)
21
- throw new RangeError("HTML exceeds the 16 MiB limit");
30
+ validateHtml(html);
22
31
  const { assetResolver, ...normalized } = normalizeOptions(options);
23
32
  await init();
24
- if (!assetResolver)
25
- return render_pdf(html, normalized);
26
- const load = createAssetLoader(assetResolver);
27
- const job = new RenderJob(html, normalized);
28
- try {
29
- for (;;) {
30
- const urls = job.pending_assets();
31
- if (urls.length === 0)
32
- return job.finish();
33
- const data = await load(urls);
34
- for (let i = 0; i < urls.length; i++)
35
- job.provide_asset(urls[i], data[i]);
36
- }
37
- }
38
- finally {
39
- // In-flight JS loaders never access this job, including after a sibling rejects.
40
- job.free();
41
- }
33
+ return render(html, normalized, assetResolver && createAssetLoader(assetResolver));
34
+ }
35
+ /** Like `renderPdf`, but layout and serialization run in a new worker. An `assets` function still runs on the calling thread. */
36
+ async function renderPdfInWorker(html, options = {}) {
37
+ validateHtml(html);
38
+ const { assetResolver, ...normalized } = normalizeOptions(options);
39
+ return renderInWorker(spawnWorker, await compile(), html, normalized, assetResolver);
42
40
  }
43
41
  async function getEngineVersion() { await init(); return engine_version(); }
44
- return { init, renderPdf, getEngineVersion };
42
+ return { init, renderPdf, renderPdfInWorker, getWasmModule, getEngineVersion };
45
43
  }
46
44
  //# sourceMappingURL=api.js.map
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,UAAU,SAAS,CAAC,aAAqD,EAC7E,UAAuD,KAAK,EAAC,MAAM,EAAC,EAAE,CAAC,MAAM;IAC7E,IAAI,KAAgC,CAAC;IAErC,6FAA6F;IAC7F,SAAS,IAAI,CAAC,UAAuB,EAAE;QACrC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,aAAa,EAAE,CAAC,CAAC;YACpE,MAAM,QAAQ,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oFAAoF;IACpF,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,UAAsB,EAAE;QAC7D,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC3E,IAAI,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;YAAE,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;QACxH,MAAM,EAAE,aAAa,EAAE,GAAG,UAAU,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,IAAI,EAAE,CAAC;QACb,IAAI,CAAC,aAAa;YAAE,OAAO,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACxD,MAAM,IAAI,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,SAAS,CAAC;gBACR,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;gBAClC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;oBAAE,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,iFAAiF;YACjF,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,KAAK,UAAU,gBAAgB,KAAsB,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,cAAc,EAAE,CAAC,CAAC,CAAC;IAC7F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,EAAE,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAC;AASpE,MAAM,UAAU,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,GAAG,KAAK,EAAC,MAAM,EAAC,EAAE,CAAC,MAAM,EAAE,WAAW,EAAa;IACnG,IAAI,QAAiD,CAAC;IACtD,IAAI,KAAgC,CAAC;IAErC,SAAS,OAAO,CAAC,MAAmB;QAClC,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,QAAQ,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,OAAO,CAAC,MAAM,IAAI,MAAM,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE;aACnF,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACrE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,6FAA6F;IAC7F,SAAS,IAAI,CAAC,UAAuB,EAAE;QACrC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,QAAQ,CAAC,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,KAAK,GAAG,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,kHAAkH;IAClH,SAAS,aAAa,KAAkC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC;IAE3E,oFAAoF;IACpF,KAAK,UAAU,SAAS,CAAC,IAAY,EAAE,UAAsB,EAAE;QAC7D,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,EAAE,aAAa,EAAE,GAAG,UAAU,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnE,MAAM,IAAI,EAAE,CAAC;QACb,OAAO,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,aAAa,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC;IACrF,CAAC;IAED,iIAAiI;IACjI,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,UAAsB,EAAE;QACrE,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,EAAE,aAAa,EAAE,GAAG,UAAU,EAAE,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnE,OAAO,cAAc,CAAC,WAAW,EAAE,MAAM,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;IACvF,CAAC;IAED,KAAK,UAAU,gBAAgB,KAAsB,MAAM,IAAI,EAAE,CAAC,CAAC,OAAO,cAAc,EAAE,CAAC,CAAC,CAAC;IAC7F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC;AACjF,CAAC"}
package/dist/browser.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export type { AssetData, AssetMap, AssetResolver, AttachmentRelationship, BinaryData, InitOptions, Length, PageFormat, PageNumberOptions, PdfAttachment, PdfDate, PdfMetadata, PdfOptions, PdfXmpProperty, PdfXmpSchema, WasmSource } from "./types.js";
2
- export declare const init: (options?: import("./types.js").InitOptions) => Promise<void>, renderPdf: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, getEngineVersion: () => Promise<string>;
2
+ export declare const init: (options?: import("./types.js").InitOptions) => Promise<void>, renderPdf: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, renderPdfInWorker: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, getWasmModule: () => Promise<WebAssembly.Module>, getEngineVersion: () => Promise<string>;
3
3
  //# sourceMappingURL=browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxP,eAAO,MAAQ,IAAI,iEAAE,SAAS,oFAAE,gBAAgB,uBAE/C,CAAC"}
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAEA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxP,eAAO,MAAQ,IAAI,iEAAE,SAAS,oFAAE,iBAAiB,oFAAE,aAAa,qCAAE,gBAAgB,uBAYhF,CAAC"}
package/dist/browser.js CHANGED
@@ -1,3 +1,15 @@
1
1
  import { createApi } from "./api.js";
2
- export const { init, renderPdf, getEngineVersion } = createApi(() => new URL("../wasm/blitz_pdf_bg.wasm", import.meta.url));
2
+ export const { init, renderPdf, renderPdfInWorker, getWasmModule, getEngineVersion } = createApi({
3
+ defaultSource: () => new URL("../wasm/blitz_pdf_bg.wasm", import.meta.url),
4
+ spawnWorker: events => {
5
+ const worker = new Worker(new URL("./worker.js", import.meta.url), { type: "module" });
6
+ worker.onmessage = event => events.message(event.data);
7
+ worker.onerror = event => {
8
+ event.preventDefault();
9
+ events.error(new Error(`Render worker failed: ${event.message || "unknown error"}`));
10
+ };
11
+ worker.onmessageerror = () => events.error(new Error("Render worker sent a message that could not be deserialized"));
12
+ return { post: (message, transfer) => worker.postMessage(message, transfer), terminate: () => worker.terminate() };
13
+ },
14
+ });
3
15
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAC5D,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAC5D,CAAC"}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAAC;IAC/F,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;IAC1E,WAAW,EAAE,MAAM,CAAC,EAAE;QACpB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvD,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE;YACvB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,yBAAyB,KAAK,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC;QACF,MAAM,CAAC,cAAc,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC,CAAC;QACrH,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;IACrH,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=node-worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-worker.d.ts","sourceRoot":"","sources":["../src/node-worker.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { parentPort } from "node:worker_threads";
2
+ import { serve } from "./worker-runtime.js";
3
+ const port = parentPort;
4
+ if (!port)
5
+ throw new Error("blitz-pdf node-worker must run in a worker thread");
6
+ serve({
7
+ post: (message, transfer) => port.postMessage(message, transfer),
8
+ onMessage: handler => { port.on("message", handler); },
9
+ });
10
+ //# sourceMappingURL=node-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-worker.js","sourceRoot":"","sources":["../src/node-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE5C,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,IAAI,CAAC,IAAI;IAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;AAChF,KAAK,CAAC;IACJ,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;IAChE,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;CACvD,CAAC,CAAC"}
package/dist/node.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export type { AssetData, AssetMap, AssetResolver, AttachmentRelationship, BinaryData, InitOptions, Length, PageFormat, PageNumberOptions, PdfAttachment, PdfDate, PdfMetadata, PdfOptions, PdfXmpProperty, PdfXmpSchema, WasmSource } from "./types.js";
2
- export declare const init: (options?: import("./types.js").InitOptions) => Promise<void>, renderPdf: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, getEngineVersion: () => Promise<string>;
2
+ export declare const init: (options?: import("./types.js").InitOptions) => Promise<void>, renderPdf: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, renderPdfInWorker: (html: string, options?: import("./types.js").PdfOptions) => Promise<Uint8Array>, getWasmModule: () => Promise<WebAssembly.Module>, getEngineVersion: () => Promise<string>;
3
3
  //# sourceMappingURL=node.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAGA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxP,eAAO,MAAQ,IAAI,iEAAE,SAAS,oFAAE,gBAAgB,uBAO/C,CAAC"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,sBAAsB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxP,eAAO,MAAQ,IAAI,iEAAE,SAAS,oFAAE,iBAAiB,oFAAE,aAAa,qCAAE,gBAAgB,uBAehF,CAAC"}
package/dist/node.js CHANGED
@@ -1,10 +1,22 @@
1
1
  import { readFile } from "node:fs/promises";
2
+ import { Worker } from "node:worker_threads";
2
3
  import { createApi } from "./api.js";
3
- export const { init, renderPdf, getEngineVersion } = createApi(() => readFile(new URL("../wasm/blitz_pdf_bg.wasm", import.meta.url)), async (source) => {
4
- if (source instanceof URL && source.protocol === "file:")
5
- return readFile(source);
6
- if (typeof source === "string" && source.startsWith("file:"))
7
- return readFile(new URL(source));
8
- return source;
4
+ export const { init, renderPdf, renderPdfInWorker, getWasmModule, getEngineVersion } = createApi({
5
+ defaultSource: () => readFile(new URL("../wasm/blitz_pdf_bg.wasm", import.meta.url)),
6
+ prepare: async (source) => {
7
+ if (source instanceof URL && source.protocol === "file:")
8
+ return readFile(source);
9
+ if (typeof source === "string" && source.startsWith("file:"))
10
+ return readFile(new URL(source));
11
+ return source;
12
+ },
13
+ spawnWorker: events => {
14
+ const worker = new Worker(new URL("./node-worker.js", import.meta.url));
15
+ worker.on("message", events.message);
16
+ worker.on("error", events.error);
17
+ worker.on("messageerror", events.error);
18
+ worker.on("exit", code => events.error(new Error(`Render worker exited with code ${code}`)));
19
+ return { post: (message, transfer) => worker.postMessage(message, transfer), terminate: () => void worker.terminate() };
20
+ },
9
21
  });
10
22
  //# sourceMappingURL=node.js.map
package/dist/node.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAC5D,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EACrE,KAAK,EAAC,MAAM,EAAC,EAAE;IACb,IAAI,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClF,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/F,OAAO,MAAM,CAAC;AAChB,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,SAAS,CAAC;IAC/F,aAAa,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpF,OAAO,EAAE,KAAK,EAAC,MAAM,EAAC,EAAE;QACtB,IAAI,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC;QAClF,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/F,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,WAAW,EAAE,MAAM,CAAC,EAAE;QACpB,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,kBAAkB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,kCAAkC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7F,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;IAC1H,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { normalizeOptions } from "./options.js";
2
+ /** Normalized options without the resolver function, so they can be posted to a worker. */
3
+ export type RenderOptions = Omit<ReturnType<typeof normalizeOptions>, "assetResolver">;
4
+ export type LoadAssets = (urls: string[]) => Promise<Uint8Array[]>;
5
+ export declare function validateHtml(html: unknown): asserts html is string;
6
+ /** Requires an initialized WASM instance in the current thread. */
7
+ export declare function render(html: string, options: RenderOptions, load?: LoadAssets): Promise<Uint8Array>;
8
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,2FAA2F;AAC3F,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAAE,eAAe,CAAC,CAAC;AACvF,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;AAEnE,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAGlE;AAED,mEAAmE;AACnE,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAczG"}
package/dist/render.js ADDED
@@ -0,0 +1,28 @@
1
+ import { render_pdf, RenderJob } from "../wasm/blitz_pdf.js";
2
+ export function validateHtml(html) {
3
+ if (typeof html !== "string")
4
+ throw new TypeError("html must be a string");
5
+ if (new TextEncoder().encode(html).byteLength > 16 * 1024 * 1024)
6
+ throw new RangeError("HTML exceeds the 16 MiB limit");
7
+ }
8
+ /** Requires an initialized WASM instance in the current thread. */
9
+ export async function render(html, options, load) {
10
+ if (!load)
11
+ return render_pdf(html, options);
12
+ const job = new RenderJob(html, options);
13
+ try {
14
+ for (;;) {
15
+ const urls = job.pending_assets();
16
+ if (urls.length === 0)
17
+ return job.finish();
18
+ const data = await load(urls);
19
+ for (let i = 0; i < urls.length; i++)
20
+ job.provide_asset(urls[i], data[i]);
21
+ }
22
+ }
23
+ finally {
24
+ // In-flight JS loaders never access this job, including after a sibling rejects.
25
+ job.free();
26
+ }
27
+ }
28
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAO7D,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,uBAAuB,CAAC,CAAC;IAC3E,IAAI,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI;QAAE,MAAM,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAC;AAC1H,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAY,EAAE,OAAsB,EAAE,IAAiB;IAClF,IAAI,CAAC,IAAI;QAAE,OAAO,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC;QACH,SAAS,CAAC;YACR,MAAM,IAAI,GAAG,GAAG,CAAC,cAAc,EAAE,CAAC;YAClC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,GAAG,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;YAAS,CAAC;QACT,iFAAiF;QACjF,GAAG,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
package/dist/wasm.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { WasmSource } from "./types.js";
2
+ export declare function compileWasm(source: WasmSource): Promise<WebAssembly.Module>;
3
+ //# sourceMappingURL=wasm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm.d.ts","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAsB,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAcjF"}
package/dist/wasm.js ADDED
@@ -0,0 +1,18 @@
1
+ export async function compileWasm(source) {
2
+ if (source instanceof WebAssembly.Module)
3
+ return source;
4
+ if (typeof source === "string" || source instanceof URL || (typeof Request === "function" && source instanceof Request)) {
5
+ source = await fetch(source);
6
+ }
7
+ if (typeof Response === "function" && source instanceof Response) {
8
+ if (!source.ok)
9
+ throw new Error(`Failed to fetch WASM: ${source.status} ${source.statusText} fetching '${source.url}'`);
10
+ // Streaming compilation rejects other MIME types, so fall back to buffering instead.
11
+ if (typeof WebAssembly.compileStreaming === "function" && source.headers.get("Content-Type") === "application/wasm") {
12
+ return WebAssembly.compileStreaming(source);
13
+ }
14
+ return WebAssembly.compile(await source.arrayBuffer());
15
+ }
16
+ return WebAssembly.compile(source);
17
+ }
18
+ //# sourceMappingURL=wasm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasm.js","sourceRoot":"","sources":["../src/wasm.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,MAAkB;IAClD,IAAI,MAAM,YAAY,WAAW,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IACxD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,OAAO,KAAK,UAAU,IAAI,MAAM,YAAY,OAAO,CAAC,EAAE,CAAC;QACxH,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,OAAO,QAAQ,KAAK,UAAU,IAAI,MAAM,YAAY,QAAQ,EAAE,CAAC;QACjE,IAAI,CAAC,MAAM,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,cAAc,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;QACxH,qFAAqF;QACrF,IAAI,OAAO,WAAW,CAAC,gBAAgB,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,kBAAkB,EAAE,CAAC;YACpH,OAAO,WAAW,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,WAAW,CAAC,OAAO,CAAC,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,WAAW,CAAC,OAAO,CAAC,MAAsB,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { RenderOptions } from "./render.js";
2
+ import type { AssetResolver } from "./types.js";
3
+ import type { HostMessage, WorkerMessage } from "./worker-protocol.js";
4
+ export interface WorkerEvents {
5
+ message(message: WorkerMessage): void;
6
+ /** Crashes, unreadable messages, or an exit before the render settled. */
7
+ error(error: unknown): void;
8
+ }
9
+ export interface WorkerHandle {
10
+ post(message: HostMessage, transfer: ArrayBuffer[]): void;
11
+ terminate(): void;
12
+ }
13
+ export type SpawnWorker = (events: WorkerEvents) => WorkerHandle;
14
+ /** Renders in a fresh worker that instantiates the precompiled module, then terminates it. */
15
+ export declare function renderInWorker(spawn: SpawnWorker, module: WebAssembly.Module, html: string, options: RenderOptions, resolver: AssetResolver | undefined): Promise<Uint8Array>;
16
+ //# sourceMappingURL=worker-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-host.d.ts","sourceRoot":"","sources":["../src/worker-host.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IACtC,0EAA0E;IAC1E,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAC1D,SAAS,IAAI,IAAI,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,YAAY,KAAK,YAAY,CAAC;AAEjE,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EACzF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAwBlF"}
@@ -0,0 +1,31 @@
1
+ import { createAssetLoader } from "./assets.js";
2
+ /** Renders in a fresh worker that instantiates the precompiled module, then terminates it. */
3
+ export function renderInWorker(spawn, module, html, options, resolver) {
4
+ return new Promise((resolve, reject) => {
5
+ const load = resolver && createAssetLoader(resolver);
6
+ let settled = false;
7
+ const settle = (callback) => {
8
+ if (settled)
9
+ return;
10
+ settled = true;
11
+ worker.terminate();
12
+ callback();
13
+ };
14
+ const worker = spawn({
15
+ message(message) {
16
+ if (message.type === "done")
17
+ settle(() => resolve(message.pdf));
18
+ else if (message.type === "error")
19
+ settle(() => reject(message.error));
20
+ else if (!load)
21
+ settle(() => reject(new Error("Render worker requested assets without a resolver")));
22
+ else
23
+ load(message.urls).then(data => { if (!settled)
24
+ worker.post({ type: "assets", data }, data.map(bytes => bytes.buffer)); }, (error) => settle(() => reject(error)));
25
+ },
26
+ error(error) { settle(() => reject(error)); },
27
+ });
28
+ worker.post({ type: "render", module, html, options, external: load !== undefined }, []);
29
+ });
30
+ }
31
+ //# sourceMappingURL=worker-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-host.js","sourceRoot":"","sources":["../src/worker-host.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAkBhD,8FAA8F;AAC9F,MAAM,UAAU,cAAc,CAAC,KAAkB,EAAE,MAA0B,EAAE,IAAY,EACzF,OAAsB,EAAE,QAAmC;IAC3D,OAAO,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,QAAQ,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACrD,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,QAAoB,EAAE,EAAE;YACtC,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,SAAS,EAAE,CAAC;YACnB,QAAQ,EAAE,CAAC;QACb,CAAC,CAAC;QACF,MAAM,MAAM,GAAiB,KAAK,CAAC;YACjC,OAAO,CAAC,OAAO;gBACb,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;oBAAE,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;qBAC3D,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;oBAAE,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;qBAClE,IAAI,CAAC,IAAI;oBAAE,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC,CAAC,CAAC;;oBAChG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAC1B,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO;wBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,MAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,EAChH,CAAC,KAAc,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAChD,CAAC;YACJ,CAAC;YACD,KAAK,CAAC,KAAK,IAAI,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;SAC9C,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,KAAK,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { RenderOptions } from "./render.js";
2
+ export type HostMessage = {
3
+ type: "render";
4
+ module: WebAssembly.Module;
5
+ html: string;
6
+ options: RenderOptions;
7
+ external: boolean;
8
+ } | {
9
+ type: "assets";
10
+ data: Uint8Array[];
11
+ };
12
+ export type WorkerMessage = {
13
+ type: "assets";
14
+ urls: string[];
15
+ } | {
16
+ type: "done";
17
+ pdf: Uint8Array;
18
+ } | {
19
+ type: "error";
20
+ error: unknown;
21
+ };
22
+ //# sourceMappingURL=worker-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-protocol.d.ts","sourceRoot":"","sources":["../src/worker-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACvG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAE3C,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,UAAU,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=worker-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-protocol.js","sourceRoot":"","sources":["../src/worker-protocol.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { HostMessage, WorkerMessage } from "./worker-protocol.js";
2
+ export interface WorkerEndpoint {
3
+ post(message: WorkerMessage, transfer: ArrayBuffer[]): void;
4
+ onMessage(handler: (message: HostMessage) => void): void;
5
+ }
6
+ /** Worker side of `renderPdfInWorker`: one render per worker; asset bytes come from the host. */
7
+ export declare function serve(endpoint: WorkerEndpoint): void;
8
+ //# sourceMappingURL=worker-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-runtime.d.ts","sourceRoot":"","sources":["../src/worker-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEvE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAC5D,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1D;AAED,iGAAiG;AACjG,wBAAgB,KAAK,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAwBpD"}
@@ -0,0 +1,34 @@
1
+ import { initSync } from "../wasm/blitz_pdf.js";
2
+ import { render } from "./render.js";
3
+ /** Worker side of `renderPdfInWorker`: one render per worker; asset bytes come from the host. */
4
+ export function serve(endpoint) {
5
+ let receiveAssets;
6
+ endpoint.onMessage(async (message) => {
7
+ if (message.type === "assets") {
8
+ const receive = receiveAssets;
9
+ receiveAssets = undefined;
10
+ receive?.(message.data);
11
+ return;
12
+ }
13
+ try {
14
+ initSync({ module: message.module });
15
+ const load = message.external
16
+ ? (urls) => new Promise(resolve => {
17
+ receiveAssets = resolve;
18
+ endpoint.post({ type: "assets", urls }, []);
19
+ })
20
+ : undefined;
21
+ const pdf = await render(message.html, message.options, load);
22
+ endpoint.post({ type: "done", pdf }, [pdf.buffer]);
23
+ }
24
+ catch (error) {
25
+ try {
26
+ endpoint.post({ type: "error", error }, []);
27
+ }
28
+ catch {
29
+ endpoint.post({ type: "error", error: new Error(String(error)) }, []);
30
+ }
31
+ }
32
+ });
33
+ }
34
+ //# sourceMappingURL=worker-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-runtime.js","sourceRoot":"","sources":["../src/worker-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,iGAAiG;AACjG,MAAM,UAAU,KAAK,CAAC,QAAwB;IAC5C,IAAI,aAAyD,CAAC;IAC9D,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;QACjC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,aAAa,CAAC;YAC9B,aAAa,GAAG,SAAS,CAAC;YAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACxB,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ;gBAC3B,CAAC,CAAC,CAAC,IAAc,EAAE,EAAE,CAAC,IAAI,OAAO,CAAe,OAAO,CAAC,EAAE;oBACxD,aAAa,GAAG,OAAO,CAAC;oBACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBAC9C,CAAC,CAAC;gBACF,CAAC,CAAC,SAAS,CAAC;YACd,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC9D,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAqB,CAAC,CAAC,CAAC;QACpE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;YAAC,CAAC;YACpD,MAAM,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAAC,CAAC;QAClF,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":""}
package/dist/worker.js ADDED
@@ -0,0 +1,7 @@
1
+ import { serve } from "./worker-runtime.js";
2
+ const scope = globalThis;
3
+ serve({
4
+ post: (message, transfer) => scope.postMessage(message, transfer),
5
+ onMessage: handler => { scope.onmessage = event => handler(event.data); },
6
+ });
7
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../src/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAO5C,MAAM,KAAK,GAAG,UAA6C,CAAC;AAC5D,KAAK,CAAC;IACJ,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC;IACjE,SAAS,EAAE,OAAO,CAAC,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CAC1E,CAAC,CAAC"}