@t4h.framework/pdf 0.3.3 → 0.4.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.
Files changed (38) hide show
  1. package/.ai/skills/framework-pdf/SKILL.md +14 -7
  2. package/CHANGELOG.md +41 -0
  3. package/README.md +4 -0
  4. package/dist/activities/RenderPDFActivity.d.ts.map +1 -1
  5. package/dist/activities/RenderPDFActivity.js +16 -11
  6. package/dist/activities/RenderPDFActivity.js.map +1 -1
  7. package/dist/helpers/document-to-element.d.ts.map +1 -1
  8. package/dist/helpers/document-to-element.js +2 -8
  9. package/dist/helpers/document-to-element.js.map +1 -1
  10. package/dist/helpers/materialize-binary.d.ts +7 -0
  11. package/dist/helpers/materialize-binary.d.ts.map +1 -0
  12. package/dist/helpers/materialize-binary.js +45 -0
  13. package/dist/helpers/materialize-binary.js.map +1 -0
  14. package/dist/helpers/materialize-document.d.ts +3 -0
  15. package/dist/helpers/materialize-document.d.ts.map +1 -0
  16. package/dist/helpers/materialize-document.js +29 -0
  17. package/dist/helpers/materialize-document.js.map +1 -0
  18. package/dist/helpers/register-fonts.d.ts +1 -0
  19. package/dist/helpers/register-fonts.d.ts.map +1 -1
  20. package/dist/helpers/register-fonts.js +33 -6
  21. package/dist/helpers/register-fonts.js.map +1 -1
  22. package/dist/helpers/render-document.d.ts +8 -0
  23. package/dist/helpers/render-document.d.ts.map +1 -0
  24. package/dist/helpers/render-document.js +54 -0
  25. package/dist/helpers/render-document.js.map +1 -0
  26. package/dist/helpers/render.d.ts +3 -0
  27. package/dist/helpers/render.d.ts.map +1 -0
  28. package/dist/helpers/render.js +19 -0
  29. package/dist/helpers/render.js.map +1 -0
  30. package/dist/tools/encrypt-pdf.d.ts +4 -1
  31. package/dist/tools/encrypt-pdf.d.ts.map +1 -1
  32. package/dist/tools/encrypt-pdf.js +31 -16
  33. package/dist/tools/encrypt-pdf.js.map +1 -1
  34. package/dist/workers/render.d.ts +14 -0
  35. package/dist/workers/render.d.ts.map +1 -0
  36. package/dist/workers/render.js +9 -0
  37. package/dist/workers/render.js.map +1 -0
  38. package/package.json +10 -7
@@ -63,12 +63,18 @@ import {
63
63
  `DocumentNode` JSON tree that is stored in the workflow history. User
64
64
  function components, fragments, arrays, and conditionals are flattened
65
65
  here; only marker components and strings remain.
66
- 2. **`run`** (activity side): fonts are registered, the `DocumentNode` tree is
67
- converted back into real `@react-pdf/renderer` elements (`Binary` image
68
- sources become `data:` URIs), rendered to a buffer, and written through
69
- **`FileSystemClaim`** at `pdf/${activityId}.pdf`. With the `encrypt`
70
- option, a password-protected copy is also written at
71
- `pdf/${activityId}-encrypted.pdf`.
66
+ 2. **`run`** (activity side): `Binary` image and font sources are read through
67
+ their claims and inlined as `data:` URIs on the calling thread, then the
68
+ resolved tree is handed to a **worker thread** (pool size
69
+ `PDF_RENDER_CONCURRENCY`, default `1`, created on first render, idle workers
70
+ unrefed) that registers fonts once per process, converts the `DocumentNode`
71
+ tree back into real `@react-pdf/renderer` elements and renders it to a
72
+ buffer. The buffer is written through **`FileSystemClaim`** at
73
+ `pdf/${activityId}.pdf`. With the `encrypt` option, a password-protected
74
+ copy (AES-128, `%PDF-1.6`) is written from the same layout at
75
+ `pdf/${activityId}-encrypted.pdf` — no second layout pass, no re-encryption
76
+ of the finished file. A render therefore blocks the event loop of the
77
+ calling process for milliseconds, not for the whole document.
72
78
  3. The activity returns the **`Binary`** the claim produced — a reference to
73
79
  the stored file, not in-memory bytes. Replay-safe by construction. With
74
80
  `encrypt`, it returns the `[original, encrypted]` pair instead, and the
@@ -277,7 +283,8 @@ const [original, encrypted] = await render(<Invoice />, {
277
283
  Test the **workflow** with `TestWorkflowEnvironment` from
278
284
  `@t4h.framework/core/testing`, mocking the single claim the render activity
279
285
  uses: `FileSystemClaim`. See the **framework-workflow-testing** skill for the
280
- harness API.
286
+ harness API. The render runs in a worker in tests too, so the first render in a
287
+ test file pays for the thread starting up (around 400 ms).
281
288
 
282
289
  ```typescript
283
290
  import { Readable } from 'node:stream'
package/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @t4h.framework/pdf
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#181](https://github.com/tech4humans-brasil/framework/pull/181) [`9449e4e`](https://github.com/tech4humans-brasil/framework/commit/9449e4e9889f42dea1d52418140f47d25dff0535) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Renders in a worker thread and encrypts through pdfkit.
8
+
9
+ Layout and writing were one uninterrupted stretch of CPU on the calling
10
+ thread, so a long document stalled every HTTP handler and queue consumer in
11
+ the process. The activity now resolves `Binary` images and fonts into data
12
+ URIs and hands the tree to a worker; an image or font with a `Binary.identity`
13
+ is materialized once per process and shared by every render that embeds it.
14
+
15
+ The encrypted copy was produced by `muhammara.recrypt` over the finished file,
16
+ a synchronous native pass quadratic in the document size. It is now written by
17
+ pdfkit while the file is produced, from the layout the first render already
18
+ computed, so the pair costs one layout. The copy is AES-128 (`%PDF-1.6`)
19
+ instead of 40-bit RC4; `ProtectionFlags` map onto the same `/P` bits, and
20
+ `muhammara` is no longer a dependency.
21
+
22
+ Embedded fonts register once per process, keyed by family, weight, style and a
23
+ digest of the file, instead of retaining a fresh copy on every render.
24
+
25
+ `@react-pdf/renderer`, `@react-pdf/render` and `pdfkit` are pinned to one
26
+ consistent set, guarded by a test that compares the shared-layout writer
27
+ byte for byte against a full render. The public API and `fs.write` output are
28
+ unchanged.
29
+
30
+ ### Patch Changes
31
+
32
+ - Updated dependencies [[`9449e4e`](https://github.com/tech4humans-brasil/framework/commit/9449e4e9889f42dea1d52418140f47d25dff0535), [`9449e4e`](https://github.com/tech4humans-brasil/framework/commit/9449e4e9889f42dea1d52418140f47d25dff0535), [`9449e4e`](https://github.com/tech4humans-brasil/framework/commit/9449e4e9889f42dea1d52418140f47d25dff0535)]:
33
+ - @t4h.framework/core@0.15.0
34
+ - @t4h.framework/fs@0.10.0
35
+
36
+ ## 0.3.4
37
+
38
+ ### Patch Changes
39
+
40
+ - Updated dependencies [[`aa72268`](https://github.com/tech4humans-brasil/framework/commit/aa72268d040a743743cac31cc14e26b8620b0e3f)]:
41
+ - @t4h.framework/core@0.14.0
42
+ - @t4h.framework/fs@0.9.4
43
+
3
44
  ## 0.3.3
4
45
 
5
46
  ### Patch Changes
package/README.md CHANGED
@@ -131,10 +131,14 @@ const pdf = await render(<Doc />, {
131
131
 
132
132
  Select variants in styles with `fontFamily`, `fontWeight` (`100–900`), and `fontStyle` (`'normal' | 'italic'`).
133
133
 
134
+ Each variant reaches the process-wide font store once, keyed by family, weight, style and the file's digest, so passing `fonts` on every render costs nothing after the first.
135
+
134
136
  ## Encryption
135
137
 
136
138
  Pass `encrypt` to also persist a password-protected copy — `render` then resolves with an `[original, encrypted]` pair (the return type narrows automatically). `password` is a bare string or `{ user, owner }`; `protection` is a `ProtectionFlags` bitmask (defaults follow the viewer; use `ProtectionPresets.ReadOnly` for view-and-print documents). Permission flags are honored by viewers, not enforced cryptographically.
137
139
 
140
+ The encrypted copy is written with pdfkit's own encryption (AES-128, PDF 1.6) from the layout the first render already produced, so neither a re-encryption pass over the finished file nor a second layout is paid for.
141
+
138
142
  ```tsx
139
143
  import { ProtectionPresets, render } from '@t4h.framework/pdf'
140
144
 
@@ -1 +1 @@
1
- {"version":3,"file":"RenderPDFActivity.d.ts","sourceRoot":"","sources":["../../src/activities/RenderPDFActivity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAIzC,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACxE,OAAO,EAAc,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,YAAY,CAAA;CACvB,GAAG,gBAAgB,CAAA;AAEpB,qBAAa,iBAAkB,SAAQ,YAAY,CACjD,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,EAC5D,cAAc,EACd,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACzB,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAC1B;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAErD,OAAO,CACZ,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,cAAc;IAQJ,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAmBpE,QAAQ,CACb,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAG7B;AAED,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,gBAAgB,GAAG;IAAE,OAAO,EAAE,iBAAiB,CAAA;CAAE,GACzD,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;AACjD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACnD,OAAO,CAAC,MAAM,CAAC,CAAA;AAClB,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"RenderPDFActivity.d.ts","sourceRoot":"","sources":["../../src/activities/RenderPDFActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAIzC,OAAO,EAAgB,KAAK,KAAK,EAAE,MAAM,8BAA8B,CAAA;AAEvE,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,OAAO,CAAC,EAAE,iBAAiB,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,YAAY,CAAA;CACvB,GAAG,gBAAgB,CAAA;AAEpB,qBAAa,iBAAkB,SAAQ,YAAY,CACjD,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,gBAAgB,CAAC,EAC5D,cAAc,EACd,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACzB,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAC1B;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAErD,OAAO,CACZ,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,cAAc;IAQJ,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAmBpE,QAAQ,CACb,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAG7B;AAED,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,gBAAgB,GAAG;IAAE,OAAO,EAAE,iBAAiB,CAAA;CAAE,GACzD,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;AACjD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GAAG;IAAE,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GACnD,OAAO,CAAC,MAAM,CAAC,CAAA;AAClB,wBAAsB,MAAM,CAC1B,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA"}
@@ -1,10 +1,10 @@
1
- import { renderToBuffer } from '@react-pdf/renderer';
2
1
  import { Binary, Claim, History, SyncActivity } from '@t4h.framework/core';
3
2
  import { FileSystemClaim } from '@t4h.framework/fs';
4
- import { documentToElement } from '../helpers/document-to-element.js';
5
3
  import { elementToDocument } from '../helpers/element-to-document.js';
6
- import { registerFonts } from '../helpers/register-fonts.js';
7
- import { encryptPDF } from '../tools/encrypt-pdf.js';
4
+ import { materializeDocument } from '../helpers/materialize-document.js';
5
+ import { resolveFonts } from '../helpers/register-fonts.js';
6
+ import { render as renderInPool } from '../helpers/render.js';
7
+ import { toDocumentEncryptionProps, } from '../tools/encrypt-pdf.js';
8
8
  export class RenderPDFActivity extends SyncActivity {
9
9
  claims = new Claim({ fs: FileSystemClaim });
10
10
  toInput(element, options) {
@@ -15,15 +15,20 @@ export class RenderPDFActivity extends SyncActivity {
15
15
  };
16
16
  }
17
17
  async run(input) {
18
- if (input.fonts)
19
- await registerFonts(input.fonts);
20
- const element = await documentToElement(input.document);
21
- const pdf = await renderToBuffer(element);
18
+ const { pdf, encrypted } = await renderInPool({
19
+ document: await materializeDocument(input.document),
20
+ fonts: input.fonts ? await resolveFonts(input.fonts) : undefined,
21
+ encryption: input.encrypt
22
+ ? toDocumentEncryptionProps(input.encrypt)
23
+ : undefined,
24
+ });
22
25
  const original = await this.claims.fs.write(`pdf/${this.id}.pdf`, pdf);
23
- if (!input.encrypt)
26
+ if (!encrypted)
24
27
  return original;
25
- const encrypted = await this.claims.fs.write(`pdf/${this.id}-encrypted.pdf`, encryptPDF(pdf, input.encrypt));
26
- return [original, encrypted];
28
+ return [
29
+ original,
30
+ await this.claims.fs.write(`pdf/${this.id}-encrypted.pdf`, encrypted),
31
+ ];
27
32
  }
28
33
  toOutput(output) {
29
34
  return output;
@@ -1 +1 @@
1
- {"version":3,"file":"RenderPDFActivity.js","sourceRoot":"","sources":["../../src/activities/RenderPDFActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAc,MAAM,8BAA8B,CAAA;AACxE,OAAO,EAAE,UAAU,EAA0B,MAAM,yBAAyB,CAAA;AAY5E,MAAM,OAAO,iBAAkB,SAAQ,YAKtC;IACkB,MAAM,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;IAErD,OAAO,CACZ,OAAqB,EACrB,OAA0B;QAE1B,OAAO;YACL,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC;YACpC,KAAK,EAAE,OAAO,EAAE,KAAK;YACrB,OAAO,EAAE,OAAO,EAAE,OAAO;SAC1B,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,KAAqB;QACpC,IAAI,KAAK,CAAC,KAAK;YAAE,MAAM,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAEjD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAEvD,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;QAEtE,IAAI,CAAC,KAAK,CAAC,OAAO;YAAE,OAAO,QAAQ,CAAA;QAEnC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAC1C,OAAO,IAAI,CAAC,EAAE,gBAAgB,EAC9B,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAC/B,CAAA;QAED,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IAC9B,CAAC;IAEM,QAAQ,CACb,MAAiC;QAEjC,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAcD,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAqB,EACrB,OAA0B;IAE1B,OAAO,MAAM,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACtE,CAAC"}
1
+ {"version":3,"file":"RenderPDFActivity.js","sourceRoot":"","sources":["../../src/activities/RenderPDFActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAGnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,EAAE,YAAY,EAAc,MAAM,8BAA8B,CAAA;AACvE,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EACL,yBAAyB,GAE1B,MAAM,yBAAyB,CAAA;AAYhC,MAAM,OAAO,iBAAkB,SAAQ,YAKtC;IACkB,MAAM,GAAG,IAAI,KAAK,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;IAErD,OAAO,CACZ,OAAqB,EACrB,OAA0B;QAE1B,OAAO;YACL,QAAQ,EAAE,iBAAiB,CAAC,OAAO,CAAC;YACpC,KAAK,EAAE,OAAO,EAAE,KAAK;YACrB,OAAO,EAAE,OAAO,EAAE,OAAO;SAC1B,CAAA;IACH,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,KAAqB;QACpC,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,YAAY,CAAC;YAC5C,QAAQ,EAAE,MAAM,mBAAmB,CAAC,KAAK,CAAC,QAAQ,CAAC;YACnD,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YAChE,UAAU,EAAE,KAAK,CAAC,OAAO;gBACvB,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,OAAO,CAAC;gBAC1C,CAAC,CAAC,SAAS;SACd,CAAC,CAAA;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAA;QAEtE,IAAI,CAAC,SAAS;YAAE,OAAO,QAAQ,CAAA;QAE/B,OAAO;YACL,QAAQ;YACR,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,gBAAgB,EAAE,SAAS,CAAC;SACtE,CAAA;IACH,CAAC;IAEM,QAAQ,CACb,MAAiC;QAEjC,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAcD,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,OAAqB,EACrB,OAA0B;IAE1B,OAAO,MAAM,OAAO,CAAC,UAAU,CAAC,iBAAiB,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACtE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"document-to-element.d.ts","sourceRoot":"","sources":["../../src/helpers/document-to-element.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAiC,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAE7E,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,mBAAmB,CAAA;AAyF1B,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAMxD"}
1
+ {"version":3,"file":"document-to-element.d.ts","sourceRoot":"","sources":["../../src/helpers/document-to-element.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAiC,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAG7E,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,mBAAmB,CAAA;AAiF1B,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAMxD"}
@@ -1,12 +1,6 @@
1
- import { buffer } from 'node:stream/consumers';
2
1
  import { Document, Image, Link, Page, Text, View } from '@react-pdf/renderer';
3
2
  import { createElement } from 'react';
4
- async function resolveImageSrc(src) {
5
- if (typeof src === 'string')
6
- return src;
7
- const data = await buffer(await src.stream());
8
- return `data:${src.contentType};base64,${data.toString('base64')}`;
9
- }
3
+ import { materializeBinary } from './materialize-binary.js';
10
4
  async function toTextChildren(children) {
11
5
  if (children === undefined)
12
6
  return [];
@@ -29,7 +23,7 @@ async function nodeToElement(node) {
29
23
  const { src, ...props } = node.props;
30
24
  return createElement(Image, {
31
25
  ...props,
32
- src: await resolveImageSrc(src),
26
+ src: await materializeBinary(src),
33
27
  });
34
28
  }
35
29
  case 'page-number': {
@@ -1 +1 @@
1
- {"version":3,"file":"document-to-element.js","sourceRoot":"","sources":["../../src/helpers/document-to-element.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document-to-element.js","sourceRoot":"","sources":["../../src/helpers/document-to-element.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Binary } from '@t4h.framework/core';
2
+ export interface MaterializeBinaryOptions {
3
+ contentType?: string;
4
+ }
5
+ export declare function toDataUrl(contentType: string, bytes: Buffer): string;
6
+ export declare function materializeBinary(src: string | Binary, { contentType }?: MaterializeBinaryOptions): Promise<string>;
7
+ //# sourceMappingURL=materialize-binary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize-binary.d.ts","sourceRoot":"","sources":["../../src/helpers/materialize-binary.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,MAAM,WAAW,wBAAwB;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAaD,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpE;AAmCD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,EAAE,WAAW,EAAE,GAAE,wBAA6B,GAC7C,OAAO,CAAC,MAAM,CAAC,CAkBjB"}
@@ -0,0 +1,45 @@
1
+ import { buffer } from 'node:stream/consumers';
2
+ const CACHE_MAX_TOTAL_SIZE_IN_BYTES = 32 * 1024 * 1024;
3
+ const cache = new Map();
4
+ let cachedSizeInBytes = 0;
5
+ export function toDataUrl(contentType, bytes) {
6
+ return `data:${contentType};base64,${bytes.toString('base64')}`;
7
+ }
8
+ function evictOldest() {
9
+ for (const [key, entry] of cache) {
10
+ if (cachedSizeInBytes <= CACHE_MAX_TOTAL_SIZE_IN_BYTES)
11
+ return;
12
+ cache.delete(key);
13
+ cachedSizeInBytes -= entry.sizeInBytes;
14
+ }
15
+ }
16
+ function remember(key, read) {
17
+ const entry = { dataUrl: read(), sizeInBytes: 0 };
18
+ cache.set(key, entry);
19
+ entry.dataUrl.then(value => {
20
+ if (cache.get(key) !== entry)
21
+ return;
22
+ entry.sizeInBytes = value.length;
23
+ cachedSizeInBytes += value.length;
24
+ evictOldest();
25
+ }, () => {
26
+ if (cache.get(key) === entry)
27
+ cache.delete(key);
28
+ });
29
+ return entry.dataUrl;
30
+ }
31
+ export async function materializeBinary(src, { contentType } = {}) {
32
+ if (typeof src === 'string')
33
+ return src;
34
+ const type = contentType ?? src.contentType;
35
+ const read = async () => toDataUrl(type, await buffer(await src.stream()));
36
+ const identity = src.identity;
37
+ if (identity === undefined)
38
+ return await read();
39
+ const key = `${type}\0${identity}`;
40
+ const cached = cache.get(key);
41
+ if (cached)
42
+ return await cached.dataUrl;
43
+ return await remember(key, read);
44
+ }
45
+ //# sourceMappingURL=materialize-binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize-binary.js","sourceRoot":"","sources":["../../src/helpers/materialize-binary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAQ9C,MAAM,6BAA6B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AAOtD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAA;AAE3C,IAAI,iBAAiB,GAAG,CAAC,CAAA;AAEzB,MAAM,UAAU,SAAS,CAAC,WAAmB,EAAE,KAAa;IAC1D,OAAO,QAAQ,WAAW,WAAW,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAA;AACjE,CAAC;AAED,SAAS,WAAW;IAClB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,iBAAiB,IAAI,6BAA6B;YAAE,OAAM;QAE9D,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAEjB,iBAAiB,IAAI,KAAK,CAAC,WAAW,CAAA;IACxC,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,IAA2B;IACxD,MAAM,KAAK,GAAe,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAA;IAE7D,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;IAErB,KAAK,CAAC,OAAO,CAAC,IAAI,CAChB,KAAK,CAAC,EAAE;QACN,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK;YAAE,OAAM;QAEpC,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,MAAM,CAAA;QAEhC,iBAAiB,IAAI,KAAK,CAAC,MAAM,CAAA;QAEjC,WAAW,EAAE,CAAA;IACf,CAAC,EACD,GAAG,EAAE;QACH,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK;YAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IACjD,CAAC,CACF,CAAA;IAED,OAAO,KAAK,CAAC,OAAO,CAAA;AACtB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,EAAE,WAAW,KAA+B,EAAE;IAE9C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAA;IAEvC,MAAM,IAAI,GAAG,WAAW,IAAI,GAAG,CAAC,WAAW,CAAA;IAE3C,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,MAAM,CAAC,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAE1E,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAA;IAE7B,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,MAAM,IAAI,EAAE,CAAA;IAE/C,MAAM,GAAG,GAAG,GAAG,IAAI,KAAK,QAAQ,EAAE,CAAA;IAElC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAE7B,IAAI,MAAM;QAAE,OAAO,MAAM,MAAM,CAAC,OAAO,CAAA;IAEvC,OAAO,MAAM,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;AAClC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { DocumentNode } from '../typings/pdf.js';
2
+ export declare function materializeDocument(document: DocumentNode): Promise<DocumentNode>;
3
+ //# sourceMappingURL=materialize-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize-document.d.ts","sourceRoot":"","sources":["../../src/helpers/materialize-document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAA;AA0BxE,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,YAAY,CAAC,CAKvB"}
@@ -0,0 +1,29 @@
1
+ import { materializeBinary } from './materialize-binary.js';
2
+ async function materializeNode(node) {
3
+ if (node.type === 'image')
4
+ return {
5
+ ...node,
6
+ props: { ...node.props, src: await materializeBinary(node.props.src) },
7
+ };
8
+ if (node.type !== 'view' || !node.children)
9
+ return node;
10
+ return {
11
+ ...node,
12
+ children: await Promise.all(node.children.map(materializeNode)),
13
+ };
14
+ }
15
+ async function materializePage(page) {
16
+ if (!page.children)
17
+ return page;
18
+ return {
19
+ ...page,
20
+ children: await Promise.all(page.children.map(materializeNode)),
21
+ };
22
+ }
23
+ export async function materializeDocument(document) {
24
+ return {
25
+ ...document,
26
+ children: await Promise.all(document.children.map(materializePage)),
27
+ };
28
+ }
29
+ //# sourceMappingURL=materialize-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"materialize-document.js","sourceRoot":"","sources":["../../src/helpers/materialize-document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAG3D,KAAK,UAAU,eAAe,CAAC,IAAa;IAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QACvB,OAAO;YACL,GAAG,IAAI;YACP,KAAK,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;SACvE,CAAA;IAEH,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAEvD,OAAO;QACL,GAAG,IAAI;QACP,QAAQ,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;KAChE,CAAA;AACH,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,IAAc;IAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE/B,OAAO;QACL,GAAG,IAAI;QACP,QAAQ,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;KAChE,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAsB;IAEtB,OAAO;QACL,GAAG,QAAQ;QACX,QAAQ,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;KACpE,CAAA;AACH,CAAC"}
@@ -10,5 +10,6 @@ export type FontVariant = {
10
10
  export type Fonts = {
11
11
  [name: string]: FontSource | readonly FontVariant[];
12
12
  };
13
+ export declare function resolveFonts(raw: Fonts): Promise<Fonts>;
13
14
  export declare function registerFonts(raw: Fonts): Promise<void>;
14
15
  //# sourceMappingURL=register-fonts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register-fonts.d.ts","sourceRoot":"","sources":["../../src/helpers/register-fonts.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAE5C,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE5E,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAExC,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,WAAW,EAAE,CAAA;CACpD,CAAA;AAQD,wBAAsB,aAAa,CAAC,GAAG,EAAE,KAAK,iBA6C7C"}
1
+ {"version":3,"file":"register-fonts.d.ts","sourceRoot":"","sources":["../../src/helpers/register-fonts.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAI5C,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AAE5E,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE3C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;AAExC,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,KAAK,GAAG;IAClB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,WAAW,EAAE,CAAA;CACpD,CAAA;AAiBD,wBAAsB,YAAY,CAAC,GAAG,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAsB7D;AAED,wBAAsB,aAAa,CAAC,GAAG,EAAE,KAAK,iBA0D7C"}
@@ -1,9 +1,28 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { buffer } from 'node:stream/consumers';
2
3
  import { Font } from '@react-pdf/renderer';
3
4
  import { Binary } from '@t4h.framework/core';
4
- function toDataUrl(data) {
5
- const bytes = Buffer.isBuffer(data) ? data : Buffer.from(data);
6
- return `data:font/ttf;base64,${bytes.toString('base64')}`;
5
+ import { materializeBinary, toDataUrl } from './materialize-binary.js';
6
+ const FONT_CONTENT_TYPE = 'font/ttf';
7
+ const registered = new Set();
8
+ function toVariantKey(family, fontWeight, fontStyle, source) {
9
+ const digest = createHash('sha256').update(source).digest('hex');
10
+ return `${family}\0${fontWeight}\0${fontStyle}\0${digest}`;
11
+ }
12
+ export async function resolveFonts(raw) {
13
+ const families = await Promise.all(Object.entries(raw ?? {}).map(async ([name, source]) => {
14
+ const variants = typeof source === 'string' || source instanceof Binary
15
+ ? [{ src: source }]
16
+ : source;
17
+ const resolved = await Promise.all(variants.map(async (variant) => ({
18
+ ...variant,
19
+ src: await materializeBinary(variant.src, {
20
+ contentType: FONT_CONTENT_TYPE,
21
+ }),
22
+ })));
23
+ return [name, resolved];
24
+ }));
25
+ return Object.fromEntries(families);
7
26
  }
8
27
  export async function registerFonts(raw) {
9
28
  const fonts = await Promise.all(Object.entries(raw ?? {}).flatMap(([name, source]) => {
@@ -26,13 +45,21 @@ export async function registerFonts(raw) {
26
45
  }));
27
46
  const families = new Map();
28
47
  for (const font of fonts) {
48
+ const fontWeight = font.weight ?? 400;
49
+ const fontStyle = font.style ?? 'normal';
50
+ const key = toVariantKey(font.name, fontWeight, fontStyle, font.src);
51
+ if (registered.has(key))
52
+ continue;
29
53
  const variants = families.get(font.name) ?? [];
30
54
  variants.push({
31
- src: typeof font.src === 'string' ? font.src : toDataUrl(font.src),
32
- fontWeight: font.weight ?? 400,
33
- fontStyle: font.style ?? 'normal',
55
+ src: typeof font.src === 'string'
56
+ ? font.src
57
+ : toDataUrl(FONT_CONTENT_TYPE, font.src),
58
+ fontWeight,
59
+ fontStyle,
34
60
  });
35
61
  families.set(font.name, variants);
62
+ registered.add(key);
36
63
  }
37
64
  for (const [family, variants] of families)
38
65
  Font.register({ family, fonts: variants });
@@ -1 +1 @@
1
- {"version":3,"file":"register-fonts.js","sourceRoot":"","sources":["../../src/helpers/register-fonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAE9C,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAkB5C,SAAS,SAAS,CAAC,IAA0B;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAE9D,OAAO,wBAAwB,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAA;AAC3D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAU;IAC5C,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;QACnD,MAAM,QAAQ,GAAkB,EAAE,CAAA;QAElC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,YAAY,MAAM;YACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAA;QAEhC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAA;QAEnD,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;YAClC,MAAM,GAAG,GACP,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;gBAC7B,CAAC,CAAC,OAAO,CAAC,GAAG;gBACb,CAAC,CAAC,MAAM,MAAM,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YAE9C,OAAO;gBACL,IAAI;gBACJ,GAAG;gBACH,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;aACrB,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CACH,CAAA;IAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAGrB,CAAA;IAEH,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;QAE9C,QAAQ,CAAC,IAAI,CAAC;YACZ,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;YAClE,UAAU,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG;YAC9B,SAAS,EAAE,IAAI,CAAC,KAAK,IAAI,QAAQ;SAClC,CAAC,CAAA;QAEF,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IACnC,CAAC;IAED,KAAK,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,QAAQ;QACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAW,CAAC,CAAA;AACvD,CAAC"}
1
+ {"version":3,"file":"register-fonts.js","sourceRoot":"","sources":["../../src/helpers/register-fonts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { type DocumentProps } from '@react-pdf/renderer';
2
+ import { type ReactElement } from 'react';
3
+ import type { DocumentEncryptionProps } from '../tools/encrypt-pdf.js';
4
+ export declare function renderDocument(element: ReactElement<DocumentProps>, encryption?: DocumentEncryptionProps): Promise<{
5
+ pdf: Buffer;
6
+ encrypted?: Buffer;
7
+ }>;
8
+ //# sourceMappingURL=render-document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-document.d.ts","sourceRoot":"","sources":["../../src/helpers/render-document.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExE,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAA;AAEvD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AA6CtE,wBAAsB,cAAc,CAClC,OAAO,EAAE,YAAY,CAAC,aAAa,CAAC,EACpC,UAAU,CAAC,EAAE,uBAAuB,GACnC,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA4B9C"}
@@ -0,0 +1,54 @@
1
+ import renderPDF from '@react-pdf/render';
2
+ import { renderToBuffer } from '@react-pdf/renderer';
3
+ import { PDFDocument } from 'pdfkit';
4
+ import { cloneElement } from 'react';
5
+ function toContext(props, encryption) {
6
+ const info = {};
7
+ const put = (key, value) => {
8
+ if (value !== undefined)
9
+ info[key] = value;
10
+ };
11
+ put('Title', props.title);
12
+ put('Author', props.author);
13
+ put('Subject', props.subject);
14
+ put('Creator', props.creator ?? 'react-pdf');
15
+ put('Producer', props.producer ?? 'react-pdf');
16
+ put('CreationDate', props.creationDate);
17
+ put('ModificationDate', props.modificationDate);
18
+ return new PDFDocument({
19
+ compress: true,
20
+ displayTitle: true,
21
+ autoFirstPage: false,
22
+ lang: props.language,
23
+ info,
24
+ ...encryption,
25
+ });
26
+ }
27
+ async function toBuffer(context) {
28
+ const chunks = [];
29
+ for await (const chunk of context)
30
+ chunks.push(chunk);
31
+ return Buffer.concat(chunks);
32
+ }
33
+ export async function renderDocument(element, encryption) {
34
+ if (!encryption)
35
+ return { pdf: await renderToBuffer(element) };
36
+ const props = {
37
+ ...element.props,
38
+ creationDate: element.props.creationDate ?? new Date(),
39
+ };
40
+ let layout;
41
+ const pdf = await renderToBuffer(cloneElement(element, {
42
+ ...props,
43
+ onRender: rendered => {
44
+ layout = rendered._INTERNAL__LAYOUT__DATA_;
45
+ },
46
+ }));
47
+ if (!layout)
48
+ throw new Error('Rendering exposed no document layout. @react-pdf/renderer and @react-pdf/render are likely out of step.');
49
+ return {
50
+ pdf,
51
+ encrypted: await toBuffer(renderPDF(toContext(props, encryption), layout)),
52
+ };
53
+ }
54
+ //# sourceMappingURL=render-document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-document.js","sourceRoot":"","sources":["../../src/helpers/render-document.ts"],"names":[],"mappings":"AAEA,OAAO,SAAS,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,cAAc,EAAsB,MAAM,qBAAqB,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,YAAY,EAAqB,MAAM,OAAO,CAAA;AAUvD,SAAS,SAAS,CAChB,KAAoB,EACpB,UAAoC;IAEpC,MAAM,IAAI,GAAkC,EAAE,CAAA;IAE9C,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,KAAgC,EAAE,EAAE;QAC5D,IAAI,KAAK,KAAK,SAAS;YAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAA;IAC5C,CAAC,CAAA;IAED,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;IACzB,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IAC3B,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,CAAA;IAC7B,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,IAAI,WAAW,CAAC,CAAA;IAC5C,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,QAAQ,IAAI,WAAW,CAAC,CAAA;IAC9C,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,CAAA;IACvC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAA;IAE/C,OAAO,IAAI,WAAW,CAAC;QACrB,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,KAAK;QACpB,IAAI,EAAE,KAAK,CAAC,QAAQ;QACpB,IAAI;QACJ,GAAG,UAAU;KACd,CAA+B,CAAA;AAClC,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,OAAwB;IAC9C,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAA8B;QACtD,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAA;IAE9B,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAoC,EACpC,UAAoC;IAEpC,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC,OAAO,CAAC,EAAE,CAAA;IAE9D,MAAM,KAAK,GAAkB;QAC3B,GAAG,OAAO,CAAC,KAAK;QAChB,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,IAAI,IAAI,IAAI,EAAE;KACvD,CAAA;IAED,IAAI,MAAkC,CAAA;IAEtC,MAAM,GAAG,GAAG,MAAM,cAAc,CAC9B,YAAY,CAAC,OAAO,EAAE;QACpB,GAAG,KAAK;QACR,QAAQ,EAAE,QAAQ,CAAC,EAAE;YACnB,MAAM,GAAI,QAA6B,CAAC,wBAAwB,CAAA;QAClE,CAAC;KACF,CAAC,CACH,CAAA;IAED,IAAI,CAAC,MAAM;QACT,MAAM,IAAI,KAAK,CACb,yGAAyG,CAC1G,CAAA;IAEH,OAAO;QACL,GAAG;QACH,SAAS,EAAE,MAAM,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;KAC3E,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { RenderResult, RenderTask } from '../workers/render.js';
2
+ export declare function render(task: RenderTask): Promise<RenderResult>;
3
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/helpers/render.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAiBpE,wBAAsB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAYpE"}
@@ -0,0 +1,19 @@
1
+ import { fileURLToPath } from 'node:url';
2
+ import { Piscina } from 'piscina';
3
+ const WORKER = fileURLToPath(new URL('../../dist/workers/render.js', import.meta.url));
4
+ let pool = null;
5
+ function toBuffer(bytes) {
6
+ return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
7
+ }
8
+ export async function render(task) {
9
+ pool ??= new Piscina({
10
+ filename: WORKER,
11
+ minThreads: 1,
12
+ maxThreads: 1,
13
+ });
14
+ const { pdf, encrypted } = await pool.run(task);
15
+ if (!encrypted)
16
+ return { pdf: toBuffer(pdf) };
17
+ return { pdf: toBuffer(pdf), encrypted: toBuffer(encrypted) };
18
+ }
19
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/helpers/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAIjC,MAAM,MAAM,GAAG,aAAa,CAC1B,IAAI,GAAG,CAAC,8BAA8B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CACzD,CAAA;AAOD,IAAI,IAAI,GAA2C,IAAI,CAAA;AAEvD,SAAS,QAAQ,CAAC,KAAiB;IACjC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAgB;IAC3C,IAAI,KAAK,IAAI,OAAO,CAAyB;QAC3C,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;KACd,CAAC,CAAA;IAEF,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAE/C,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAA;IAE7C,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAA;AAC/D,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { DocumentProps } from '@react-pdf/renderer';
1
2
  export declare enum ProtectionFlags {
2
3
  Print = 4,
3
4
  Modify = 8,
@@ -20,6 +21,8 @@ export type EncryptPDFOptions = {
20
21
  password: Password;
21
22
  protection?: ProtectionFlags;
22
23
  };
23
- export declare function encryptPDF(input: Buffer, options: EncryptPDFOptions): Buffer;
24
+ export type DocumentEncryptionProps = Pick<DocumentProps, 'pdfVersion' | 'userPassword' | 'ownerPassword' | 'permissions'>;
25
+ export declare function toPermissions(protection: ProtectionFlags): NonNullable<DocumentProps['permissions']>;
26
+ export declare function toDocumentEncryptionProps(options: EncryptPDFOptions): DocumentEncryptionProps;
24
27
  export {};
25
28
  //# sourceMappingURL=encrypt-pdf.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"encrypt-pdf.d.ts","sourceRoot":"","sources":["../../src/tools/encrypt-pdf.ts"],"names":[],"mappings":"AAGA,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,cAAc,KAAK;IACnB,eAAe,KAAK;IACpB,SAAS,MAAM;IACf,uBAAuB,MAAM;IAC7B,QAAQ,OAAO;IACf,mBAAmB,OAAO;CAC3B;AAED,eAAO,MAAM,iBAAiB;;;CAcpB,CAAA;AAEV,KAAK,QAAQ,GACT,MAAM,GACN;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAEL,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,CAAA;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAmB5E"}
1
+ {"version":3,"file":"encrypt-pdf.d.ts","sourceRoot":"","sources":["../../src/tools/encrypt-pdf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD,oBAAY,eAAe;IACzB,KAAK,IAAI;IACT,MAAM,IAAI;IACV,cAAc,KAAK;IACnB,eAAe,KAAK;IACpB,SAAS,MAAM;IACf,uBAAuB,MAAM;IAC7B,QAAQ,OAAO;IACf,mBAAmB,OAAO;CAC3B;AAED,eAAO,MAAM,iBAAiB;;;CAcpB,CAAA;AAEV,KAAK,QAAQ,GACT,MAAM,GACN;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAEL,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,CAAC,EAAE,eAAe,CAAA;CAC7B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,IAAI,CACxC,aAAa,EACb,YAAY,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAChE,CAAA;AASD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,eAAe,GAC1B,WAAW,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAmB3C;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,iBAAiB,GACzB,uBAAuB,CAczB"}
@@ -1,5 +1,3 @@
1
- /* eslint-disable cspell/spellchecker */
2
- import muhammara from 'muhammara';
3
1
  export var ProtectionFlags;
4
2
  (function (ProtectionFlags) {
5
3
  ProtectionFlags[ProtectionFlags["Print"] = 4] = "Print";
@@ -24,19 +22,36 @@ export const ProtectionPresets = {
24
22
  ProtectionFlags.Assemble |
25
23
  ProtectionFlags.PrintHighResolution,
26
24
  };
27
- export function encryptPDF(input, options) {
28
- const output = new muhammara.PDFWStreamForBuffer();
29
- const pdfPassword = {};
30
- if (typeof options.password === 'string')
31
- pdfPassword.userPassword = options.password;
32
- if (typeof options.password === 'object') {
33
- pdfPassword.userPassword = options.password.user;
34
- pdfPassword.ownerPassword = options.password.owner;
35
- }
36
- muhammara.recrypt(new muhammara.PDFRStreamForBuffer(input), output, {
37
- ...pdfPassword,
38
- userProtectionFlag: options.protection,
39
- });
40
- return output.buffer;
25
+ const ENCRYPTED_PDF_VERSION = '1.6';
26
+ const DEFAULT_PROTECTION = ProtectionFlags.Print;
27
+ const has = (protection, flag) => (protection & flag) === flag;
28
+ export function toPermissions(protection) {
29
+ const printing = has(protection, ProtectionFlags.PrintHighResolution)
30
+ ? 'highResolution'
31
+ : has(protection, ProtectionFlags.Print)
32
+ ? 'lowResolution'
33
+ : undefined;
34
+ return {
35
+ printing,
36
+ modifying: has(protection, ProtectionFlags.Modify),
37
+ copying: has(protection, ProtectionFlags.CopyAndExtract),
38
+ annotating: has(protection, ProtectionFlags.AnnotateAndFill),
39
+ fillingForms: has(protection, ProtectionFlags.FillForms),
40
+ contentAccessibility: has(protection, ProtectionFlags.ExtractForAccessibility),
41
+ documentAssembly: has(protection, ProtectionFlags.Assemble),
42
+ };
43
+ }
44
+ export function toDocumentEncryptionProps(options) {
45
+ const password = typeof options.password === 'string'
46
+ ? { userPassword: options.password }
47
+ : {
48
+ userPassword: options.password.user,
49
+ ownerPassword: options.password.owner,
50
+ };
51
+ return {
52
+ pdfVersion: ENCRYPTED_PDF_VERSION,
53
+ permissions: toPermissions(options.protection ?? DEFAULT_PROTECTION),
54
+ ...password,
55
+ };
41
56
  }
42
57
  //# sourceMappingURL=encrypt-pdf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encrypt-pdf.js","sourceRoot":"","sources":["../../src/tools/encrypt-pdf.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,SAAS,MAAM,WAAW,CAAA;AAEjC,MAAM,CAAN,IAAY,eASX;AATD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,0EAAmB,CAAA;IACnB,4EAAoB,CAAA;IACpB,iEAAe,CAAA;IACf,6FAA6B,CAAA;IAC7B,gEAAe,CAAA;IACf,sFAA0B,CAAA;AAC5B,CAAC,EATW,eAAe,KAAf,eAAe,QAS1B;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EACN,eAAe,CAAC,KAAK;QACrB,eAAe,CAAC,mBAAmB;QACnC,eAAe,CAAC,uBAAuB;IACzC,GAAG,EACD,eAAe,CAAC,KAAK;QACrB,eAAe,CAAC,MAAM;QACtB,eAAe,CAAC,cAAc;QAC9B,eAAe,CAAC,eAAe;QAC/B,eAAe,CAAC,SAAS;QACzB,eAAe,CAAC,uBAAuB;QACvC,eAAe,CAAC,QAAQ;QACxB,eAAe,CAAC,mBAAmB;CAC7B,CAAA;AAcV,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,OAA0B;IAClE,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,mBAAmB,EAAE,CAAA;IAElD,MAAM,WAAW,GAA2B,EAAE,CAAA;IAE9C,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;QACtC,WAAW,CAAC,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAA;IAE7C,IAAI,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACzC,WAAW,CAAC,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAA;QAChD,WAAW,CAAC,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAA;IACpD,CAAC;IAED,SAAS,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE;QAClE,GAAG,WAAW;QACd,kBAAkB,EAAE,OAAO,CAAC,UAAU;KACvC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC"}
1
+ {"version":3,"file":"encrypt-pdf.js","sourceRoot":"","sources":["../../src/tools/encrypt-pdf.ts"],"names":[],"mappings":"AAEA,MAAM,CAAN,IAAY,eASX;AATD,WAAY,eAAe;IACzB,uDAAS,CAAA;IACT,yDAAU,CAAA;IACV,0EAAmB,CAAA;IACnB,4EAAoB,CAAA;IACpB,iEAAe,CAAA;IACf,6FAA6B,CAAA;IAC7B,gEAAe,CAAA;IACf,sFAA0B,CAAA;AAC5B,CAAC,EATW,eAAe,KAAf,eAAe,QAS1B;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EACN,eAAe,CAAC,KAAK;QACrB,eAAe,CAAC,mBAAmB;QACnC,eAAe,CAAC,uBAAuB;IACzC,GAAG,EACD,eAAe,CAAC,KAAK;QACrB,eAAe,CAAC,MAAM;QACtB,eAAe,CAAC,cAAc;QAC9B,eAAe,CAAC,eAAe;QAC/B,eAAe,CAAC,SAAS;QACzB,eAAe,CAAC,uBAAuB;QACvC,eAAe,CAAC,QAAQ;QACxB,eAAe,CAAC,mBAAmB;CAC7B,CAAA;AAmBV,MAAM,qBAAqB,GAAgC,KAAK,CAAA;AAEhE,MAAM,kBAAkB,GAAG,eAAe,CAAC,KAAK,CAAA;AAEhD,MAAM,GAAG,GAAG,CAAC,UAAkB,EAAE,IAAqB,EAAE,EAAE,CACxD,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,IAAI,CAAA;AAE9B,MAAM,UAAU,aAAa,CAC3B,UAA2B;IAE3B,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,mBAAmB,CAAC;QACnE,CAAC,CAAC,gBAAgB;QAClB,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,KAAK,CAAC;YACtC,CAAC,CAAC,eAAe;YACjB,CAAC,CAAC,SAAS,CAAA;IAEf,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,MAAM,CAAC;QAClD,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,cAAc,CAAC;QACxD,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,eAAe,CAAC;QAC5D,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,SAAS,CAAC;QACxD,oBAAoB,EAAE,GAAG,CACvB,UAAU,EACV,eAAe,CAAC,uBAAuB,CACxC;QACD,gBAAgB,EAAE,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,QAAQ,CAAC;KAC5D,CAAA;AACH,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAA0B;IAE1B,MAAM,QAAQ,GACZ,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAClC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,QAAQ,EAAE;QACpC,CAAC,CAAC;YACE,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI;YACnC,aAAa,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK;SACtC,CAAA;IAEP,OAAO;QACL,UAAU,EAAE,qBAAqB;QACjC,WAAW,EAAE,aAAa,CAAC,OAAO,CAAC,UAAU,IAAI,kBAAkB,CAAC;QACpE,GAAG,QAAQ;KACZ,CAAA;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { type Fonts } from '../helpers/register-fonts.js';
2
+ import type { DocumentEncryptionProps } from '../tools/encrypt-pdf.js';
3
+ import type { DocumentNode } from '../typings/pdf.js';
4
+ export type RenderTask = {
5
+ document: DocumentNode;
6
+ fonts?: Fonts | undefined;
7
+ encryption?: DocumentEncryptionProps | undefined;
8
+ };
9
+ export type RenderResult = {
10
+ pdf: Buffer;
11
+ encrypted?: Buffer;
12
+ };
13
+ export default function render({ document, fonts, encryption, }: RenderTask): Promise<RenderResult>;
14
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/workers/render.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,KAAK,KAAK,EAAE,MAAM,8BAA8B,CAAA;AAExE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,YAAY,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAA;CACjD,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAA8B,MAAM,CAAC,EACnC,QAAQ,EACR,KAAK,EACL,UAAU,GACX,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAIpC"}
@@ -0,0 +1,9 @@
1
+ import { documentToElement } from '../helpers/document-to-element.js';
2
+ import { registerFonts } from '../helpers/register-fonts.js';
3
+ import { renderDocument } from '../helpers/render-document.js';
4
+ export default async function render({ document, fonts, encryption, }) {
5
+ if (fonts)
6
+ await registerFonts(fonts);
7
+ return await renderDocument(await documentToElement(document), encryption);
8
+ }
9
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/workers/render.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAc,MAAM,8BAA8B,CAAA;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAe9D,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,MAAM,CAAC,EACnC,QAAQ,EACR,KAAK,EACL,UAAU,GACC;IACX,IAAI,KAAK;QAAE,MAAM,aAAa,CAAC,KAAK,CAAC,CAAA;IAErC,OAAO,MAAM,cAAc,CAAC,MAAM,iBAAiB,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,CAAA;AAC5E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t4h.framework/pdf",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "Declarative PDF rendering module for the T4H Framework",
5
5
  "homepage": "https://github.com/tech4humans-brasil/framework/tree/main/packages/pdf",
6
6
  "bugs": "https://github.com/tech4humans-brasil/framework/issues",
@@ -32,23 +32,26 @@
32
32
  "test:watch": "vitest"
33
33
  },
34
34
  "devDependencies": {
35
- "@t4h.framework/core": "^0.13.0",
36
- "@t4h.framework/fs": "^0.9.3",
35
+ "@t4h.framework/core": "^0.15.0",
36
+ "@t4h.framework/fs": "^0.10.0",
37
37
  "@types/react": "^19.2.17",
38
+ "muhammara": "^6.0.5",
38
39
  "typescript": "^5.9.3",
39
40
  "vitest": "^4.0.18"
40
41
  },
41
42
  "peerDependencies": {
42
- "@t4h.framework/core": "^0.13.0",
43
- "@t4h.framework/fs": "^0.9.3"
43
+ "@t4h.framework/core": "^0.15.0",
44
+ "@t4h.framework/fs": "^0.10.0"
44
45
  },
45
46
  "packageManager": "yarn@4.12.0",
46
47
  "engines": {
47
48
  "node": ">=22"
48
49
  },
49
50
  "dependencies": {
50
- "@react-pdf/renderer": "^4.5.1",
51
- "muhammara": "^6.0.5",
51
+ "@react-pdf/render": "4.7.0",
52
+ "@react-pdf/renderer": "4.9.0",
53
+ "pdfkit": "0.20.1",
54
+ "piscina": "5.3.2",
52
55
  "react": "^19.2.8"
53
56
  }
54
57
  }