@awacloud/pdf 0.0.0-stage → 1.0.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 (345) hide show
  1. package/CHANGELOG.md +609 -0
  2. package/LICENSE +661 -0
  3. package/NOTICE +77 -0
  4. package/README.md +363 -2
  5. package/dist/build/index.js +21 -0
  6. package/dist/build/pdf-full-rw.js +10972 -0
  7. package/dist/build/pdf-full-rw.meta.json +105 -0
  8. package/dist/build/pdf-full-rw.min.js +53 -0
  9. package/dist/build/pdf-full.js +6078 -0
  10. package/dist/build/pdf-full.meta.json +90 -0
  11. package/dist/build/pdf-full.min.js +32 -0
  12. package/dist/build/pdf-large-rw.js +10367 -0
  13. package/dist/build/pdf-large-rw.meta.json +99 -0
  14. package/dist/build/pdf-large-rw.min.js +53 -0
  15. package/dist/build/pdf-large.js +5473 -0
  16. package/dist/build/pdf-large.meta.json +84 -0
  17. package/dist/build/pdf-large.min.js +32 -0
  18. package/dist/build/pdf-legacy-rw.js +12402 -0
  19. package/dist/build/pdf-legacy-rw.meta.json +110 -0
  20. package/dist/build/pdf-legacy-rw.min.js +53 -0
  21. package/dist/build/pdf-legacy.js +7508 -0
  22. package/dist/build/pdf-legacy.meta.json +95 -0
  23. package/dist/build/pdf-legacy.min.js +32 -0
  24. package/dist/build/pdf-rw.js +7578 -0
  25. package/dist/build/pdf-rw.meta.json +77 -0
  26. package/dist/build/pdf-rw.min.js +53 -0
  27. package/dist/build/pdf.js +2684 -0
  28. package/dist/build/pdf.meta.json +62 -0
  29. package/dist/build/pdf.min.js +32 -0
  30. package/dist/standalone/pdf-full-rw.js +16798 -0
  31. package/dist/standalone/pdf-full-rw.meta.json +78 -0
  32. package/dist/standalone/pdf-full-rw.min.js +56 -0
  33. package/dist/standalone/pdf-full.js +11904 -0
  34. package/dist/standalone/pdf-full.meta.json +63 -0
  35. package/dist/standalone/pdf-full.min.js +35 -0
  36. package/dist/standalone/pdf-large-rw.js +16193 -0
  37. package/dist/standalone/pdf-large-rw.meta.json +72 -0
  38. package/dist/standalone/pdf-large-rw.min.js +56 -0
  39. package/dist/standalone/pdf-large.js +11299 -0
  40. package/dist/standalone/pdf-large.meta.json +57 -0
  41. package/dist/standalone/pdf-large.min.js +35 -0
  42. package/dist/standalone/pdf-legacy-rw.js +18228 -0
  43. package/dist/standalone/pdf-legacy-rw.meta.json +83 -0
  44. package/dist/standalone/pdf-legacy-rw.min.js +56 -0
  45. package/dist/standalone/pdf-legacy.js +13334 -0
  46. package/dist/standalone/pdf-legacy.meta.json +68 -0
  47. package/dist/standalone/pdf-legacy.min.js +35 -0
  48. package/dist/standalone/pdf-rw.js +13404 -0
  49. package/dist/standalone/pdf-rw.meta.json +50 -0
  50. package/dist/standalone/pdf-rw.min.js +56 -0
  51. package/dist/standalone/pdf.js +8510 -0
  52. package/dist/standalone/pdf.meta.json +35 -0
  53. package/dist/standalone/pdf.min.js +35 -0
  54. package/docs/README.md +53 -0
  55. package/docs/api/README.md +38 -0
  56. package/docs/api/_shared/README.md +91 -0
  57. package/docs/api/action/README.md +29 -0
  58. package/docs/api/action/action.md +81 -0
  59. package/docs/api/action/goTo.md +66 -0
  60. package/docs/api/action/launch.md +58 -0
  61. package/docs/api/action/named.md +55 -0
  62. package/docs/api/action/uri.md +54 -0
  63. package/docs/api/annot/README.md +53 -0
  64. package/docs/api/annot/annot.md +114 -0
  65. package/docs/api/annot/fileAttach.md +53 -0
  66. package/docs/api/annot/freeText.md +68 -0
  67. package/docs/api/annot/ink.md +69 -0
  68. package/docs/api/annot/link.md +74 -0
  69. package/docs/api/annot/markup.md +83 -0
  70. package/docs/api/annot/popup.md +52 -0
  71. package/docs/api/annot/projection.md +56 -0
  72. package/docs/api/annot/redact.md +67 -0
  73. package/docs/api/annot/square.md +87 -0
  74. package/docs/api/annot/stamp.md +54 -0
  75. package/docs/api/annot/text.md +69 -0
  76. package/docs/api/annot/widget.md +69 -0
  77. package/docs/api/associatedFiles/README.md +9 -0
  78. package/docs/api/associatedFiles/associatedFiles.md +78 -0
  79. package/docs/api/bundles/README.md +68 -0
  80. package/docs/api/bundles/dist-matrix.md +165 -0
  81. package/docs/api/bundles/pdf-full.md +148 -0
  82. package/docs/api/bundles/pdf-large.md +144 -0
  83. package/docs/api/bundles/pdf-legacy.md +169 -0
  84. package/docs/api/content/README.md +29 -0
  85. package/docs/api/content/color.md +99 -0
  86. package/docs/api/content/graphics.md +114 -0
  87. package/docs/api/content/images.md +124 -0
  88. package/docs/api/content/ops.md +100 -0
  89. package/docs/api/content/stream.md +107 -0
  90. package/docs/api/content/text.md +98 -0
  91. package/docs/api/crypto/README.md +29 -0
  92. package/docs/api/crypto/aesGcm.md +72 -0
  93. package/docs/api/crypto/permissions.md +79 -0
  94. package/docs/api/crypto/security.md +98 -0
  95. package/docs/api/crypto/standardV4.md +104 -0
  96. package/docs/api/crypto/standardV5.md +84 -0
  97. package/docs/api/crypto/standardV6.md +93 -0
  98. package/docs/api/destination/README.md +9 -0
  99. package/docs/api/destination/destination.md +79 -0
  100. package/docs/api/document/README.md +29 -0
  101. package/docs/api/document/builder.md +281 -0
  102. package/docs/api/document/catalog.md +98 -0
  103. package/docs/api/document/document.md +187 -0
  104. package/docs/api/document/encryptedWriter.md +149 -0
  105. package/docs/api/document/incrementalWriter.md +148 -0
  106. package/docs/api/document/page.md +99 -0
  107. package/docs/api/document/pages.md +82 -0
  108. package/docs/api/document/resources.md +102 -0
  109. package/docs/api/document/writer.md +157 -0
  110. package/docs/api/document/xrefStreamWriter.md +122 -0
  111. package/docs/api/embedded/README.md +13 -0
  112. package/docs/api/embedded/collection.md +80 -0
  113. package/docs/api/embedded/embeddedFile.md +86 -0
  114. package/docs/api/embedded/fileSpec.md +87 -0
  115. package/docs/api/errors.md +110 -0
  116. package/docs/api/extra/3d-richmedia.md +76 -0
  117. package/docs/api/extra/README.md +99 -0
  118. package/docs/api/extra/annot-extended.md +71 -0
  119. package/docs/api/extra/associated-files.md +70 -0
  120. package/docs/api/extra/ccitt-fax-decoder.md +74 -0
  121. package/docs/api/extra/color-spaces-extended.md +72 -0
  122. package/docs/api/extra/content-ops-extended.md +82 -0
  123. package/docs/api/extra/document-parts.md +69 -0
  124. package/docs/api/extra/embedded-files-portfolio.md +87 -0
  125. package/docs/api/extra/font-cid-typed.md +77 -0
  126. package/docs/api/extra/font-color-tagging.md +76 -0
  127. package/docs/api/extra/form-actions-extended.md +75 -0
  128. package/docs/api/extra/info-dict-deprecated.md +72 -0
  129. package/docs/api/extra/jbig2-read.md +80 -0
  130. package/docs/api/extra/legacy-deprecated-annots.md +89 -0
  131. package/docs/api/extra/legacy-deprecated-filters.md +78 -0
  132. package/docs/api/extra/legacy-rc4-read.md +74 -0
  133. package/docs/api/extra/legacy-xfa-read.md +65 -0
  134. package/docs/api/extra/linearization-write.md +71 -0
  135. package/docs/api/extra/misc.md +93 -0
  136. package/docs/api/extra/optional-content-extended.md +83 -0
  137. package/docs/api/extra/pdf-a-output-intent.md +65 -0
  138. package/docs/api/extra/pdf-sandbox.md +76 -0
  139. package/docs/api/extra/pdf-ua-tagged.md +63 -0
  140. package/docs/api/extra/pdf-x-prepress.md +65 -0
  141. package/docs/api/extra/redaction-iso32005.md +65 -0
  142. package/docs/api/extra/shading-typed.md +73 -0
  143. package/docs/api/extra/sig-aes-gcm.md +69 -0
  144. package/docs/api/extra/sig-pades.md +103 -0
  145. package/docs/api/extra/tagged-pdf-typed.md +78 -0
  146. package/docs/api/extra/transparency-typed.md +74 -0
  147. package/docs/api/extra/well-tagged-pdf.md +61 -0
  148. package/docs/api/extra/xmp-extended.md +65 -0
  149. package/docs/api/font/README.md +25 -0
  150. package/docs/api/font/embed.md +157 -0
  151. package/docs/api/font/encoding.md +95 -0
  152. package/docs/api/font/font.md +97 -0
  153. package/docs/api/font/type3.md +89 -0
  154. package/docs/api/form/README.md +35 -0
  155. package/docs/api/form/acroform.md +88 -0
  156. package/docs/api/form/appearance.md +87 -0
  157. package/docs/api/form/button.md +97 -0
  158. package/docs/api/form/choice.md +96 -0
  159. package/docs/api/form/fieldTree.md +93 -0
  160. package/docs/api/form/signature.md +90 -0
  161. package/docs/api/form/text.md +88 -0
  162. package/docs/api/linearization/README.md +11 -0
  163. package/docs/api/linearization/linearization.md +81 -0
  164. package/docs/api/main.md +116 -0
  165. package/docs/api/metadata/README.md +10 -0
  166. package/docs/api/metadata/info.md +70 -0
  167. package/docs/api/metadata/xmp.md +62 -0
  168. package/docs/api/ocg/README.md +23 -0
  169. package/docs/api/ocg/config.md +95 -0
  170. package/docs/api/ocg/ocg.md +77 -0
  171. package/docs/api/outline/README.md +11 -0
  172. package/docs/api/outline/outline.md +107 -0
  173. package/docs/api/pdf.md +152 -0
  174. package/docs/api/prepress/README.md +10 -0
  175. package/docs/api/prepress/outputIntent.md +79 -0
  176. package/docs/api/prepress/pageBoundary.md +75 -0
  177. package/docs/api/sig/README.md +32 -0
  178. package/docs/api/sig/byteRange.md +120 -0
  179. package/docs/api/sig/certChain.md +84 -0
  180. package/docs/api/sig/dss.md +111 -0
  181. package/docs/api/sig/oids.md +76 -0
  182. package/docs/api/sig/sha1.md +72 -0
  183. package/docs/api/sig/sign.md +317 -0
  184. package/docs/api/sig/signature.md +178 -0
  185. package/docs/api/sig/timestamp.md +84 -0
  186. package/docs/api/syntax/README.md +29 -0
  187. package/docs/api/syntax/crossRefStream.md +115 -0
  188. package/docs/api/syntax/filters/README.md +50 -0
  189. package/docs/api/syntax/filters/ascii85.md +76 -0
  190. package/docs/api/syntax/filters/asciiHex.md +73 -0
  191. package/docs/api/syntax/filters/dispatch.md +125 -0
  192. package/docs/api/syntax/filters/flate.md +134 -0
  193. package/docs/api/syntax/filters/runLength.md +78 -0
  194. package/docs/api/syntax/objStream.md +88 -0
  195. package/docs/api/syntax/parser-obj.md +97 -0
  196. package/docs/api/syntax/parser.md +151 -0
  197. package/docs/api/syntax/serializer.md +109 -0
  198. package/docs/api/syntax/tokenizer.md +104 -0
  199. package/docs/api/syntax/trailer.md +85 -0
  200. package/docs/api/syntax/xref.md +139 -0
  201. package/docs/api/tagged/README.md +25 -0
  202. package/docs/api/tagged/classMap.md +67 -0
  203. package/docs/api/tagged/markedContent.md +62 -0
  204. package/docs/api/tagged/parentTree.md +67 -0
  205. package/docs/api/tagged/roleMap.md +67 -0
  206. package/docs/api/tagged/structElement.md +76 -0
  207. package/docs/api/tagged/structTree.md +75 -0
  208. package/docs/guide/coverage.md +113 -0
  209. package/docs/guide/crypto.md +121 -0
  210. package/docs/guide/extending.md +76 -0
  211. package/docs/guide/getting-started.md +75 -0
  212. package/docs/guide/legacy-1.7.md +42 -0
  213. package/docs/guide/pades-integration.md +579 -0
  214. package/docs/guide/read-pdf.md +89 -0
  215. package/package.json +97 -4
  216. package/src/_shared/index.js +179 -0
  217. package/src/action/action.js +119 -0
  218. package/src/action/goTo.js +89 -0
  219. package/src/action/launch.js +61 -0
  220. package/src/action/named.js +54 -0
  221. package/src/action/uri.js +51 -0
  222. package/src/annot/annot.js +212 -0
  223. package/src/annot/fileAttach.js +55 -0
  224. package/src/annot/freeText.js +82 -0
  225. package/src/annot/ink.js +77 -0
  226. package/src/annot/link.js +77 -0
  227. package/src/annot/markup.js +91 -0
  228. package/src/annot/popup.js +53 -0
  229. package/src/annot/projection.js +52 -0
  230. package/src/annot/redact.js +87 -0
  231. package/src/annot/square.js +132 -0
  232. package/src/annot/stamp.js +48 -0
  233. package/src/annot/text.js +54 -0
  234. package/src/annot/widget.js +61 -0
  235. package/src/associatedFiles/associatedFiles.js +86 -0
  236. package/src/bundles/pdf-full.js +91 -0
  237. package/src/bundles/pdf-large.js +81 -0
  238. package/src/bundles/pdf-legacy.js +107 -0
  239. package/src/content/color.js +114 -0
  240. package/src/content/graphics.js +192 -0
  241. package/src/content/images.js +160 -0
  242. package/src/content/ops.js +137 -0
  243. package/src/content/stream.js +154 -0
  244. package/src/content/text.js +125 -0
  245. package/src/crypto/aesGcm.js +123 -0
  246. package/src/crypto/permissions.js +112 -0
  247. package/src/crypto/security.js +327 -0
  248. package/src/crypto/standardV4.js +443 -0
  249. package/src/crypto/standardV5.js +306 -0
  250. package/src/crypto/standardV6.js +334 -0
  251. package/src/destination/destination.js +183 -0
  252. package/src/document/builder.js +618 -0
  253. package/src/document/catalog.js +100 -0
  254. package/src/document/document.js +472 -0
  255. package/src/document/encryptedWriter.js +554 -0
  256. package/src/document/incrementalWriter.js +514 -0
  257. package/src/document/page.js +131 -0
  258. package/src/document/pages.js +103 -0
  259. package/src/document/resources.js +146 -0
  260. package/src/document/writer.js +211 -0
  261. package/src/document/xrefStreamWriter.js +353 -0
  262. package/src/embedded/collection.js +102 -0
  263. package/src/embedded/embeddedFile.js +99 -0
  264. package/src/embedded/fileSpec.js +137 -0
  265. package/src/errors.js +78 -0
  266. package/src/extra/3d-richmedia.js +171 -0
  267. package/src/extra/annot-extended.js +200 -0
  268. package/src/extra/associated-files.js +131 -0
  269. package/src/extra/ccitt-fax-decoder.js +776 -0
  270. package/src/extra/color-spaces-extended.js +196 -0
  271. package/src/extra/content-ops-extended.js +153 -0
  272. package/src/extra/document-parts.js +149 -0
  273. package/src/extra/embedded-files-portfolio.js +234 -0
  274. package/src/extra/font-cid-typed.js +185 -0
  275. package/src/extra/font-color-tagging.js +144 -0
  276. package/src/extra/form-actions-extended.js +196 -0
  277. package/src/extra/info-dict-deprecated.js +137 -0
  278. package/src/extra/jbig2-read.js +169 -0
  279. package/src/extra/legacy-deprecated-annots.js +198 -0
  280. package/src/extra/legacy-deprecated-filters.js +167 -0
  281. package/src/extra/legacy-rc4-read.js +235 -0
  282. package/src/extra/legacy-xfa-read.js +104 -0
  283. package/src/extra/linearization-write.js +97 -0
  284. package/src/extra/misc.js +217 -0
  285. package/src/extra/optional-content-extended.js +142 -0
  286. package/src/extra/pdf-a-output-intent.js +112 -0
  287. package/src/extra/pdf-sandbox.js +88 -0
  288. package/src/extra/pdf-ua-tagged.js +116 -0
  289. package/src/extra/pdf-x-prepress.js +114 -0
  290. package/src/extra/redaction-iso32005.js +136 -0
  291. package/src/extra/shading-typed.js +222 -0
  292. package/src/extra/sig-aes-gcm.js +135 -0
  293. package/src/extra/sig-pades.js +242 -0
  294. package/src/extra/tagged-pdf-typed.js +203 -0
  295. package/src/extra/transparency-typed.js +135 -0
  296. package/src/extra/well-tagged-pdf.js +138 -0
  297. package/src/extra/xmp-extended.js +190 -0
  298. package/src/font/embed.js +480 -0
  299. package/src/font/encoding.js +92 -0
  300. package/src/font/font.js +101 -0
  301. package/src/font/type3.js +75 -0
  302. package/src/form/acroform.js +94 -0
  303. package/src/form/appearance.js +90 -0
  304. package/src/form/button.js +105 -0
  305. package/src/form/choice.js +152 -0
  306. package/src/form/fieldTree.js +120 -0
  307. package/src/form/signature.js +100 -0
  308. package/src/form/text.js +101 -0
  309. package/src/linearization/linearization.js +107 -0
  310. package/src/main.js +411 -0
  311. package/src/metadata/info.js +87 -0
  312. package/src/metadata/xmp.js +62 -0
  313. package/src/ocg/config.js +156 -0
  314. package/src/ocg/ocg.js +124 -0
  315. package/src/outline/outline.js +157 -0
  316. package/src/pdf.js +133 -0
  317. package/src/prepress/outputIntent.js +118 -0
  318. package/src/prepress/pageBoundary.js +108 -0
  319. package/src/sig/byteRange.js +306 -0
  320. package/src/sig/certChain.js +247 -0
  321. package/src/sig/dss.js +317 -0
  322. package/src/sig/oids.js +157 -0
  323. package/src/sig/sha1.js +142 -0
  324. package/src/sig/sign.js +1899 -0
  325. package/src/sig/signature.js +1441 -0
  326. package/src/sig/timestamp.js +236 -0
  327. package/src/syntax/crossRefStream.js +133 -0
  328. package/src/syntax/filters/ascii85.js +122 -0
  329. package/src/syntax/filters/asciiHex.js +83 -0
  330. package/src/syntax/filters/dispatch.js +176 -0
  331. package/src/syntax/filters/flate.js +316 -0
  332. package/src/syntax/filters/runLength.js +96 -0
  333. package/src/syntax/objStream.js +99 -0
  334. package/src/syntax/parser-obj.js +52 -0
  335. package/src/syntax/parser.js +321 -0
  336. package/src/syntax/serializer.js +221 -0
  337. package/src/syntax/tokenizer.js +290 -0
  338. package/src/syntax/trailer.js +76 -0
  339. package/src/syntax/xref.js +341 -0
  340. package/src/tagged/classMap.js +81 -0
  341. package/src/tagged/markedContent.js +123 -0
  342. package/src/tagged/parentTree.js +126 -0
  343. package/src/tagged/roleMap.js +107 -0
  344. package/src/tagged/structElement.js +138 -0
  345. package/src/tagged/structTree.js +94 -0
@@ -0,0 +1,149 @@
1
+ ---
2
+ module: pdfEncryptedWriter
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfWriter, pdfStandardV5, pdfStandardV6, pdfStandardV4, pdfAesGcm]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfEncryptedWriter
11
+
12
+ > Emits an `/Encrypt`-protected PDF — wraps `pdfWriter` with the Standard Security Handlers.
13
+
14
+ **Module** `pdfEncryptedWriter` | **Source** `packages/front/office/pdf/src/document/encryptedWriter.js` | **Deps** `pdfErrors`, `pdfWriter`, `pdfStandardV5`, `pdfStandardV6`, `pdfStandardV4`, `pdfAesGcm` | **Worker-safe** yes
15
+
16
+ Encrypts a from-scratch indirect-object graph (same shape as `pdfWriter`'s
17
+ `indirects`) and emits the result with an `/Encrypt` dictionary. Supports:
18
+
19
+ - **V=4, R=4** (PDF 1.6) — method `'AESV2'` (AES-128-CBC, default) or `'V2'`
20
+ (RC4-128), delegated to `pdfStandardV4`.
21
+ - **V=5, R=5** (historical AES-256, Adobe Extension Level 3) — delegated to `pdfStandardV5`.
22
+ - **V=5, R=6** (ISO 32000-2:2020 hardening) — delegated to `pdfStandardV6`. Method
23
+ `'AESV3'` (AES-256-CBC, default) or `'AESV4'` (AES-256-GCM, ISO TS 32003 — requires `pdfAesGcm`).
24
+
25
+ An optional distinct cipher for `/Type /EmbeddedFile` streams (`/EFF`, ISO
26
+ 32000-1 §7.6.5) is selected via `opts.encrypt.effMethod`, validated against
27
+ the same (version, method) rules as the main `method`. Every `string` and
28
+ `stream.raw` payload in the indirect graph is walked and encrypted in place
29
+ (fresh IV per object) before the `/Encrypt` indirect is appended and the
30
+ trailer patched.
31
+
32
+ ## Resolve
33
+
34
+ ```js
35
+ const ew = runtime.resolve('pdfEncryptedWriter');
36
+ // Returns: { writeEncryptedDocument }
37
+ ```
38
+
39
+ ## API
40
+
41
+ | Method | Signature | Returns |
42
+ |--------|-----------|---------|
43
+ | `writeEncryptedDocument` | `(opts: EncWriteOpts) => EncWriteResult` | Encrypted PDF bytes plus the derived crypto material. |
44
+
45
+ ### `EncWriteOpts`
46
+
47
+ Mirrors `pdfWriter`'s `WriteOpts` (`indirects`, `root`, `info?`, `id?`, `version?`) plus:
48
+
49
+ ```js
50
+ {
51
+ encrypt: {
52
+ version: 4 | 5,
53
+ revision: 4 | 5 | 6,
54
+ method?: 'AESV2' | 'V2' | 'AESV3' | 'AESV4', // default per version
55
+ effMethod?: 'AESV2' | 'V2' | 'AESV3' | 'AESV4', // optional, /Type /EmbeddedFile only
56
+ keyBits?: number, // default 128 (V4) / 256 (V5)
57
+ ownerPassword?: string | Uint8Array,
58
+ userPassword?: string | Uint8Array,
59
+ permissions?: number, // /P bitmask (Table 24)
60
+ encryptMetadata?: boolean, // default true
61
+ randomBytes?: (n: number) => Uint8Array // default globalThis.crypto.getRandomValues
62
+ }
63
+ }
64
+ ```
65
+
66
+ `randomBytes` supplies every key, salt and IV the writer draws. When it is
67
+ omitted the writer uses `globalThis.crypto.getRandomValues`, read at call
68
+ time; when neither exists the call throws `pdf/crypto/enc-writer/no-random`
69
+ before producing any output. There is no non-cryptographic fallback.
70
+
71
+ ### `EncWriteResult`
72
+
73
+ ```js
74
+ {
75
+ bytes: Uint8Array, encryptObjNum: number,
76
+ fek: Uint8Array, id: [Uint8Array, Uint8Array],
77
+ O, U, OE?, UE?, Perms?: Uint8Array,
78
+ version, revision, method, effMethod
79
+ }
80
+ ```
81
+
82
+ ## Examples
83
+
84
+ ### V=5 R=6, AES-256-CBC, deterministic (test) randomness
85
+
86
+ ```js
87
+ const ew = runtime.resolve('pdfEncryptedWriter');
88
+ const out = ew.writeEncryptedDocument({
89
+ indirects, root: { num: 1, gen: 0 },
90
+ encrypt: {
91
+ version: 5, revision: 6,
92
+ ownerPassword: 'owner', userPassword: 'user',
93
+ permissions: -4,
94
+ randomBytes: makeDeterministicRand(1) // test-only PRNG
95
+ }
96
+ });
97
+ out.bytes; // encrypted PDF, ready to write to disk
98
+ ```
99
+
100
+ ### V=4 R=4, legacy RC4-128
101
+
102
+ ```js
103
+ const out = ew.writeEncryptedDocument({
104
+ indirects, root: { num: 1, gen: 0 },
105
+ encrypt: { version: 4, revision: 4, method: 'V2', userPassword: 'user' }
106
+ });
107
+ ```
108
+
109
+ ### Distinct cipher for embedded-file streams (`/EFF`)
110
+
111
+ ```js
112
+ const out = ew.writeEncryptedDocument({
113
+ indirects, root: { num: 1, gen: 0 },
114
+ encrypt: {
115
+ version: 5, revision: 6, method: 'AESV3',
116
+ effMethod: 'AESV4', // embedded files get AES-GCM, everything else AES-CBC
117
+ userPassword: 'user'
118
+ }
119
+ });
120
+ ```
121
+
122
+ ### Recovering the FEK to decrypt
123
+
124
+ ```js
125
+ const v6 = runtime.resolve('pdfStandardV6');
126
+ const r = v6.tryPassword(typedEncryptDict, 'user', false);
127
+ r.fileEncryptionKey; // === out.fek, when the password matches
128
+ ```
129
+
130
+ ## Errors
131
+
132
+ | Code | Class | When |
133
+ |------|-------|------|
134
+ | `pdf/crypto/enc-writer/missing-writer` | `EncryptionError` | Constructed without a `pdfWriter.writeDocument` function (module wiring). |
135
+ | `pdf/crypto/enc-writer/unsupported-version` | `EncryptionError` | `(version, revision)` outside `{4,4}`, `{5,5}`, `{5,6}`. |
136
+ | `pdf/crypto/enc-writer/missing-v4` | `EncryptionError` | `version: 4` requested but `pdfStandardV4` not supplied. |
137
+ | `pdf/crypto/enc-writer/bad-input` | `RenderError` | `opts` missing or not an object. |
138
+ | `pdf/crypto/enc-writer/no-encrypt` | `RenderError` | `opts.encrypt` missing. |
139
+ | `pdf/crypto/enc-writer/bad-method` | `RenderError` | `method` incompatible with `version` (V=4 wants AESV2/V2, V=5 wants AESV3/AESV4). |
140
+ | `pdf/crypto/enc-writer/missing-gcm` | `EncryptionError` | `method` or `effMethod` is `'AESV4'` but `pdfAesGcm` not supplied. |
141
+ | `pdf/crypto/enc-writer/bad-eff-method` | `RenderError` | `effMethod` incompatible with `version`. |
142
+ | `pdf/crypto/enc-writer/no-random` | `EncryptionError` | No `randomBytes` and no `globalThis.crypto.getRandomValues`. |
143
+ | `pdf/crypto/enc-writer/no-trailer` / `no-trailer-close` | `RenderError` | Internal: the base `writeDocument` output didn't contain a patchable trailer (should not occur in practice). |
144
+
145
+ ## See also
146
+
147
+ - [`pdfWriter`](./writer.md) — the base emitter this wraps.
148
+ - [`pdfStandardV4`](../crypto/standardV4.md) · [`pdfStandardV5`](../crypto/standardV5.md) · [`pdfStandardV6`](../crypto/standardV6.md) · [`pdfAesGcm`](../crypto/aesGcm.md)
149
+ - [`pdfSecurity`](../crypto/security.md) — the read-side dispatcher.
@@ -0,0 +1,148 @@
1
+ ---
2
+ module: pdfIncrementalWriter
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfSerializer, pdfTokenizer, pdfParser, pdfXref, pdfTrailer]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfIncrementalWriter
11
+
12
+ > Append-only incremental update — ISO 32000-2 §7.5.6.
13
+
14
+ **Module** `pdfIncrementalWriter` | **Source** `packages/front/office/pdf/src/document/incrementalWriter.js` | **Deps** `pdfErrors`, `pdfSerializer`, `pdfTokenizer`, `pdfParser`, `pdfXref`, `pdfTrailer` | **Worker-safe** yes
15
+
16
+ `appendIncremental(pdfBytes, opts)` produces a new PDF that carries the
17
+ original bytes **verbatim**, followed by an incremental-update section:
18
+ `originalBytes ‖ newObjects ‖ xref ‖ trailer (with /Prev) ‖ %%EOF`. It locates
19
+ the previous `startxref`/trailer to chain `/Prev` and carry over `/Root`,
20
+ `/Info`, `/Size`, `/ID` unless the caller overrides them, then emits a fresh
21
+ cross-reference section covering only the newly-added object numbers (one
22
+ subsection per contiguous run — object 0's free-list head is always
23
+ re-emitted), in the form the section-selection rule below picks. A reader that follows the `/Prev` chain (e.g. `pdfDocument`)
24
+ sees the new entries win over older ones automatically. This is the
25
+ non-destructive counterpart of a full re-emit: existing objects are never
26
+ patched in place, only appended to — the mechanism behind PAdES levels
27
+ T/LT/LTA (`pdfSign`) appending DSS/DocTimeStamp updates.
28
+
29
+ Scope: no ObjStm grouping; hybrid-reference bases are refused (below).
30
+
31
+ ## Section forms and the selection rule
32
+
33
+ The update's cross-reference section takes the form of the base's **newest**
34
+ section, the one the final `startxref` designates:
35
+
36
+ | Newest base section | Update written | Trailer keys come from |
37
+ |---|---|---|
38
+ | Classical `xref` table | Classical table + `trailer` dict, `/Prev` = the base's `startxref` offset. **Byte-identical** to the output of earlier versions, which wrote only this form. | The newest trailer dict alone. |
39
+ | `/Type /XRef` stream (§7.5.8) | One uncompressed `/Type /XRef` stream object (no `/Filter`), carrying `/W`, `/Index`, `/Size`, `/Prev`, `/Root` and, when known, `/Info` and `/ID`. No `trailer` keyword. The stream takes object number `max(size, prevSize, newMaxNum + 1)`, and the written `/Size` is one more. | The newest-first merge of every section's dict in the `/Prev` chain, as [`pdfDocument`](./document.md) types it. So a linearized file whose `/Root` sits in only one of its two xref streams still resolves `/Root`. |
40
+ | Hybrid-reference file: a classical trailer carrying `/XRefStm`, anywhere in the chain | **Refused**, `pdf/incremental/hybrid-base`. | — |
41
+ | Neither a table nor an xref stream | **Refused**, `pdf/incremental/unsupported-base`. | — |
42
+
43
+ Hybrid-reference bases are refused on purpose. A hybrid file carries two
44
+ cross-reference forms, so two conforming readers can resolve different
45
+ objects in it, and an update over it could read differently from viewer to
46
+ viewer. The refusal is reversible: support can be added once a real hybrid
47
+ file is available to choose and test a form against.
48
+
49
+ The emitted stream is read back by this library's own reader: an update over
50
+ a stream base re-reads with both the base objects and the appended ones
51
+ reachable (`tests/real-shapes.integration.test.js`).
52
+
53
+ ## Resolve
54
+
55
+ ```js
56
+ const iw = runtime.resolve('pdfIncrementalWriter');
57
+ // Returns: { appendIncremental, appendIncrementalWithOffsets, readBaseTrailer }
58
+ ```
59
+
60
+ ## API
61
+
62
+ | Method | Signature | Returns |
63
+ |--------|-----------|---------|
64
+ | `appendIncremental` | `(pdfBytes: Uint8Array, opts: AppendOpts) => Uint8Array` | The original bytes plus one incremental-update section. |
65
+ | `appendIncrementalWithOffsets` | `(pdfBytes: Uint8Array, opts: AppendOpts) => { bytes, offsets, xrefOffset }` | Same as `appendIncremental`: same options, same validation and refusals, and `bytes` is byte-identical to its return value. `offsets` is a `Map<num, byteOffset>` giving where each update's `num gen obj` header starts in `bytes`. `xrefOffset` is where the update's cross-reference section (table or stream object) starts, which is the offset the new `startxref` records. |
66
+ | `readBaseTrailer` | `(pdfBytes: Uint8Array) => { form, xrefOffset, trailer }` | The trailer an update over `pdfBytes` starts from. Nothing is written. `form` is `'table'` or `'stream'` (the newest section's form). `trailer` is the typed newest-first merge of every section's dict, as `pdfDocument` types it, for classical bases too. It is `null` when no section supplies a usable `/Size` and `/Root`. The base is vetted as `appendIncremental` vets it, so a hybrid-reference base throws `pdf/incremental/hybrid-base` and a `startxref` that designates neither form throws `pdf/incremental/unsupported-base`. |
67
+
68
+ `appendIncrementalWithOffsets` and `readBaseTrailer` were added for
69
+ [`pdfSign`](../sig/sign.md). The signer reads the merged `/Size`
70
+ to number its signature object. It then patches the fixed-width `/ByteRange`
71
+ placeholder inside that object, found from its offset, without changing the
72
+ byte length. Every offset recorded in the cross-reference section therefore
73
+ stays valid.
74
+
75
+ ### `AppendOpts`
76
+
77
+ ```js
78
+ {
79
+ updates: [ { num, gen?, value }, … ], // required — num >= 1
80
+ root?: { num, gen }, // defaults to the previous /Root
81
+ info?: { num, gen }, // defaults to the previous /Info
82
+ id?: [ Uint8Array, Uint8Array ], // defaults to the previous /ID
83
+ size?: number, // defaults to max(prevSize, newMaxNum + 1)
84
+ encrypt?: { num, gen } // the base's /Encrypt, repeated in the update; never defaulted
85
+ }
86
+ ```
87
+
88
+ `opts.root` is mandatory only when no section of the base supplies a usable
89
+ `/Root` (and `/Size`) — on a classical base, when the newest trailer does not.
90
+
91
+ `opts.encrypt` is the base's `/Encrypt` reference (the `{ num, gen }` that
92
+ `readBaseTrailer(...).trailer.encrypt` reports). It is written as
93
+ `/Encrypt n g R` right after `/ID`, in the trailer or in the cross-reference
94
+ stream dictionary. An update over an encrypted document needs it to
95
+ conform (ISO 32000-2 §7.5.6): every trailer of an encrypted file carries
96
+ `/Encrypt`. It is not taken from the base by default. Without it the output
97
+ is byte-identical to what it was before the option existed. A direct
98
+ `/Encrypt` dictionary (a typed `{ type: 'dict' }`) is written as it is in a
99
+ classical trailer. Over a cross-reference stream base it is refused with
100
+ `pdf/xref/bad-stream-section`.
101
+
102
+ ## Examples
103
+
104
+ ### Append a new indirect object to an existing PDF
105
+
106
+ ```js
107
+ const iw = runtime.resolve('pdfIncrementalWriter');
108
+ const updated = iw.appendIncremental(originalBytes, {
109
+ updates: [
110
+ { num: 42, gen: 0, value: { type: 'dict', entries: {
111
+ Type: { type: 'name', value: 'Example' }
112
+ } } }
113
+ ]
114
+ });
115
+ // `updated` re-parses via pdfDocument.readDocument, following /Prev.
116
+ ```
117
+
118
+ ### Update the Catalog to point at a new object (e.g. DSS)
119
+
120
+ ```js
121
+ const nextNum = 43;
122
+ const updated = iw.appendIncremental(signedBytes, {
123
+ updates: [
124
+ { num: nextNum, gen: 0, value: dssDict },
125
+ { num: 1, gen: 0, value: updatedCatalogDict } // re-defines obj 1
126
+ ],
127
+ root: { num: 1, gen: 0 }
128
+ });
129
+ ```
130
+
131
+ ## Errors
132
+
133
+ | Code | Class | When |
134
+ |------|-------|------|
135
+ | `pdf/incremental/bad-input` | `RenderError` | `pdfBytes` is not a `Uint8Array` (every member). |
136
+ | `pdf/incremental/no-updates` | `RenderError` | `opts.updates` is not an array. |
137
+ | `pdf/incremental/bad-update` | `RenderError` | An update entry lacks a finite `num >= 1`. |
138
+ | `pdf/incremental/no-startxref` | `ParseError` | `pdfBytes` has no `startxref` — not a valid PDF. |
139
+ | `pdf/incremental/no-root` | `RenderError` | `opts.root` missing and no `/Root` can be read from the base (see the table above). |
140
+ | `pdf/incremental/hybrid-base` | `RenderError` | A classical section in the base's `/Prev` chain carries `/XRefStm` (hybrid-reference file). Nothing is written. |
141
+ | `pdf/incremental/unsupported-base` | `ParseError` | `startxref` designates neither a classical `xref` table nor a `/Type /XRef` stream. Nothing is written. |
142
+ | `pdf/xref/bad-stream-section` | `RenderError` | Cross-reference stream base, and `opts.encrypt` is not an indirect reference (propagated from `pdfXref.buildXrefStream`). |
143
+
144
+ ## See also
145
+
146
+ - [`pdfWriter`](./writer.md) — full re-emit (the `{ num, gen, value }` update shape mirrors `writeDocument`'s `indirects`).
147
+ - [`pdfSign`](../sig/sign.md) — appends every signature (all levels), the LT/LTA DSS and the LTA DocTimeStamp through this module.
148
+ - [`pdfDssBuilder`](../sig/dss.md) — produces the DSS updates typically appended here.
@@ -0,0 +1,99 @@
1
+ ---
2
+ module: pdfPage
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfParser]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfPage
11
+
12
+ > Typing of a `/Type /Page` dictionary, ISO 32000-2 §7.7.3.3 — boxes, contents, rotate, annots.
13
+
14
+ **Module** `pdfPage` | **Source** `packages/front/office/pdf/src/document/page.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
15
+
16
+ Normalises a Page dictionary:
17
+
18
+ - The boxes (`MediaBox`, `CropBox`, `BleedBox`, `TrimBox`, `ArtBox`) are
19
+ flattened to `[llx, lly, urx, ury]` numeric tuples.
20
+ - `/Contents` is always exposed as `Array<{num, gen}>` (empty, single, or
21
+ multiple).
22
+ - `/Rotate` is normalised to a multiple of 90 within `[0, 270]`; an invalid
23
+ value becomes 0.
24
+ - `/Resources` is inheritable (§7.7.3.4) — not resolved here, kept raw.
25
+ - Unknown entries go to `_extras`.
26
+
27
+ ## Resolve
28
+
29
+ ```js
30
+ const page = runtime.resolve('pdfPage');
31
+ // Returns: { typePage }
32
+ ```
33
+
34
+ ## API
35
+
36
+ | Method | Signature | Returns |
37
+ |--------|-----------|---------|
38
+ | `typePage` | `(dict: PdfDict) => TypedPage` | Typed record. |
39
+
40
+ ### `TypedPage` shape
41
+
42
+ ```js
43
+ {
44
+ parent: { num, gen } | null,
45
+ mediaBox: [number, number, number, number] | null,
46
+ cropBox?: [number, number, number, number],
47
+ bleedBox?, trimBox?, artBox?: same,
48
+ resources: PdfObject | null,
49
+ contents: Array<{ num, gen }>, // always an array, sometimes empty
50
+ rotate: number, // 0 | 90 | 180 | 270
51
+ annots: Array<PdfObject>, // references or inline annotations
52
+ userUnit?: number,
53
+ tabs?: string,
54
+ metadata?: PdfRef,
55
+ group?: PdfObject,
56
+ raw: PdfDict,
57
+ _extras: Object<string, PdfObject>
58
+ }
59
+ ```
60
+
61
+ ## Examples
62
+
63
+ ### Dimensions of the first page
64
+
65
+ ```js
66
+ const doc = api.read(bytes);
67
+ const p0 = doc.pages[0];
68
+ const [llx, lly, urx, ury] = p0.mediaBox; // e.g. [0, 0, 612, 792]
69
+ console.log('rotate=', p0.rotate);
70
+ ```
71
+
72
+ ### Iterating the content streams
73
+
74
+ ```js
75
+ for (const ref of p0.contents) {
76
+ const stream = doc._raw.resolve({ type: 'ref', ...ref });
77
+ // stream.raw: Uint8Array — decode /Filter with pdfFilterDispatch
78
+ }
79
+ ```
80
+
81
+ ### Counting annotations
82
+
83
+ ```js
84
+ doc.pages.reduce((n, p) => n + p.annots.length, 0);
85
+ ```
86
+
87
+ ## Errors
88
+
89
+ | Code | Class | When |
90
+ |------|-------|------|
91
+ | `pdf/page/not-dict` | `ParseError` | Argument is not a dictionary. |
92
+ | `pdf/page/bad-type` | `ParseError` | `/Type` present but not `/Page`. |
93
+
94
+ ## See also
95
+
96
+ - [`pdfPages`](./pages.md) — produces the reference list typed here.
97
+ - [`pdfResources`](./resources.md) — resolves the inheritable `/Resources`.
98
+ - [`pdfDocument`](./document.md)
99
+ - [`pdfErrors`](../errors.md)
@@ -0,0 +1,82 @@
1
+ ---
2
+ module: pdfPages
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfParser]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfPages
11
+
12
+ > Page-tree walker, ISO 32000-2 §7.7.3 — `/Pages` tree → ordered list of leaf references.
13
+
14
+ **Module** `pdfPages` | **Source** `packages/front/office/pdf/src/document/pages.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
15
+
16
+ Descends `/Kids` recursively from the root pointed at by the Catalog. Guard
17
+ rails: maximum depth (`maxDepth = 64`), maximum page count
18
+ (`maxPages = 200000`), cycle detection through a `Set<'num:gen'>`. Tolerant of
19
+ intermediate nodes without `/Type` (present in some older PDFs): the fallback
20
+ test is the presence of `/Kids`.
21
+
22
+ ## Resolve
23
+
24
+ ```js
25
+ const pages = runtime.resolve('pdfPages');
26
+ // Returns: { walkPageTree, readPageCount }
27
+ ```
28
+
29
+ ## API
30
+
31
+ | Method | Signature | Returns |
32
+ |--------|-----------|---------|
33
+ | `walkPageTree` | `(rootRef, resolveRef, opts?: { maxDepth?, maxPages? }) => Array<{num, gen}>` | Leaf references in document order. |
34
+ | `readPageCount` | `(node: PdfDict) => number \| null` | Reads `/Count` off an intermediate node. |
35
+
36
+ `resolveRef` must accept `{ type: 'ref', num, gen }` and return the materialised
37
+ dictionary — typically `doc._raw.resolve`.
38
+
39
+ ## Examples
40
+
41
+ ### Standard walk
42
+
43
+ ```js
44
+ const pages = runtime.resolve('pdfPages');
45
+ const refs = pages.walkPageTree(doc.catalog.pages, doc._raw.resolve);
46
+ refs.length; // page count
47
+ refs[0]; // { num: 3, gen: 0 }
48
+ ```
49
+
50
+ ### `/Count` sanity check
51
+
52
+ ```js
53
+ const root = doc._raw.resolve({ type: 'ref', ...doc.catalog.pages });
54
+ const declared = pages.readPageCount(root);
55
+ const actual = pages.walkPageTree(doc.catalog.pages, doc._raw.resolve).length;
56
+ if (declared !== null && declared !== actual) {
57
+ console.warn('page tree /Count mismatch', { declared, actual });
58
+ }
59
+ ```
60
+
61
+ ### Limiting the depth
62
+
63
+ ```js
64
+ pages.walkPageTree(rootRef, resolve, { maxDepth: 16 });
65
+ ```
66
+
67
+ ## Errors
68
+
69
+ | Code | Class | When |
70
+ |------|-------|------|
71
+ | `pdf/pages/max-depth` | `ParseError` | Tree deeper than `maxDepth`. |
72
+ | `pdf/pages/cycle` | `ParseError` | Reference already visited during the walk. |
73
+ | `pdf/pages/not-dict` | `ParseError` | A resolved node is not a dictionary. |
74
+ | `pdf/pages/too-many` | `ParseError` | More than `maxPages` leaves found. |
75
+ | `pdf/pages/missing-kids` | `ParseError` | Intermediate node without `/Kids`. |
76
+ | `pdf/pages/non-ref-kid` | `ParseError` | `/Kids` holds something other than a reference. |
77
+
78
+ ## See also
79
+
80
+ - [`pdfPage`](./page.md) — types each leaf.
81
+ - [`pdfCatalog`](./catalog.md) — supplies `catalog.pages`.
82
+ - [`pdfDocument`](./document.md)
@@ -0,0 +1,102 @@
1
+ ---
2
+ module: pdfResources
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfParser]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfResources
11
+
12
+ > Resolution of a Page's or Form XObject's `/Resources` dictionary — ISO 32000-2 §7.8.3.
13
+
14
+ **Module** `pdfResources` | **Source** `packages/front/office/pdf/src/document/resources.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
15
+
16
+ Six named sub-dictionaries map the **local names** used inside a content stream
17
+ to indirect objects: `/Font`, `/XObject`, `/ColorSpace`, `/ExtGState`,
18
+ `/Pattern`, `/Shading`. A legacy `/ProcSet` is read but never required
19
+ (deprecated in PDF 2.0). Resources are **inheritable**: a Page without its own
20
+ `/Resources` walks up the page tree's `/Parent` chain (§7.7.3.4).
21
+ `resolvePageResources` implements that walk with a cycle guard.
22
+
23
+ Any category value may itself be an indirect reference (§7.3.10). Real
24
+ documents do this: a measured ANSSI guide carries `/ExtGState` as
25
+ `N 0 R` on 56 of its 58 pages. Rejecting that used to throw away the
26
+ page's whole resource map, fonts included. The resolver you pass reaches
27
+ objects inside object streams,
28
+ because it is the document's own `_raw.resolve`.
29
+
30
+ ## Resolve
31
+
32
+ ```js
33
+ const r = runtime.resolve('pdfResources');
34
+ // Returns: { typeResources, resolvePageResources, lookupResource }
35
+ ```
36
+
37
+ ## API
38
+
39
+ | Method | Signature | Returns |
40
+ |--------|-----------|---------|
41
+ | `typeResources` | `(dict\|null, resolveRef?) => Resources` | Direct typing. With `resolveRef`, an indirect category (`/Font 12 0 R`) is resolved through it; a category that resolves to `null` is treated as absent. |
42
+ | `resolvePageResources` | `(pageDict, resolveRef) => Resources` | Inherited walk, at most 64 levels; passes `resolveRef` on to `typeResources`. |
43
+ | `lookupResource` | `(resources, category, name, resolveRef?) => object` | Named lookup. |
44
+
45
+ ### `Resources` shape
46
+
47
+ ```js
48
+ {
49
+ Font: { [name]: PdfObject },
50
+ XObject: { [name]: PdfObject },
51
+ ColorSpace: { [name]: PdfObject },
52
+ ExtGState: { [name]: PdfObject },
53
+ Pattern: { [name]: PdfObject },
54
+ Shading: { [name]: PdfObject },
55
+ ProcSet: string[] | null,
56
+ raw: object | null
57
+ }
58
+ ```
59
+
60
+ `lookupResource` returns the resolved object directly (ref → object) when
61
+ `resolveRef` is supplied, otherwise the typed entry (possibly a `ref`).
62
+
63
+ ## Examples
64
+
65
+ ### Page → Resources
66
+
67
+ ```js
68
+ const r = runtime.resolve('pdfResources');
69
+ const res = r.resolvePageResources(pageDict, doc._raw.resolve);
70
+ res.Font; // { F1: <typed font dict>, F2: … }
71
+ res.ExtGState; // { GS1: … }
72
+ ```
73
+
74
+ ### Look up a named font
75
+
76
+ ```js
77
+ const fontDict = r.lookupResource(res, 'Font', 'F1', doc._raw.resolve);
78
+ const typed = runtime.resolve('pdfFont').typeFont(fontDict);
79
+ ```
80
+
81
+ ### Direct typing without the walk
82
+
83
+ ```js
84
+ const res = r.typeResources(pageDict.entries.Resources);
85
+ ```
86
+
87
+ ## Errors
88
+
89
+ | Code | Class | When |
90
+ |------|-------|------|
91
+ | `pdf/resources/not-dict` | `ParseError` | `/Resources` is not a dictionary. |
92
+ | `pdf/resources/bad-subdict` | `ParseError` | A sub-dictionary (`/Font`, …) is not a dictionary — or it is an indirect reference and no `resolveRef` was supplied. |
93
+ | `pdf/resources/bad-shape` | `ParseError` | `/Resources` is neither a dictionary nor a reference. |
94
+ | `pdf/resources/cycle` | `ParseError` | Cycle detected in the `/Parent` chain. |
95
+ | `pdf/resources/unknown-category` | `ParseError` | Invalid category passed to `lookupResource`. |
96
+ | `pdf/resources/missing-name` | `ParseError` | Name not found in the category. |
97
+
98
+ ## See also
99
+
100
+ - [`pdfPage`](./page.md) — supplies `pageDict`.
101
+ - [`pdfPages`](./pages.md) — page-tree walk.
102
+ - [`pdfFont`](../font/font.md), [`pdfImages`](../content/images.md) — typers for the resolved entries.