blitz-pdf 0.1.4 → 0.1.6
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 +67 -3
- package/THIRD_PARTY_NOTICES.md +2 -0
- package/dist/api.d.ts +9 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +25 -27
- package/dist/api.js.map +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +13 -1
- package/dist/browser.js.map +1 -1
- package/dist/node-worker.d.ts +2 -0
- package/dist/node-worker.d.ts.map +1 -0
- package/dist/node-worker.js +10 -0
- package/dist/node-worker.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +18 -6
- package/dist/node.js.map +1 -1
- package/dist/render.d.ts +8 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +28 -0
- package/dist/render.js.map +1 -0
- package/dist/wasm.d.ts +3 -0
- package/dist/wasm.d.ts.map +1 -0
- package/dist/wasm.js +18 -0
- package/dist/wasm.js.map +1 -0
- package/dist/worker-host.d.ts +16 -0
- package/dist/worker-host.d.ts.map +1 -0
- package/dist/worker-host.js +31 -0
- package/dist/worker-host.js.map +1 -0
- package/dist/worker-protocol.d.ts +22 -0
- package/dist/worker-protocol.d.ts.map +1 -0
- package/dist/worker-protocol.js +2 -0
- package/dist/worker-protocol.js.map +1 -0
- package/dist/worker-runtime.d.ts +8 -0
- package/dist/worker-runtime.d.ts.map +1 -0
- package/dist/worker-runtime.js +34 -0
- package/dist/worker-runtime.js.map +1 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +7 -0
- package/dist/worker.js.map +1 -0
- package/package.json +5 -2
- package/src/api.ts +33 -22
- package/src/browser.ts +13 -3
- package/src/node-worker.ts +9 -0
- package/src/node.ts +13 -4
- package/src/render.ts +28 -0
- package/src/wasm.ts +17 -0
- package/src/worker-host.ts +45 -0
- package/src/worker-protocol.ts +10 -0
- package/src/worker-runtime.ts +35 -0
- package/src/worker.ts +12 -0
- package/vendor/README.md +24 -0
- package/vendor/blitz-paint/Cargo.toml +50 -0
- package/vendor/blitz-paint/LICENSE-APACHE +176 -0
- package/vendor/blitz-paint/LICENSE-MIT +23 -0
- package/vendor/blitz-paint/src/color.rs +66 -0
- package/vendor/blitz-paint/src/debug_overlay.rs +168 -0
- package/vendor/blitz-paint/src/filters.rs +40 -0
- package/vendor/blitz-paint/src/gradient.rs +536 -0
- package/vendor/blitz-paint/src/kurbo_css/css_box.rs +847 -0
- package/vendor/blitz-paint/src/kurbo_css/mod.rs +77 -0
- package/vendor/blitz-paint/src/kurbo_css/non_uniform_radii.rs +60 -0
- package/vendor/blitz-paint/src/layers.rs +95 -0
- package/vendor/blitz-paint/src/lib.rs +190 -0
- package/vendor/blitz-paint/src/render/background.rs +968 -0
- package/vendor/blitz-paint/src/render/border.rs +631 -0
- package/vendor/blitz-paint/src/render/box_shadow.rs +157 -0
- package/vendor/blitz-paint/src/render/clip_path.rs +492 -0
- package/vendor/blitz-paint/src/render/form_controls.rs +103 -0
- package/vendor/blitz-paint/src/render/mask.rs +144 -0
- package/vendor/blitz-paint/src/render.rs +1351 -0
- package/vendor/blitz-paint/src/sizing.rs +63 -0
- package/vendor/blitz-paint/src/text.rs +747 -0
- 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>`
|
|
@@ -367,6 +396,38 @@ Input limits: 16 MiB HTML, 64 MiB supplied assets, 64 MiB attachments, 32 MiB su
|
|
|
367
396
|
resource requests. These are practical limits, not a complete sandbox; isolate
|
|
368
397
|
untrusted documents in a terminable worker with application limits.
|
|
369
398
|
|
|
399
|
+
### Unicode text
|
|
400
|
+
|
|
401
|
+
HTML strings and UTF-8 assets preserve the text produced by layout, including
|
|
402
|
+
non-Latin scripts, supplementary-plane characters, combining marks, and
|
|
403
|
+
ligatures. Visually identical sequences such as `é` / `é`, `fi` / `fi`, and
|
|
404
|
+
composed / decomposed Hangul can coexist in one document. Their source mappings
|
|
405
|
+
remain separate in body text, form values, repeated table headers, margin
|
|
406
|
+
templates, and page numbers. CSS whitespace handling and `text-transform`
|
|
407
|
+
still apply normally.
|
|
408
|
+
|
|
409
|
+
PDF Unicode maps and `ActualText` spans preserve the original sequences when
|
|
410
|
+
multiple characters share a glyph or a cluster uses multiple glyphs. Accurate
|
|
411
|
+
copy/paste requires a reader that supports `ActualText`; extractors that ignore
|
|
412
|
+
it, including PDF.js, can normalize ligatures or repeat combining clusters.
|
|
413
|
+
The Unicode regression suite verifies extraction with Poppler's `pdftotext`.
|
|
414
|
+
|
|
415
|
+
Unicode support does not imply that one font covers every character. There is
|
|
416
|
+
no system-font discovery or automatic font download. For example, provide a
|
|
417
|
+
static CJK font and select its family to render Chinese, Japanese, or Korean:
|
|
418
|
+
|
|
419
|
+
```js
|
|
420
|
+
import { readFile } from "node:fs/promises";
|
|
421
|
+
|
|
422
|
+
const pdf = await renderPdf(
|
|
423
|
+
'<p style="font-family: \'Noto Sans CJK SC\'">中文 日本語 한국어</p>',
|
|
424
|
+
{ fonts: [await readFile("NotoSansCJKsc-Regular.otf")] },
|
|
425
|
+
);
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Use `@font-face` and `assets` for a CSS family alias. Fonts must contain the
|
|
429
|
+
required glyphs and permit embedding; missing glyphs still reject PDF/A output.
|
|
430
|
+
|
|
370
431
|
## PDF/A-3 conformance
|
|
371
432
|
|
|
372
433
|
Every successful render targets **PDF/A-3u (ISO 19005-3, level U)**. The PDF 1.7
|
|
@@ -577,6 +638,8 @@ transition rule. [§ 14 UStG](https://www.gesetze-im-internet.de/ustg_1980/__14.
|
|
|
577
638
|
|
|
578
639
|
Install Node.js 22.13+ for development tooling, Bun, and rustup. The repository
|
|
579
640
|
pins Rust 1.99.0 and its WASM target in `rust-toolchain.toml`.
|
|
641
|
+
The Unicode integration tests also require Poppler's `pdftotext` (`brew install
|
|
642
|
+
poppler` on macOS or `apt-get install poppler-utils` on Debian/Ubuntu).
|
|
580
643
|
|
|
581
644
|
```sh
|
|
582
645
|
npm ci
|
|
@@ -596,11 +659,12 @@ the tarball; it does not publish. Install locally using
|
|
|
596
659
|
|
|
597
660
|
The pinned Stylo source in `vendor/stylo` enables paged-media properties in the
|
|
598
661
|
Servo build. `vendor/krilla` adds custom XMP schema support and independent
|
|
599
|
-
modification dates. `vendor/
|
|
600
|
-
|
|
662
|
+
modification dates. `vendor/blitz-paint` exposes source layouts in paint order
|
|
663
|
+
so Unicode mappings retain each run's identity. `vendor/README.md` records the
|
|
664
|
+
patches; the sources and licenses are included in the npm archive.
|
|
601
665
|
|
|
602
666
|
`bun test` exercises the compiled module through its public package export. Tests
|
|
603
|
-
extract Unicode with PDF.js and inspect embedded fonts, vector paths, absence
|
|
667
|
+
extract Unicode with PDF.js and Poppler and inspect embedded fonts, vector paths, absence
|
|
604
668
|
of page images, dimensions, pagination, assets, media queries, and error recovery.
|
|
605
669
|
For browser verification, run `npm run test:browser` and open
|
|
606
670
|
`http://127.0.0.1:4173`. CI builds WASM, runs Bun and Node tests, validates the
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -20,6 +20,8 @@ independent modification dates; its source and MIT/Apache-2.0 licenses are in
|
|
|
20
20
|
`vendor/krilla`. Blitz's DOM crate is patched for fractional PDF geometry,
|
|
21
21
|
table-cell sizing/spacing, anonymous table wrappers, and paragraph margin
|
|
22
22
|
collapse; its source and MIT/Apache-2.0 licenses are in `vendor/blitz-dom`.
|
|
23
|
+
Blitz's paint crate exposes source-layout notifications for Unicode PDF text;
|
|
24
|
+
its source and MIT/Apache-2.0 licenses are in `vendor/blitz-paint`.
|
|
23
25
|
`vendor/README.md` lists these patches. Other dependencies are used without
|
|
24
26
|
source modifications.
|
|
25
27
|
|
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
|
|
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":"
|
|
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, {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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,
|
|
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
|
package/dist/browser.d.ts.map
CHANGED
|
@@ -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,
|
|
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(
|
|
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
|
package/dist/browser.js.map
CHANGED
|
@@ -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,
|
|
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 @@
|
|
|
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
|
package/dist/node.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"
|
|
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(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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,
|
|
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"}
|
package/dist/render.d.ts
ADDED
|
@@ -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 @@
|
|
|
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
|
package/dist/wasm.js.map
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/dist/worker.d.ts
ADDED
|
@@ -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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitz-pdf",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Render HTML and CSS to PDF with Blitz and WebAssembly in Node.js, Bun, and browsers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
"engines": {
|
|
16
16
|
"node": ">=20"
|
|
17
17
|
},
|
|
18
|
-
"sideEffects":
|
|
18
|
+
"sideEffects": [
|
|
19
|
+
"./dist/worker.js",
|
|
20
|
+
"./dist/node-worker.js"
|
|
21
|
+
],
|
|
19
22
|
"main": "./dist/node.js",
|
|
20
23
|
"module": "./dist/browser.js",
|
|
21
24
|
"types": "./dist/node.d.ts",
|