@lpdfio/lpdf 0.31.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/browser.js CHANGED
@@ -66,6 +66,19 @@ var LpdfEngine = class {
66
66
  const len1 = WASM_VECTOR_LEN;
67
67
  wasm.lpdfengine_load_markdown_styles(this.__wbg_ptr, ptr0, len0, ptr1, len1);
68
68
  }
69
+ /**
70
+ * Register the bytes of an ICC colour profile, for the `<profile>` of a document's `<assets>` whose `ref`, or with
71
+ * no ref whose name, is `name`: the press profile a PDF/X document names in `<output profile>`.
72
+ * @param {string} name
73
+ * @param {Uint8Array} bytes
74
+ */
75
+ load_profile(name, bytes) {
76
+ const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
77
+ const len0 = WASM_VECTOR_LEN;
78
+ const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
79
+ const len1 = WASM_VECTOR_LEN;
80
+ wasm.lpdfengine_load_profile(this.__wbg_ptr, ptr0, len0, ptr1, len1);
81
+ }
69
82
  /**
70
83
  * @param {string} license_key
71
84
  */
@@ -221,6 +234,20 @@ var LpdfEngine = class {
221
234
  const len0 = WASM_VECTOR_LEN;
222
235
  wasm.lpdfengine_set_font_metrics(this.__wbg_ptr, ptr0, len0);
223
236
  }
237
+ /**
238
+ * Set the memory a render may allocate, in megabytes: 1024 when it isn't set. A render that needs more stops
239
+ * with an error that names the cap. What the engine holds before the render, such as its loaded fonts, doesn't
240
+ * count.
241
+ *
242
+ * Returns an error when `mb` is 0 or above 4096, the most 32-bit WebAssembly addresses.
243
+ * @param {number} mb
244
+ */
245
+ set_max_memory_mb(mb) {
246
+ const ret = wasm.lpdfengine_set_max_memory_mb(this.__wbg_ptr, mb);
247
+ if (ret[1]) {
248
+ throw takeFromExternrefTable0(ret[0]);
249
+ }
250
+ }
224
251
  /**
225
252
  * Set the current Unix timestamp (seconds) for license expiry checking.
226
253
  * Must be called before `render_pdf` when using a time-limited token.
@@ -230,6 +257,32 @@ var LpdfEngine = class {
230
257
  set_now(unix) {
231
258
  wasm.lpdfengine_set_now(this.__wbg_ptr, unix);
232
259
  }
260
+ /**
261
+ * Draw PNG stamps over the pages of an existing PDF, and return the file with them added as an incremental
262
+ * update: the input, byte for byte, then the images and the pages they change. The original bytes stay as they
263
+ * were, so an owner password and its permissions stay, and so does a digital signature's revision.
264
+ *
265
+ * `stamps` is a JSON list of stamps, each with an `image`, the name of a PNG loaded with `load_image`, a `page`
266
+ * scope, a box (`x`, `y`, `anchor`, `width`, `height`, placed as a layer element is) and how the image sits in it
267
+ * (`align`, `justify`, `scale`, `max-grow`). Without a valid license key, each stamped page gets the attribution
268
+ * line of a render in its top-right corner.
269
+ * @param {Uint8Array} pdf
270
+ * @param {string} stamps
271
+ * @returns {Uint8Array}
272
+ */
273
+ stamp(pdf, stamps) {
274
+ const ptr0 = passArray8ToWasm0(pdf, wasm.__wbindgen_malloc);
275
+ const len0 = WASM_VECTOR_LEN;
276
+ const ptr1 = passStringToWasm0(stamps, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
277
+ const len1 = WASM_VECTOR_LEN;
278
+ const ret = wasm.lpdfengine_stamp(this.__wbg_ptr, ptr0, len0, ptr1, len1);
279
+ if (ret[3]) {
280
+ throw takeFromExternrefTable0(ret[2]);
281
+ }
282
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
283
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
284
+ return v3;
285
+ }
233
286
  };
234
287
  if (Symbol.dispose) LpdfEngine.prototype[Symbol.dispose] = LpdfEngine.prototype.free;
235
288
  function check_license(token, now_unix) {
@@ -252,6 +305,11 @@ function __wbg_get_imports() {
252
305
  __wbg___wbindgen_throw_6b64449b9b9ed33c: function(arg0, arg1) {
253
306
  throw new Error(getStringFromWasm0(arg0, arg1));
254
307
  },
308
+ __wbg_getRandomValues_cc7f052a444bb2ce: function() {
309
+ return handleError(function(arg0, arg1) {
310
+ globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
311
+ }, arguments);
312
+ },
255
313
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
256
314
  const ret = getStringFromWasm0(arg0, arg1);
257
315
  return ret;
@@ -274,6 +332,11 @@ function __wbg_get_imports() {
274
332
  var LpdfEngineFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {
275
333
  }, unregister: () => {
276
334
  } } : new FinalizationRegistry((ptr) => wasm.__wbg_lpdfengine_free(ptr >>> 0, 1));
335
+ function addToExternrefTable0(obj) {
336
+ const idx = wasm.__externref_table_alloc();
337
+ wasm.__wbindgen_externrefs.set(idx, obj);
338
+ return idx;
339
+ }
277
340
  function getArrayU8FromWasm0(ptr, len) {
278
341
  ptr = ptr >>> 0;
279
342
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
@@ -289,6 +352,14 @@ function getUint8ArrayMemory0() {
289
352
  }
290
353
  return cachedUint8ArrayMemory0;
291
354
  }
355
+ function handleError(f, args) {
356
+ try {
357
+ return f.apply(this, args);
358
+ } catch (e) {
359
+ const idx = addToExternrefTable0(e);
360
+ wasm.__wbindgen_exn_store(idx);
361
+ }
362
+ }
292
363
  function isLikeNone(x) {
293
364
  return x === void 0 || x === null;
294
365
  }
@@ -422,6 +493,15 @@ async function __wbg_init(module_or_path) {
422
493
  }
423
494
 
424
495
  // src/_shared.ts
496
+ var DEFAULT_MAX_MEMORY_MB = 1024;
497
+ var MAX_MEMORY_MB = 4096;
498
+ function maxMemoryMb(value) {
499
+ if (value === void 0) return DEFAULT_MAX_MEMORY_MB;
500
+ if (!Number.isInteger(value) || value < 1 || value > MAX_MEMORY_MB) {
501
+ throw new RangeError(`maxMemoryMb must be a whole number of megabytes from 1 to ${MAX_MEMORY_MB}, not ${value}`);
502
+ }
503
+ return value;
504
+ }
425
505
  var ENTROPY_BYTES = 32;
426
506
  function encryptionArguments(options, randomBytes) {
427
507
  const hasPassword = options.userPassword !== void 0 || options.ownerPassword !== void 0;
@@ -433,6 +513,123 @@ function encryptionArguments(options, randomBytes) {
433
513
  ];
434
514
  }
435
515
 
516
+ // src/render-error.ts
517
+ var LpdfRenderError = class extends Error {
518
+ constructor(message, cause) {
519
+ super(message);
520
+ this.name = "LpdfRenderError";
521
+ if (cause !== void 0) this.cause = cause;
522
+ }
523
+ };
524
+
525
+ // src/render-queue.ts
526
+ var DEFAULT_TIMEOUT = 5;
527
+ var MAX_DELAY_MS = 2 ** 31 - 1;
528
+ function renderTimeout(timeout) {
529
+ if (timeout === void 0) return DEFAULT_TIMEOUT;
530
+ if (!Number.isFinite(timeout) || timeout < 0) {
531
+ throw new RangeError(`timeout must be a number of seconds, 0 for no limit, not ${timeout}`);
532
+ }
533
+ return timeout;
534
+ }
535
+ function seconds(count) {
536
+ return count === 1 ? "1 second" : `${count} seconds`;
537
+ }
538
+ var RenderQueue = class {
539
+ constructor(_start) {
540
+ this._start = _start;
541
+ this._waiting = [];
542
+ }
543
+ /**
544
+ * Renders `job` once the renders before it have ended. Its timeout counts from when it starts.
545
+ *
546
+ * @param timeout - The seconds it may run, 0 for no limit.
547
+ * @returns The PDF; rejects with an `LpdfRenderError` when the engine refuses the document or the render runs
548
+ * past its timeout.
549
+ */
550
+ render(job, timeout) {
551
+ return new Promise((resolve, reject) => {
552
+ this._waiting.push({ job, timeout, resolve, reject });
553
+ this._next();
554
+ });
555
+ }
556
+ _next() {
557
+ if (this._running) return;
558
+ const pending = this._waiting.shift();
559
+ if (!pending) {
560
+ this._worker?.hold?.(false);
561
+ return;
562
+ }
563
+ this._running = pending;
564
+ try {
565
+ const worker = this._worker ??= this._startWorker();
566
+ worker.hold?.(true);
567
+ if (pending.timeout > 0) {
568
+ pending.timer = setTimeout(() => this._timedOut(pending), Math.min(pending.timeout * 1e3, MAX_DELAY_MS));
569
+ }
570
+ worker.post(pending.job);
571
+ } catch (e) {
572
+ this._dropWorker();
573
+ this._settle({ error: `The render worker failed: ${e instanceof Error ? e.message : String(e)}`, broken: true });
574
+ }
575
+ }
576
+ _startWorker() {
577
+ const worker = this._start({
578
+ replied: (reply) => {
579
+ if (worker !== this._worker) return;
580
+ if ("error" in reply && reply.broken) this._dropWorker();
581
+ this._settle(reply);
582
+ },
583
+ failed: (message) => {
584
+ if (worker !== this._worker) return;
585
+ this._dropWorker();
586
+ this._settle({ error: message, broken: true });
587
+ }
588
+ });
589
+ return worker;
590
+ }
591
+ _dropWorker() {
592
+ this._worker?.terminate();
593
+ this._worker = void 0;
594
+ }
595
+ _settle(reply) {
596
+ const pending = this._running;
597
+ if (!pending) return;
598
+ this._running = void 0;
599
+ clearTimeout(pending.timer);
600
+ if ("pdf" in reply) {
601
+ pending.resolve(reply.pdf);
602
+ } else {
603
+ pending.reject(new LpdfRenderError(reply.error, reply.cause));
604
+ }
605
+ this._next();
606
+ }
607
+ _timedOut(pending) {
608
+ if (pending !== this._running) return;
609
+ this._dropWorker();
610
+ this._settle({ error: `The render timed out after ${seconds(pending.timeout)}.`, broken: true });
611
+ }
612
+ };
613
+
614
+ // src/stamp.ts
615
+ function stampRequest(stamps) {
616
+ const images = /* @__PURE__ */ new Map();
617
+ const names = /* @__PURE__ */ new Map();
618
+ const list = stamps.map(({ image, maxGrow, ...rest }, i) => {
619
+ if (!(image instanceof Uint8Array)) {
620
+ throw new TypeError(`stamp ${i + 1}: image must be the PNG's bytes, a Uint8Array`);
621
+ }
622
+ let name = names.get(image);
623
+ if (name === void 0) {
624
+ name = `stamp-${names.size}`;
625
+ names.set(image, name);
626
+ images.set(name, image);
627
+ }
628
+ return { ...rest, image: name, ...maxGrow === void 0 ? {} : { "max-grow": maxGrow } };
629
+ });
630
+ return { stamps: JSON.stringify(list), images };
631
+ }
632
+
436
633
  // src/constants.ts
437
634
  var FieldType = {
438
635
  Text: "text",
@@ -445,7 +642,8 @@ var Pin = {
445
642
  Top: "top",
446
643
  Bottom: "bottom",
447
644
  Left: "left",
448
- Right: "right"
645
+ Right: "right",
646
+ Inset: "inset"
449
647
  };
450
648
  var Orientation = {
451
649
  Portrait: "portrait",
@@ -459,6 +657,10 @@ var FootnoteCounter = {
459
657
  Section: "section",
460
658
  Document: "document"
461
659
  };
660
+ var ColumnFill = {
661
+ Auto: "auto",
662
+ Balance: "balance"
663
+ };
462
664
  var Cipher = {
463
665
  Aes256: "aes-256",
464
666
  Rc4128: "rc4-128"
@@ -512,11 +714,52 @@ function nowUnix() {
512
714
  function secureRandomBytes(count) {
513
715
  return crypto.getRandomValues(new Uint8Array(count));
514
716
  }
515
- async function initLpdf(wasmSource, licenseKey = "") {
516
- await __wbg_init(wasmSource);
717
+ async function compileEngine(source) {
718
+ if (source instanceof WebAssembly.Module) return source;
719
+ const from = source ?? new URL("lpdf_bg.wasm", import.meta.url);
720
+ if (typeof from === "string" || from instanceof URL || from instanceof Request) {
721
+ return compileResponse(await fetch(from));
722
+ }
723
+ if (from instanceof Response) return compileResponse(from);
724
+ return WebAssembly.compile(from);
725
+ }
726
+ async function compileResponse(response) {
727
+ if (!response.ok) {
728
+ throw new Error(`The engine could not be loaded from ${response.url}: ${response.status} ${response.statusText}`);
729
+ }
730
+ if (response.headers.get("Content-Type")?.startsWith("application/wasm")) {
731
+ return WebAssembly.compileStreaming(response);
732
+ }
733
+ return WebAssembly.compile(await response.arrayBuffer());
734
+ }
735
+ var renderWorkerUrl;
736
+ function startBrowserWorker(module, events) {
737
+ renderWorkerUrl ??= URL.createObjectURL(new Blob(['"use strict";\n(() => {\n // wasm/lpdf-web.js\n var import_meta = {};\n var LpdfEngine = class {\n __destroy_into_raw() {\n const ptr = this.__wbg_ptr;\n this.__wbg_ptr = 0;\n LpdfEngineFinalization.unregister(this);\n return ptr;\n }\n free() {\n const ptr = this.__destroy_into_raw();\n wasm.__wbg_lpdfengine_free(ptr, 0);\n }\n /**\n * Register the bytes of a file a document carries, for the `<file>` of its `<attachments>` whose `ref`, or with\n * no ref whose name, is `name`. The PDF carries them as they are.\n * @param {string} name\n * @param {Uint8Array} bytes\n */\n load_file(name, bytes) {\n const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);\n const len1 = WASM_VECTOR_LEN;\n wasm.lpdfengine_load_file(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n }\n /**\n * Register raw font bytes (TTF/OTF) for a custom font name.\n * Call this once per font before calling `render_pdf`.\n * Glyph advance-width metrics are extracted automatically from the font\n * bytes so the layout engine can measure text accurately \u2014 no separate\n * `set_font_metrics` call is required.\n * @param {string} name\n * @param {Uint8Array} bytes\n */\n load_font(name, bytes) {\n const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);\n const len1 = WASM_VECTOR_LEN;\n wasm.lpdfengine_load_font(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n }\n /**\n * Register raw image bytes (JPEG or PNG) for an image name.\n * Call this for every image referenced by `<img name="\u2026">` nodes.\n * @param {string} name\n * @param {Uint8Array} bytes\n */\n load_image(name, bytes) {\n const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);\n const len1 = WASM_VECTOR_LEN;\n wasm.lpdfengine_load_image(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n }\n /**\n * Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the\n * `src` that names it. The engine reads no files: call this once for every `<markdown-styles src="\u2026">`\n * of the document before `render_pdf`, as `load_font` is called for a font.\n * @param {string} src\n * @param {string} xml\n */\n load_markdown_styles(src, xml) {\n const ptr0 = passStringToWasm0(src, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passStringToWasm0(xml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len1 = WASM_VECTOR_LEN;\n wasm.lpdfengine_load_markdown_styles(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n }\n /**\n * Register the bytes of an ICC colour profile, for the `<profile>` of a document\'s `<assets>` whose `ref`, or with\n * no ref whose name, is `name`: the press profile a PDF/X document names in `<output profile>`.\n * @param {string} name\n * @param {Uint8Array} bytes\n */\n load_profile(name, bytes) {\n const ptr0 = passStringToWasm0(name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);\n const len1 = WASM_VECTOR_LEN;\n wasm.lpdfengine_load_profile(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n }\n /**\n * @param {string} license_key\n */\n constructor(license_key) {\n const ptr0 = passStringToWasm0(license_key, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_new(ptr0, len0);\n this.__wbg_ptr = ret >>> 0;\n LpdfEngineFinalization.register(this, this.__wbg_ptr, this);\n return this;\n }\n /**\n * @param {string} xml\n * @returns {string}\n */\n render(xml) {\n let deferred2_0;\n let deferred2_1;\n try {\n const ptr0 = passStringToWasm0(xml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_render(this.__wbg_ptr, ptr0, len0);\n deferred2_0 = ret[0];\n deferred2_1 = ret[1];\n return getStringFromWasm0(ret[0], ret[1]);\n } finally {\n wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);\n }\n }\n /**\n * Render `xml` to binary PDF bytes.\n *\n * Any custom fonts referenced in `<font src="\u2026">` declarations must have\n * their bytes registered via `load_font` before calling this method.\n *\n * `json_data` is an optional JSON string used to resolve `data-*`\n * attributes in the template. Pass `None` (or `null` / `undefined` from\n * JavaScript) to render the template with its inline fallback content.\n *\n * The rest is for a document that asks for encryption in its `<output>`, which sets the cipher and\n * the permissions: the passwords, which the template never holds, and `entropy`, at least 32 random\n * bytes from the host\'s secure generator for AES-256. A document that asks for encryption needs an\n * owner password, or `skip_encryption` to render it unencrypted, as a preview does; passwords for a\n * document that doesn\'t ask for it are an error, and so are passwords with `skip_encryption`.\n * @param {string} xml\n * @param {string | null | undefined} json_data\n * @param {string | null | undefined} user_password\n * @param {string | null | undefined} owner_password\n * @param {boolean} skip_encryption\n * @param {Uint8Array} entropy\n * @returns {Uint8Array}\n */\n render_pdf(xml, json_data, user_password, owner_password, skip_encryption, entropy) {\n const ptr0 = passStringToWasm0(xml, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n var ptr1 = isLikeNone(json_data) ? 0 : passStringToWasm0(json_data, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n var len1 = WASM_VECTOR_LEN;\n var ptr2 = isLikeNone(user_password) ? 0 : passStringToWasm0(user_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n var len2 = WASM_VECTOR_LEN;\n var ptr3 = isLikeNone(owner_password) ? 0 : passStringToWasm0(owner_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n var len3 = WASM_VECTOR_LEN;\n const ptr4 = passArray8ToWasm0(entropy, wasm.__wbindgen_malloc);\n const len4 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_render_pdf(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, skip_encryption, ptr4, len4);\n if (ret[3]) {\n throw takeFromExternrefTable0(ret[2]);\n }\n var v6 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n return v6;\n }\n /**\n * @param {string} json\n * @returns {string}\n */\n render_tree(json) {\n let deferred2_0;\n let deferred2_1;\n try {\n const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_render_tree(this.__wbg_ptr, ptr0, len0);\n deferred2_0 = ret[0];\n deferred2_1 = ret[1];\n return getStringFromWasm0(ret[0], ret[1]);\n } finally {\n wasm.__wbindgen_free(deferred2_0, deferred2_1, 1);\n }\n }\n /**\n * Render a JSON kit-tree document to PDF bytes.\n *\n * This is the JSON counterpart of `render_pdf`. The Node adapter uses it\n * when an `LpdfDocument` Kit tree is passed to `renderPdf()`, avoiding an\n * intermediate XML serialisation step. PHP, Python, and .NET adapters also\n * use this entry point.\n *\n * The passwords, `skip_encryption` and `entropy` are those of `render_pdf`, for a document whose\n * `output` asks for encryption.\n * @param {string} json\n * @param {string | null | undefined} user_password\n * @param {string | null | undefined} owner_password\n * @param {boolean} skip_encryption\n * @param {Uint8Array} entropy\n * @returns {Uint8Array}\n */\n render_tree_pdf(json, user_password, owner_password, skip_encryption, entropy) {\n const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n var ptr1 = isLikeNone(user_password) ? 0 : passStringToWasm0(user_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n var len1 = WASM_VECTOR_LEN;\n var ptr2 = isLikeNone(owner_password) ? 0 : passStringToWasm0(owner_password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n var len2 = WASM_VECTOR_LEN;\n const ptr3 = passArray8ToWasm0(entropy, wasm.__wbindgen_malloc);\n const len3 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_render_tree_pdf(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2, skip_encryption, ptr3, len3);\n if (ret[3]) {\n throw takeFromExternrefTable0(ret[2]);\n }\n var v5 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n return v5;\n }\n /**\n * Set an optional ISO 8601 creation timestamp (e.g. `"2024-06-01T12:00:00"`, `"2024-06-01T12:00:00.000Z"` or\n * `"2024-06-01T12:00:00+01:00"`). When provided, written as `/CreationDate` in the PDF info dictionary, with\n * the precision and the time zone it was given in; a value that is not a date makes the render an error.\n * Omitting this keeps builds reproducible (no embedded timestamp).\n * @param {string} iso\n */\n set_created_on(iso) {\n const ptr0 = passStringToWasm0(iso, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n wasm.lpdfengine_set_created_on(this.__wbg_ptr, ptr0, len0);\n }\n /**\n * Inject glyph advance-width tables for custom fonts.\n *\n * Call this *before* `render_pdf` / `render` when the document uses custom\n * fonts (declared via `<font src="\u2026"`). The adapter extracts these widths\n * from the font binary and passes them as a JSON object:\n *\n * ```json\n * { "fontName": { "default": 500, "ascii": [260, 285, \u2026] } }\n * ```\n *\n * `ascii` is a 95-element array for code points 32\u2013126. `default` is used\n * for code points outside that range. All values are in 1/1000 em units.\n * @param {string} json\n */\n set_font_metrics(json) {\n const ptr0 = passStringToWasm0(json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len0 = WASM_VECTOR_LEN;\n wasm.lpdfengine_set_font_metrics(this.__wbg_ptr, ptr0, len0);\n }\n /**\n * Set the memory a render may allocate, in megabytes: 1024 when it isn\'t set. A render that needs more stops\n * with an error that names the cap. What the engine holds before the render, such as its loaded fonts, doesn\'t\n * count.\n *\n * Returns an error when `mb` is 0 or above 4096, the most 32-bit WebAssembly addresses.\n * @param {number} mb\n */\n set_max_memory_mb(mb) {\n const ret = wasm.lpdfengine_set_max_memory_mb(this.__wbg_ptr, mb);\n if (ret[1]) {\n throw takeFromExternrefTable0(ret[0]);\n }\n }\n /**\n * Set the current Unix timestamp (seconds) for license expiry checking.\n * Must be called before `render_pdf` when using a time-limited token.\n * If not set (default `0`), expiry is not checked.\n * @param {bigint} unix\n */\n set_now(unix) {\n wasm.lpdfengine_set_now(this.__wbg_ptr, unix);\n }\n /**\n * Draw PNG stamps over the pages of an existing PDF, and return the file with them added as an incremental\n * update: the input, byte for byte, then the images and the pages they change. The original bytes stay as they\n * were, so an owner password and its permissions stay, and so does a digital signature\'s revision.\n *\n * `stamps` is a JSON list of stamps, each with an `image`, the name of a PNG loaded with `load_image`, a `page`\n * scope, a box (`x`, `y`, `anchor`, `width`, `height`, placed as a layer element is) and how the image sits in it\n * (`align`, `justify`, `scale`, `max-grow`). Without a valid license key, each stamped page gets the attribution\n * line of a render in its top-right corner.\n * @param {Uint8Array} pdf\n * @param {string} stamps\n * @returns {Uint8Array}\n */\n stamp(pdf, stamps) {\n const ptr0 = passArray8ToWasm0(pdf, wasm.__wbindgen_malloc);\n const len0 = WASM_VECTOR_LEN;\n const ptr1 = passStringToWasm0(stamps, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n const len1 = WASM_VECTOR_LEN;\n const ret = wasm.lpdfengine_stamp(this.__wbg_ptr, ptr0, len0, ptr1, len1);\n if (ret[3]) {\n throw takeFromExternrefTable0(ret[2]);\n }\n var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n return v3;\n }\n };\n if (Symbol.dispose) LpdfEngine.prototype[Symbol.dispose] = LpdfEngine.prototype.free;\n function __wbg_get_imports() {\n const import0 = {\n __proto__: null,\n __wbg___wbindgen_throw_6b64449b9b9ed33c: function(arg0, arg1) {\n throw new Error(getStringFromWasm0(arg0, arg1));\n },\n __wbg_getRandomValues_cc7f052a444bb2ce: function() {\n return handleError(function(arg0, arg1) {\n globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));\n }, arguments);\n },\n __wbindgen_cast_0000000000000001: function(arg0, arg1) {\n const ret = getStringFromWasm0(arg0, arg1);\n return ret;\n },\n __wbindgen_init_externref_table: function() {\n const table = wasm.__wbindgen_externrefs;\n const offset = table.grow(4);\n table.set(0, void 0);\n table.set(offset + 0, void 0);\n table.set(offset + 1, null);\n table.set(offset + 2, true);\n table.set(offset + 3, false);\n }\n };\n return {\n __proto__: null,\n "./lpdf_bg.js": import0\n };\n }\n var LpdfEngineFinalization = typeof FinalizationRegistry === "undefined" ? { register: () => {\n }, unregister: () => {\n } } : new FinalizationRegistry((ptr) => wasm.__wbg_lpdfengine_free(ptr >>> 0, 1));\n function addToExternrefTable0(obj) {\n const idx = wasm.__externref_table_alloc();\n wasm.__wbindgen_externrefs.set(idx, obj);\n return idx;\n }\n function getArrayU8FromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);\n }\n function getStringFromWasm0(ptr, len) {\n ptr = ptr >>> 0;\n return decodeText(ptr, len);\n }\n var cachedUint8ArrayMemory0 = null;\n function getUint8ArrayMemory0() {\n if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n }\n return cachedUint8ArrayMemory0;\n }\n function handleError(f, args) {\n try {\n return f.apply(this, args);\n } catch (e) {\n const idx = addToExternrefTable0(e);\n wasm.__wbindgen_exn_store(idx);\n }\n }\n function isLikeNone(x) {\n return x === void 0 || x === null;\n }\n function passArray8ToWasm0(arg, malloc) {\n const ptr = malloc(arg.length * 1, 1) >>> 0;\n getUint8ArrayMemory0().set(arg, ptr / 1);\n WASM_VECTOR_LEN = arg.length;\n return ptr;\n }\n function passStringToWasm0(arg, malloc, realloc) {\n if (realloc === void 0) {\n const buf = cachedTextEncoder.encode(arg);\n const ptr2 = malloc(buf.length, 1) >>> 0;\n getUint8ArrayMemory0().subarray(ptr2, ptr2 + buf.length).set(buf);\n WASM_VECTOR_LEN = buf.length;\n return ptr2;\n }\n let len = arg.length;\n let ptr = malloc(len, 1) >>> 0;\n const mem = getUint8ArrayMemory0();\n let offset = 0;\n for (; offset < len; offset++) {\n const code = arg.charCodeAt(offset);\n if (code > 127) break;\n mem[ptr + offset] = code;\n }\n if (offset !== len) {\n if (offset !== 0) {\n arg = arg.slice(offset);\n }\n ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);\n const ret = cachedTextEncoder.encodeInto(arg, view);\n offset += ret.written;\n ptr = realloc(ptr, len, offset, 1) >>> 0;\n }\n WASM_VECTOR_LEN = offset;\n return ptr;\n }\n function takeFromExternrefTable0(idx) {\n const value = wasm.__wbindgen_externrefs.get(idx);\n wasm.__externref_table_dealloc(idx);\n return value;\n }\n var cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });\n cachedTextDecoder.decode();\n var MAX_SAFARI_DECODE_BYTES = 2146435072;\n var numBytesDecoded = 0;\n function decodeText(ptr, len) {\n numBytesDecoded += len;\n if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {\n cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });\n cachedTextDecoder.decode();\n numBytesDecoded = len;\n }\n return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n }\n var cachedTextEncoder = new TextEncoder();\n if (!("encodeInto" in cachedTextEncoder)) {\n cachedTextEncoder.encodeInto = function(arg, view) {\n const buf = cachedTextEncoder.encode(arg);\n view.set(buf);\n return {\n read: arg.length,\n written: buf.length\n };\n };\n }\n var WASM_VECTOR_LEN = 0;\n var wasmModule;\n var wasm;\n function __wbg_finalize_init(instance, module) {\n wasm = instance.exports;\n wasmModule = module;\n cachedUint8ArrayMemory0 = null;\n wasm.__wbindgen_start();\n return wasm;\n }\n async function __wbg_load(module, imports) {\n if (typeof Response === "function" && module instanceof Response) {\n if (typeof WebAssembly.instantiateStreaming === "function") {\n try {\n return await WebAssembly.instantiateStreaming(module, imports);\n } catch (e) {\n const validResponse = module.ok && expectedResponseType(module.type);\n if (validResponse && module.headers.get("Content-Type") !== "application/wasm") {\n console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n", e);\n } else {\n throw e;\n }\n }\n }\n const bytes = await module.arrayBuffer();\n return await WebAssembly.instantiate(bytes, imports);\n } else {\n const instance = await WebAssembly.instantiate(module, imports);\n if (instance instanceof WebAssembly.Instance) {\n return { instance, module };\n } else {\n return instance;\n }\n }\n function expectedResponseType(type) {\n switch (type) {\n case "basic":\n case "cors":\n case "default":\n return true;\n }\n return false;\n }\n }\n async function __wbg_init(module_or_path) {\n if (wasm !== void 0) return wasm;\n if (module_or_path !== void 0) {\n if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n ({ module_or_path } = module_or_path);\n } else {\n console.warn("using deprecated parameters for the initialization function; pass a single object instead");\n }\n }\n if (module_or_path === void 0) {\n module_or_path = new URL("lpdf_bg.wasm", import_meta.url);\n }\n const imports = __wbg_get_imports();\n if (typeof module_or_path === "string" || typeof Request === "function" && module_or_path instanceof Request || typeof URL === "function" && module_or_path instanceof URL) {\n module_or_path = fetch(module_or_path);\n }\n const { instance, module } = await __wbg_load(await module_or_path, imports);\n return __wbg_finalize_init(instance, module);\n }\n\n // src/render-error.ts\n var ENGINE_CRASHED = "The engine crashed during the render. This is a bug in Lpdf, or the render ran out of memory before its cap stopped it: please report it with the document at https://github.com/lpdfio/lpdf/issues.";\n\n // src/render-job.ts\n function runRenderJob(createEngine, job) {\n let engine;\n let reply;\n try {\n engine = createEngine(job.licenseKey);\n engine.set_now(job.now);\n engine.set_max_memory_mb(job.maxMemoryMb);\n if (job.createdOn) engine.set_created_on(job.createdOn);\n for (const [name, bytes] of job.fonts) engine.load_font(name, bytes);\n for (const [name, bytes] of job.images) engine.load_image(name, bytes);\n for (const [name, bytes] of job.files) engine.load_file(name, bytes);\n for (const [name, bytes] of job.profiles) engine.load_profile(name, bytes);\n for (const [src, text] of job.markdownStyles) engine.load_markdown_styles(src, text);\n const { document } = job;\n const pdf = "xml" in document ? engine.render_pdf(document.xml, document.data, ...job.encryption) : "tree" in document ? engine.render_tree_pdf(document.tree, ...job.encryption) : engine.stamp(document.pdf, document.stamps);\n reply = { pdf };\n } catch (e) {\n const crashed = e instanceof WebAssembly.RuntimeError || e instanceof RangeError;\n reply = crashed ? { error: ENGINE_CRASHED, broken: true, cause: `${e.name}: ${e.message}` } : { error: e instanceof Error ? e.message : String(e), broken: false };\n }\n if ("pdf" in reply || !reply.broken) {\n try {\n engine?.free();\n } catch {\n if ("error" in reply) reply = { ...reply, broken: true };\n }\n }\n return reply;\n }\n function transferList(reply) {\n if (!("pdf" in reply)) return [];\n const { buffer, byteLength } = reply.pdf;\n return buffer instanceof ArrayBuffer && buffer.byteLength === byteLength ? [buffer] : [];\n }\n\n // src/browser-worker.ts\n var ready;\n self.onmessage = async (event) => {\n const message = event.data;\n if ("module" in message) {\n const loading = __wbg_init({ module_or_path: message.module });\n loading.catch(() => void 0);\n ready = loading;\n return;\n }\n let reply;\n try {\n if (!ready) throw new Error("the worker was sent no engine");\n await ready;\n } catch (e) {\n reply = { error: `The engine did not load: ${e instanceof Error ? e.message : String(e)}`, broken: true };\n self.postMessage(reply);\n return;\n }\n try {\n reply = runRenderJob((licenseKey) => new LpdfEngine(licenseKey), message);\n } catch (e) {\n reply = { error: e instanceof Error ? e.message : String(e), broken: true };\n }\n self.postMessage(reply, { transfer: transferList(reply) });\n };\n})();\n'], { type: "text/javascript" }));
738
+ const worker = new Worker(renderWorkerUrl, { name: "lpdf-render" });
739
+ worker.onmessage = (event) => events.replied(event.data);
740
+ worker.onerror = (event) => {
741
+ event.preventDefault();
742
+ events.failed(
743
+ `The render worker failed${event.message ? `: ${event.message}` : ""}. A page with a Content-Security-Policy must allow blob: in worker-src for it.`
744
+ );
745
+ };
746
+ worker.onmessageerror = () => events.failed("A reply of the render worker could not be read.");
747
+ worker.postMessage({ module });
748
+ return {
749
+ post: (job) => worker.postMessage(job),
750
+ terminate: () => worker.terminate()
751
+ };
752
+ }
753
+ async function initLpdf(wasmSource, licenseKey = "", options = {}) {
754
+ const timeout = renderTimeout(options.timeout);
755
+ const memory = maxMemoryMb(options.maxMemoryMb);
756
+ const module = await compileEngine(wasmSource);
757
+ await __wbg_init({ module_or_path: module });
758
+ const queue = new RenderQueue((events) => startBrowserWorker(module, events));
517
759
  const fontMap = /* @__PURE__ */ new Map();
518
760
  const imageMap = /* @__PURE__ */ new Map();
519
761
  const fileMap = /* @__PURE__ */ new Map();
762
+ const profileMap = /* @__PURE__ */ new Map();
520
763
  const markdownStyles = /* @__PURE__ */ new Map();
521
764
  return {
522
765
  loadFont(name, bytes) {
@@ -528,6 +771,9 @@ async function initLpdf(wasmSource, licenseKey = "") {
528
771
  loadFile(name, bytes) {
529
772
  fileMap.set(name, bytes);
530
773
  },
774
+ loadProfile(name, bytes) {
775
+ profileMap.set(name, bytes);
776
+ },
531
777
  loadMarkdownStyles(src, text) {
532
778
  markdownStyles.set(src, text);
533
779
  },
@@ -535,45 +781,48 @@ async function initLpdf(wasmSource, licenseKey = "") {
535
781
  return JSON.parse(check_license(key ?? licenseKey, nowUnix()));
536
782
  },
537
783
  async render(input, callOptions = {}) {
538
- const engine = new LpdfEngine(licenseKey);
539
- engine.set_now(nowUnix());
540
- for (const [name, bytes] of fontMap) {
541
- engine.load_font(name, bytes);
542
- }
543
- for (const [name, bytes] of imageMap) {
544
- engine.load_image(name, bytes);
545
- }
546
- for (const [name, bytes] of fileMap) {
547
- engine.load_file(name, bytes);
548
- }
549
- for (const [src, text] of markdownStyles) {
550
- engine.load_markdown_styles(src, text);
551
- }
552
- if (callOptions.createdOn) {
553
- engine.set_created_on(callOptions.createdOn);
554
- }
555
- const encryption = encryptionArguments(callOptions, secureRandomBytes);
556
- let pdf;
557
- try {
558
- if (typeof input === "string") {
559
- const dataJson = callOptions.data != null ? JSON.stringify(callOptions.data) : null;
560
- pdf = engine.render_pdf(input, dataJson, ...encryption);
561
- } else {
562
- pdf = engine.render_tree_pdf(JSON.stringify(input), ...encryption);
563
- }
564
- } finally {
565
- engine.free();
566
- }
567
- return pdf;
784
+ const job = {
785
+ licenseKey,
786
+ now: nowUnix(),
787
+ maxMemoryMb: memory,
788
+ createdOn: callOptions.createdOn,
789
+ fonts: new Map(fontMap),
790
+ images: new Map(imageMap),
791
+ files: new Map(fileMap),
792
+ profiles: new Map(profileMap),
793
+ markdownStyles: new Map(markdownStyles),
794
+ document: typeof input === "string" ? { xml: input, data: callOptions.data != null ? JSON.stringify(callOptions.data) : null } : { tree: JSON.stringify(input) },
795
+ encryption: encryptionArguments(callOptions, secureRandomBytes)
796
+ };
797
+ return queue.render(job, timeout);
798
+ },
799
+ async stamp(pdf, stamps) {
800
+ const { stamps: json, images } = stampRequest(stamps);
801
+ const job = {
802
+ licenseKey,
803
+ now: nowUnix(),
804
+ maxMemoryMb: memory,
805
+ createdOn: void 0,
806
+ fonts: /* @__PURE__ */ new Map(),
807
+ images,
808
+ files: /* @__PURE__ */ new Map(),
809
+ profiles: /* @__PURE__ */ new Map(),
810
+ markdownStyles: /* @__PURE__ */ new Map(),
811
+ document: { pdf, stamps: json },
812
+ encryption: [null, null, false, new Uint8Array()]
813
+ };
814
+ return queue.render(job, timeout);
568
815
  }
569
816
  };
570
817
  }
571
818
  export {
572
819
  BuiltinFont,
573
820
  Cipher,
821
+ ColumnFill,
574
822
  FieldType,
575
823
  FileRelationship,
576
824
  FootnoteCounter,
825
+ LpdfRenderError,
577
826
  NoAttr,
578
827
  Orientation,
579
828
  PageScope,
@@ -13,6 +13,7 @@ export declare const Pin: {
13
13
  readonly Bottom: "bottom";
14
14
  readonly Left: "left";
15
15
  readonly Right: "right";
16
+ readonly Inset: "inset";
16
17
  };
17
18
  export type Pin = (typeof Pin)[keyof typeof Pin];
18
19
  /** The values of the `orientation` attribute of a document or a section. */
@@ -33,6 +34,12 @@ export declare const FootnoteCounter: {
33
34
  readonly Document: "document";
34
35
  };
35
36
  export type FootnoteCounter = (typeof FootnoteCounter)[keyof typeof FootnoteCounter];
37
+ /** The values of the `column-fill` attribute of a section: how the columns of its last page fill. */
38
+ export declare const ColumnFill: {
39
+ readonly Auto: "auto";
40
+ readonly Balance: "balance";
41
+ };
42
+ export type ColumnFill = (typeof ColumnFill)[keyof typeof ColumnFill];
36
43
  /** The values of the `encrypt` attribute of the output: the cipher the PDF is encrypted with. */
37
44
  export declare const Cipher: {
38
45
  readonly Aes256: "aes-256";
package/dist/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Generated from lpdf.xsd by scripts/gen-sdk-api.mjs.
3
3
  // Do not edit: change the schema and run `make gen-sdk-api`.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.PageScope = exports.BuiltinFont = exports.FileRelationship = exports.Permission = exports.Cipher = exports.FootnoteCounter = exports.SectionType = exports.Orientation = exports.Pin = exports.FieldType = void 0;
5
+ exports.PageScope = exports.BuiltinFont = exports.FileRelationship = exports.Permission = exports.Cipher = exports.ColumnFill = exports.FootnoteCounter = exports.SectionType = exports.Orientation = exports.Pin = exports.FieldType = void 0;
6
6
  /** The values of the `type` attribute of a field. */
7
7
  exports.FieldType = {
8
8
  Text: 'text',
@@ -17,6 +17,7 @@ exports.Pin = {
17
17
  Bottom: 'bottom',
18
18
  Left: 'left',
19
19
  Right: 'right',
20
+ Inset: 'inset',
20
21
  };
21
22
  /** The values of the `orientation` attribute of a document or a section. */
22
23
  exports.Orientation = {
@@ -33,6 +34,11 @@ exports.FootnoteCounter = {
33
34
  Section: 'section',
34
35
  Document: 'document',
35
36
  };
37
+ /** The values of the `column-fill` attribute of a section: how the columns of its last page fill. */
38
+ exports.ColumnFill = {
39
+ Auto: 'auto',
40
+ Balance: 'balance',
41
+ };
36
42
  /** The values of the `encrypt` attribute of the output: the cipher the PDF is encrypted with. */
37
43
  exports.Cipher = {
38
44
  Aes256: 'aes-256',
package/dist/engine.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import { type RenderOptions } from './_shared';
1
+ import { type EngineOptions, type RenderOptions } from './_shared';
2
2
  import type { PdfDocument } from './kit';
3
+ import { type StampAttr } from './stamp';
4
+ export { LpdfRenderError } from './render-error';
3
5
  /** How a license key stands with this build of the engine. */
4
6
  export type LicenseStatus = 'licensed' | 'no_key' | 'expired' | 'version_mismatch' | 'wrong_product' | 'unknown_key' | 'bad_signature' | 'malformed';
5
7
  /**
@@ -22,18 +24,24 @@ export interface LicenseCheck {
22
24
  /** Which key this is on its license — 1, 2, 3 in issue order. */
23
25
  key?: number;
24
26
  }
25
- /** Thrown when the lpdf engine returns a layout or parse error. */
26
- export declare class LpdfRenderError extends Error {
27
- constructor(message: string);
28
- }
29
27
  export declare class PdfEngine {
30
28
  private _licenseKey;
31
29
  private readonly _fonts;
32
30
  private readonly _images;
33
31
  private readonly _files;
32
+ private readonly _profiles;
34
33
  private readonly _markdownStyles;
34
+ private readonly _timeout;
35
+ private readonly _maxMemoryMb;
35
36
  private _disposed;
36
- constructor();
37
+ /**
38
+ * @param options - Engine-level options: `timeout`, the seconds a render may run before it rejects with an
39
+ * `LpdfRenderError` that names the limit, 5 when left out and no limit at 0; `maxMemoryMb`, the megabytes a render
40
+ * may allocate before it rejects with an `LpdfRenderError` that names the cap, 1024 when left out.
41
+ * @throws {RangeError} when `timeout` is negative or not a finite number, or `maxMemoryMb` is not a whole number
42
+ * from 1 to 4096.
43
+ */
44
+ constructor(options?: EngineOptions);
37
45
  /**
38
46
  * Set the license key. Returns `this` for chaining.
39
47
  */
@@ -65,6 +73,12 @@ export declare class PdfEngine {
65
73
  * no ref whose name, is `name`. The PDF carries them as they are. Call before `render`. Returns `this` for chaining.
66
74
  */
67
75
  loadFile(name: string, bytes: Uint8Array): this;
76
+ /**
77
+ * Register the bytes of an ICC color profile, for the `<profile>` of the document's `<assets>` whose `ref`, or with
78
+ * no ref whose name, is `name`: the press profile a PDF/X document names in its output. Call before `render`.
79
+ * Returns `this` for chaining.
80
+ */
81
+ loadProfile(name: string, bytes: Uint8Array): this;
68
82
  /**
69
83
  * Register the text of a file of Markdown rules, the root of which is a `<markdown-styles>`, for the `src` that
70
84
  * names it, as `<markdown-styles src="…">` does. Call before `render`. Returns `this` for chaining.
@@ -77,22 +91,53 @@ export declare class PdfEngine {
77
91
  dispose(): void;
78
92
  [Symbol.dispose](): void;
79
93
  /**
80
- * Hand the engine the files of Markdown rules that a document names: the ones loaded here, and the ones read from
81
- * their `src`. A file that can't be read is left for the engine to report, naming the `src`.
94
+ * The files of Markdown rules that a document names: the ones loaded here, and the ones read from their `src`. A
95
+ * file that can't be read is left for the engine to report, naming the `src`.
96
+ */
97
+ private _markdownStylesFor;
98
+ /**
99
+ * The files the document carries: the ones loaded here, and the ones read from the `src` of a file that wasn't. A
100
+ * `src` that can't be read is an error that names the file and the path.
82
101
  */
83
- private _loadMarkdownStyles;
102
+ private _filesFor;
84
103
  /**
85
- * Hand the engine the files the document carries: the ones loaded here, and the ones read from the `src` of a file
86
- * that wasn't. A `src` that can't be read is an error that names the file and the path.
104
+ * The color profiles the document declares: the ones loaded here, and the ones read from the `src` of a profile
105
+ * that wasn't. A `src` that can't be read is an error that names the profile and the path.
87
106
  */
88
- private _loadFiles;
107
+ private _profilesFor;
89
108
  private _throwIfDisposed;
90
109
  /**
91
110
  * Render an lpdf XML string to PDF bytes (Node.js).
111
+ *
112
+ * The render runs on a worker thread, after the renders before it. It rejects with an `LpdfRenderError` when the
113
+ * engine refuses the document, when it runs past the engine's `timeout` or needs more than its `maxMemoryMb`, or
114
+ * when the engine crashes, after which the next render runs on a fresh engine.
92
115
  */
93
116
  render(input: string, callOptions?: RenderOptions): Promise<Uint8Array>;
94
117
  /**
95
- * Render a `PdfDocument` tree (built with `Pdf.document`) to PDF bytes (Node.js).
118
+ * Render a `PdfDocument` tree (built with `Pdf.document`) to PDF bytes (Node.js), on a worker thread as an XML
119
+ * string is.
96
120
  */
97
121
  render(input: PdfDocument, callOptions?: RenderOptions): Promise<Uint8Array>;
122
+ /**
123
+ * Draw PNG images over the pages of an existing PDF, and return the PDF with them (Node.js). Nothing is laid out:
124
+ * each image is drawn in its stamp's box, over the pages its `page` names.
125
+ *
126
+ * The output is the input, byte for byte, with an incremental update after it, so an owner password and its
127
+ * permissions stay, and so does a digital signature, for the revision it signed. A PDF/A file stays PDF/A. Without a
128
+ * license key each stamped page gets the attribution line in its top-right corner. A stamp covers what is under it
129
+ * and does not remove it: the text under an image can still be selected and found, so a stamp is not a redaction.
130
+ *
131
+ * The stamp runs on a worker thread, as a render does, with its `timeout` and `maxMemoryMb`. It rejects with an
132
+ * `LpdfRenderError` when the input is not a PDF, needs a password to open, or doesn't have a page a stamp names, and
133
+ * when an image is not a PNG or a stamp's options are wrong.
134
+ *
135
+ * @throws {TypeError} when a stamp's `image` is not the PNG's bytes.
136
+ */
137
+ stamp(pdf: Uint8Array, stamps: StampAttr[]): Promise<Uint8Array>;
138
+ /**
139
+ * A render of `input` with every file it needs, read here from the `src` of each font, image, file, profile and
140
+ * file of rules the document names and that wasn't loaded: the worker reads nothing itself.
141
+ */
142
+ private _job;
98
143
  }