@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,281 @@
1
+ ---
2
+ module: pdfBuilder
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfParserObj, pdfWriter]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfBuilder
11
+
12
+ > Chainable constructive DSL for assembling a PDF document from scratch.
13
+
14
+ **Module** `pdfBuilder` | **Source** `packages/front/office/pdf/src/document/builder.js` | **Deps** `pdfErrors`, `pdfParserObj`, `pdfWriter` | **Worker-safe** yes
15
+
16
+ An ergonomic layer over `pdfWriter.writeDocument`: instead of hand-assembling
17
+ a typed indirect-object graph, `builder()` returns a chainable object
18
+ (`addPage` → `addContent`/`addFont`/`addImage` → … → `build()`) that tracks
19
+ pages, content streams, fonts (referenced **or** [embedded](#embedded-fonts)),
20
+ [image XObjects](#images) and the Info dict internally, then
21
+ emits `Uint8Array` bytes on `.build()`. The returned chain is closure-based
22
+ (no `class`, no `this`), so it stays worker-transportable.
23
+
24
+ ## Resolve
25
+
26
+ ```js
27
+ const b = runtime.resolve('pdfBuilder');
28
+ // Returns: { builder }
29
+ const doc = b.builder();
30
+ // doc: { addPage, addContent, addFont, addImage, addMetadata, setVersion, setId, build }
31
+ ```
32
+
33
+ ## API
34
+
35
+ | Method | Signature | Returns |
36
+ |--------|-----------|---------|
37
+ | `builder` | `() => Builder` | Creates a fresh chainable builder (own closure state — call once per document). |
38
+
39
+ ### `Builder` chain
40
+
41
+ | Method | Signature | Notes |
42
+ |--------|-----------|-------|
43
+ | `addPage` | `(opts?: { mediaBox?: number[4], cropBox?: number[4], rotate?: number, resources?: DictObj }) => Builder` | Starts a new page (default `mediaBox` is US Letter `[0,0,612,792]`); becomes the target of subsequent `addContent`/`addFont` calls. |
44
+ | `addContent` | `(data: string \| Uint8Array) => Builder` | Appends one content stream to the **current** page. |
45
+ | `addFont` | `(spec: { name: string, baseFont: string, subtype?: string, encoding?: 'WinAnsiEncoding' \| 'MacRomanEncoding' \| 'StandardEncoding' }) => Builder` | **Legacy shape** — registers a non-embedded font reference (`subtype` defaults to `Type1`) into the current page's `/Resources /Font`. The font dictionary is allocated once per distinct `(baseFont, subtype, encoding)` and shared by every page that registers it. Without `encoding` the emitted bytes are frozen. |
46
+ | `addFont` | `(spec: { name: string, embedded: SimpleEmbed \| CidEmbed }) => Builder` | **Embedded shape** — takes a [`pdfFontEmbed`](../font/embed.md) result and allocates every indirect it needs (see [Embedded fonts](#embedded-fonts)). Exactly one of `baseFont` / `embedded` must be given. |
47
+ | `addImage` | `(spec: { name, width, height, colorSpace, bitsPerComponent, data, filter?, decodeParms?, sMask? }) => Builder` | Allocates an **image XObject** as an indirect stream and registers it into the current page's `/Resources /XObject` (see [Images](#images)). Decodes nothing; emits no content operator. |
48
+ | `addMetadata` | `(meta: object) => Builder` | Merges Info-dict fields. `Title`/`Author`/`Subject`/`Keywords`/`Creator`/`Producer`/`CreationDate`/`ModDate` are always emitted as PDF strings; other keys are kept only if their value is already a string. |
49
+ | `setVersion` | `(v: string) => Builder` | Overrides the PDF header version (default `'2.0'`); must match `/^\d\.\d$/`. |
50
+ | `setId` | `(a: string \| Uint8Array, b?: string \| Uint8Array) => Builder` | Sets the `/ID` pair — hex string or raw bytes; `b` defaults to `a`. |
51
+ | `build` | `() => Uint8Array` | Assembles Catalog + Pages tree + page objects + Info (if any), then calls `pdfWriter.writeDocument`. |
52
+
53
+ Every chain method except `build` returns the same `Builder` instance.
54
+
55
+ ### `addFont` spec — non-embedded shape
56
+
57
+ | Key | Type | Notes |
58
+ |-----|------|-------|
59
+ | `name` | `string` | Resource name registered under the page's `/Resources /Font` (e.g. `F1`). Required. |
60
+ | `baseFont` | `string` | `/BaseFont` name (e.g. `Helvetica`). Exactly one of `baseFont` / `embedded`. |
61
+ | `subtype` | `string` | `/Subtype`; defaults to `Type1`. |
62
+ | `encoding` | `'WinAnsiEncoding' \| 'MacRomanEncoding' \| 'StandardEncoding'` | Optional. One of the three predefined simple-font encodings of ISO 32000-1 § 9.6.6 / Annex D, emitted as `/Encoding /<name>` after the existing keys: `<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>`. Absent (or `undefined`) emits no `/Encoding` key and the bytes are identical to a spec without the option — the default is unchanged. Any other value, or `encoding` combined with `embedded`, throws `pdf/builder/bad-font` with `{ name, encoding }` in its `context`. No `/Differences` or custom encoding dictionaries. |
63
+
64
+ **Shared dictionary.** A non-embedded font dictionary is allocated once per
65
+ distinct `(baseFont, subtype, encoding)` and shared by every page that
66
+ registers it: `subtype` is the defaulted value, so `{ baseFont: 'Helvetica' }`
67
+ and `{ baseFont: 'Helvetica', subtype: 'Type1' }` share one object. Each page
68
+ (and each resource name) still gets its own `/Resources /Font` entry; only the
69
+ referenced object is shared. A 3-page document that registers the same four
70
+ faces on every page therefore carries 4 font dictionaries, not 12. A document
71
+ that never repeats a `(baseFont, subtype, encoding)` triple is byte-identical to
72
+ one built without sharing.
73
+
74
+ ## Examples
75
+
76
+ ### Minimal one-page document
77
+
78
+ ```js
79
+ const { builder } = runtime.resolve('pdfBuilder');
80
+ const bytes = builder()
81
+ .addPage({ mediaBox: [0, 0, 612, 792] })
82
+ .build();
83
+ ```
84
+
85
+ ### Page with a font and content stream
86
+
87
+ ```js
88
+ const bytes = builder()
89
+ .addPage({ mediaBox: [0, 0, 612, 792] })
90
+ .addFont({ name: 'F1', baseFont: 'Helvetica', subtype: 'Type1' })
91
+ .addContent('BT /F1 12 Tf 100 700 Td (Hello) Tj ET')
92
+ .build();
93
+ ```
94
+
95
+ ### Metadata + explicit `/ID`
96
+
97
+ ```js
98
+ const bytes = builder()
99
+ .addPage()
100
+ .addMetadata({ Title: 'Demo', Author: 'awa' })
101
+ .setId('0102030405060708090a0b0c0d0e0f10')
102
+ .build();
103
+ ```
104
+
105
+ ## Embedded fonts
106
+
107
+ `addFont({ name, embedded })` accepts a [`pdfFontEmbed`](../font/embed.md)
108
+ result — `embedSimple` (a `SimpleEmbed`: `/TrueType` + `/WinAnsiEncoding`) or
109
+ `embedCid` (a `CidEmbed`: `/Type0` + `/Identity-H` + `/CIDFontType2`). The
110
+ adapter deliberately returns **inline** dicts and leaves every indirect to its
111
+ consumer; the builder is that consumer.
112
+
113
+ An `embedded` value must carry `fontFile` (`Uint8Array`), `descriptor`,
114
+ `toUnicodeStream` and either `fontDict` **or** `type0Dict` + `cidFontDict` —
115
+ never both — else `pdf/builder/bad-font`.
116
+
117
+ ### What gets allocated
118
+
119
+ Per **embed result object**, not per `addFont` call:
120
+
121
+ | # | Indirect | Content | Route |
122
+ |---|----------|---------|-------|
123
+ | 1 | font-program stream | `<< /Length1 <fontFile.length> >>` (plus `/Subtype /OpenType` when `fontFileKey` is `FontFile3`) over `embedded.fontFile` | both |
124
+ | 2 | `FontDescriptor` | `embedded.descriptor` **cloned**, with `[fontFileKey] → 1 0 R` added | both |
125
+ | 3 | `/ToUnicode` | `embedded.toUnicodeStream` (the serializer refuses an inline stream) | both |
126
+ | 4 | `CIDFont` | `embedded.cidFontDict` cloned, `/FontDescriptor → 2 0 R` | CID only |
127
+ | 5 | font object | simple: `embedded.fontDict` cloned, `/FontDescriptor → 2 0 R`, `/ToUnicode → 3 0 R` · CID: `embedded.type0Dict` cloned, `/DescendantFonts [4 0 R]`, `/ToUnicode → 3 0 R` | both |
128
+
129
+ So a simple embedding costs **4** indirects and a composite one **5** — i.e.
130
+ **+3** and **+4** over the single object a legacy `addFont` allocates. Only
131
+ the last one lands in the page's `/Resources /Font`.
132
+
133
+ **Identity cache.** The builder keeps a `WeakMap` keyed by the `embedded`
134
+ object, so registering the *same* result on several pages (under any resource
135
+ names) allocates the graph **once** and every page references the same font
136
+ object number. Two distinct results — even from the same face — are two
137
+ graphs.
138
+
139
+ **No mutation.** Every patched dict is shallow-cloned; the caller's
140
+ `descriptor` / `fontDict` / `type0Dict` / `cidFontDict` come back exactly as
141
+ `pdfFontEmbed` returned them, so one result can be reused across builders.
142
+
143
+ ### Example — `pdfFontEmbed` → `addFont` → `addContent`
144
+
145
+ ```js
146
+ const fontsMod = runtime.resolve('fonts');
147
+ const embed = runtime.resolve('pdfFontEmbed');
148
+ const { builder } = runtime.resolve('pdfBuilder');
149
+
150
+ const face = fontsMod.read(ttfBytes);
151
+ const text = 'Unicode fi ⁄ ⁴';
152
+ const cps = [...new Set([...text].map(c => c.codePointAt(0)))];
153
+
154
+ const e = embed.embedCid(face, cps); // or embedSimple for WinAnsi
155
+ const hex = [...e.encode(text)]
156
+ .map(b => b.toString(16).padStart(2, '0')).join('');
157
+
158
+ const bytes = builder()
159
+ .addPage({ mediaBox: [0, 0, 612, 792] })
160
+ .addFont({ name: 'F1', embedded: e })
161
+ .addContent(`BT /F1 12 Tf 72 700 Td <${hex}> Tj ET`)
162
+ .build();
163
+ ```
164
+
165
+ `e.encode(text)` yields the character codes the written font expects — WinAnsi
166
+ bytes for the simple route, big-endian 2-byte CIDs for `Identity-H` — and
167
+ `e.widthOf(codePoint)` gives the 1000/em advance for layout.
168
+
169
+ ## Images
170
+
171
+ `addImage({ name, … })` is the image counterpart of `addFont`'s embedded
172
+ route: it allocates the image as an **indirect stream object** — the
173
+ serializer refuses an inline one — and maps `name` to it in the current
174
+ page's `/Resources /XObject`.
175
+
176
+ **The seam decodes nothing.** The caller supplies data that is *already*
177
+ encoded plus the parameters that describe it. This module does not parse a
178
+ PNG `IHDR`, a JPEG `SOF`, or anything else; it does not transcode, resample
179
+ or colour-manage, and it never inspects `data` — the bytes reach the file
180
+ verbatim. Choosing `/Filter`, `/ColorSpace` and `/BitsPerComponent`
181
+ consistently with those bytes is the caller's job.
182
+
183
+ **And it places no ink.** `addImage` makes the resource *reachable*; drawing
184
+ it is a content-stream matter, so the caller emits the operators itself (see
185
+ the snippet below).
186
+
187
+ ### Spec
188
+
189
+ | Key | Type | `/Key` | Notes |
190
+ |-----|------|--------|-------|
191
+ | `name` | `string` | — | Resource name **without** the leading slash (e.g. `'Im0'`); non-empty. |
192
+ | `width` | `number` | `/Width` | Positive safe integer. |
193
+ | `height` | `number` | `/Height` | Positive safe integer. |
194
+ | `colorSpace` | `string` | `/ColorSpace` | Emitted as a **name** (e.g. `'DeviceRGB'`, `'DeviceGray'`); non-empty. |
195
+ | `bitsPerComponent` | `number` | `/BitsPerComponent` | Positive safe integer. |
196
+ | `data` | `Uint8Array` | stream body | The encoded bytes, verbatim; `/Length` is added by the serializer. |
197
+ | `filter` | `string?` | `/Filter` | Emitted as a name (e.g. `'DCTDecode'`, `'FlateDecode'`). Omit for unfiltered data — then no `/Filter` is written. |
198
+ | `decodeParms` | `DictObj?` | `/DecodeParms` | **Passthrough** — must already be a typed `obj.dict`, exactly like `addPage`'s `resources`. |
199
+ | `sMask` | `object?` | `/SMask` | A soft mask: the same spec shape **minus `name`**, and with **no nested `sMask`**. |
200
+
201
+ The emitted dict is
202
+ `<< /Type /XObject /Subtype /Image /Width … /Height … /ColorSpace … /BitsPerComponent … >>`,
203
+ plus `/Filter`, `/DecodeParms` and `/SMask` when those were given.
204
+
205
+ ### Soft masks
206
+
207
+ An `sMask` is allocated **first**, as its own image XObject, and the parent's
208
+ `/SMask` holds a reference to it. It is *referenced, never named*: it does
209
+ **not** appear in the page's `/XObject` dict, so no content operator can draw
210
+ it directly. A masked image therefore costs **2** indirects instead of 1.
211
+
212
+ ```js
213
+ builder().addPage()
214
+ .addImage({
215
+ name: 'Im0', width: w, height: h,
216
+ colorSpace: 'DeviceRGB', bitsPerComponent: 8,
217
+ filter: 'FlateDecode', data: rgbDeflated,
218
+ sMask: { // no `name` here
219
+ width: w, height: h,
220
+ colorSpace: 'DeviceGray', bitsPerComponent: 8,
221
+ filter: 'FlateDecode', data: alphaDeflated
222
+ }
223
+ })
224
+ .build();
225
+ ```
226
+
227
+ ### Resource precedence
228
+
229
+ `/XObject` follows the pre-existing `/Font` rule exactly: `addPage`'s
230
+ `resources` passthrough is merged **after** the built resource classes and
231
+ only fills keys the builder did not produce. So on a page that called
232
+ `addImage`, a caller-supplied `/XObject` is dropped; on a page that did not,
233
+ it passes through untouched. Nothing about that rule changed.
234
+
235
+ ### Example — place a JPEG on the page
236
+
237
+ ```js
238
+ const bytes = builder()
239
+ .addPage({ mediaBox: [0, 0, 612, 792] })
240
+ .addImage({
241
+ name: 'Im0',
242
+ width: 800, height: 600, // the image's own pixel size
243
+ colorSpace: 'DeviceRGB',
244
+ bitsPerComponent: 8,
245
+ filter: 'DCTDecode', // the bytes ARE a JPEG already
246
+ data: jpegBytes
247
+ })
248
+ // The seam placed the resource; the caller places the ink.
249
+ // `cm` is width height 0 0 x y in USER SPACE units, not pixels:
250
+ // 400x300 pt with its lower-left corner at (100, 400).
251
+ .addContent('q 400 0 0 300 100 400 cm /Im0 Do Q')
252
+ .build();
253
+ ```
254
+
255
+ `q … Q` brackets the transform so the CTM is restored afterwards; the image
256
+ XObject's own space is the unit square, which is why the `cm` matrix carries
257
+ the on-page size directly.
258
+
259
+ ## Errors
260
+
261
+ | Code | Class | When |
262
+ |------|-------|------|
263
+ | `pdf/builder/no-page` | `RenderError` | `addContent`, `addFont` or `addImage` called before any `addPage`. |
264
+ | `pdf/builder/bad-bytes` | `RenderError` | `addContent` data is neither `string` nor `Uint8Array`. |
265
+ | `pdf/builder/bad-font` | `RenderError` | `addFont` spec has no `name`; or neither / both of `baseFont` and `embedded`; or an `embedded` value that is not a well-formed `pdfFontEmbed` result; or an `encoding` that is not one of the three predefined names, or is combined with `embedded`. |
266
+ | `pdf/builder/bad-image` | `RenderError` | `addImage` spec is not an object, or one of `name` / `width` / `height` / `colorSpace` / `bitsPerComponent` / `data` / `filter` / `decodeParms` is missing or ill-typed, or an `sMask` carries a nested `sMask`. `err.context.keys` lists the offending keys; `err.context.sMask` is `true` when the failure is on the mask leg. |
267
+ | `pdf/builder/bad-metadata` | `RenderError` | `addMetadata` argument is not an object. |
268
+ | `pdf/builder/bad-version` | `RenderError` | `setVersion` value doesn't match `/^\d\.\d$/`. |
269
+ | `pdf/builder/bad-id` | `RenderError` | `setId` part is neither hex string nor `Uint8Array`. |
270
+ | `pdf/builder/bad-id-hex` | `RenderError` | `setId` hex string has odd length. |
271
+ | `pdf/builder/bad-box` | `RenderError` | `mediaBox`/`cropBox` is not a 4-element array. |
272
+ | `pdf/builder/no-pages` | `RenderError` | `build()` called with zero pages added. |
273
+
274
+ It also propagates every code from [`pdfWriter`](./writer.md) (raised inside `writeDocument`).
275
+
276
+ ## See also
277
+
278
+ - [`pdfWriter`](./writer.md) — the underlying emitter.
279
+ - [`pdfFontEmbed`](../font/embed.md) — produces the `embedded` value (`embedSimple` / `embedCid`).
280
+ - [`pdfParserObj`](../syntax/parser-obj.md) — typed-object constructors (`obj.dict`, `obj.ref`, …) used internally.
281
+ - [`pdfIncrementalWriter`](./incrementalWriter.md) · [`pdfEncryptedWriter`](./encryptedWriter.md)
@@ -0,0 +1,98 @@
1
+ ---
2
+ module: pdfCatalog
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfParser]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfCatalog
11
+
12
+ > Typing of the `/Type /Catalog` dictionary, ISO 32000-2 §7.7.2 — root of the document tree.
13
+
14
+ **Module** `pdfCatalog` | **Source** `packages/front/office/pdf/src/document/catalog.js` | **Deps** `pdfErrors`, `pdfParser` | **Worker-safe** yes
15
+
16
+ Extracts the canonical entries of the root dictionary referenced by
17
+ `trailer.root`. Unrecognised entries are preserved in `_extras` — useful for
18
+ extensions and non-destructive round trips. `/Type` is validated strictly (when
19
+ present it must be `/Catalog`) so that a bad xref offset cannot silently type an
20
+ arbitrary dictionary as the catalog.
21
+
22
+ ## Resolve
23
+
24
+ ```js
25
+ const cat = runtime.resolve('pdfCatalog');
26
+ // Returns: { typeCatalog }
27
+ ```
28
+
29
+ ## API
30
+
31
+ | Method | Signature | Returns |
32
+ |--------|-----------|---------|
33
+ | `typeCatalog` | `(dict: PdfDict) => TypedCatalog` | Typed record. |
34
+
35
+ ### `TypedCatalog` shape
36
+
37
+ ```js
38
+ {
39
+ pages: { num, gen }, // /Pages — required
40
+ version?: string, // /Version (overrides the header)
41
+ pageLayout?: string, // /PageLayout
42
+ pageMode?: string, // /PageMode
43
+ lang?: string, // /Lang
44
+ outlines?: PdfRef, // /Outlines
45
+ metadata?: PdfRef, // /Metadata (XMP stream)
46
+ structTreeRoot?: PdfRef, // /StructTreeRoot (tagged PDF)
47
+ acroForm?: PdfObject, // /AcroForm
48
+ names?: PdfObject, // /Names
49
+ dests?: PdfObject, // /Dests
50
+ viewerPrefs?: PdfObject, // /ViewerPreferences
51
+ pageLabels?: PdfObject, // /PageLabels
52
+ markInfo?: PdfObject, // /MarkInfo
53
+ ocProperties?: PdfObject, // /OCProperties
54
+ outputIntents?: PdfObject, // /OutputIntents
55
+ raw: PdfDict,
56
+ _extras: Object<string, PdfObject>
57
+ }
58
+ ```
59
+
60
+ ## Examples
61
+
62
+ ### Reaching the Catalog
63
+
64
+ ```js
65
+ const doc = api.read(bytes);
66
+ doc.catalog.pages; // { num, gen } — page-tree root
67
+ doc.catalog.metadata; // reference to the XMP stream, when present
68
+ ```
69
+
70
+ ### Following the Outlines reference
71
+
72
+ ```js
73
+ if (doc.catalog.outlines) {
74
+ const root = doc._raw.resolve(doc.catalog.outlines);
75
+ const items = runtime.resolve('pdfOutline').walkOutline(root, doc._raw.resolve);
76
+ }
77
+ ```
78
+
79
+ ### Inspecting `_extras`
80
+
81
+ ```js
82
+ Object.keys(doc.catalog._extras);
83
+ // e.g. ['MyProprietaryKey'] when the PDF carries an entry outside §7.7.2
84
+ ```
85
+
86
+ ## Errors
87
+
88
+ | Code | Class | When |
89
+ |------|-------|------|
90
+ | `pdf/catalog/not-dict` | `ParseError` | Argument is not a dictionary. |
91
+ | `pdf/catalog/bad-type` | `ParseError` | `/Type` present but not `/Catalog`. |
92
+ | `pdf/catalog/missing-pages` | `ParseError` | `/Pages` missing or not a reference. |
93
+
94
+ ## See also
95
+
96
+ - [`pdfPages`](./pages.md) — consumes `catalog.pages` as its root.
97
+ - [`pdfDocument`](./document.md)
98
+ - [`pdfErrors`](../errors.md)
@@ -0,0 +1,187 @@
1
+ ---
2
+ module: pdfDocument
3
+ category: pdf/document
4
+ dependencies: [pdfErrors, pdfTokenizer, pdfParser, pdfXref, pdfTrailer, pdfCatalog, pdfPage, pdfPages, pdfCrossRefStream, pdfObjStream, pdfFilterDispatch]
5
+ returns: object
6
+ worker-safe: true
7
+ status: complete
8
+ ---
9
+
10
+ # pdfDocument
11
+
12
+ > Top-level read orchestrator — `Uint8Array` → navigable typed model.
13
+
14
+ **Module** `pdfDocument` | **Source** `packages/front/office/pdf/src/document/document.js` | **Deps** `pdfErrors`, `pdfTokenizer`, `pdfParser`, `pdfXref`, `pdfTrailer`, `pdfCatalog`, `pdfPage`, `pdfPages`, `pdfCrossRefStream`, `pdfObjStream`, `pdfFilterDispatch` | **Worker-safe** yes
15
+
16
+ Full pipeline: header → xref (chaining `/Prev`, at most 32 sections) → trailer →
17
+ catalog → pages. It builds an **indirect resolver** (`doc._raw.resolve`) backed
18
+ by a `Map<'num:gen'>` cache.
19
+
20
+ Both cross-reference forms are read automatically. At each `startxref` /
21
+ `/Prev` offset the walk looks at the bytes: an `xref` keyword takes the
22
+ classical table path, anything else is parsed as a `/Type /XRef`
23
+ cross-reference stream through [`pdfCrossRefStream`](../syntax/crossRefStream.md)
24
+ (§7.5.8), so mixed chains — a signed file whose classical incremental section
25
+ chains back into an xref-stream base, or the reverse — resolve end to end. A
26
+ classical trailer carrying `/XRefStm` (hybrid-reference file, §7.5.8.4) also
27
+ has its companion stream merged, without overriding the entries the table
28
+ itself provides. Objects stored inside a `/Type /ObjStm` container (§7.5.7)
29
+ are materialised on demand through [`pdfObjStream`](../syntax/objStream.md),
30
+ each container being decoded once per document.
31
+
32
+ The cross-reference stream is decoded through
33
+ [`pdfFilterDispatch`](../syntax/filters/dispatch.md), which hands its
34
+ `/DecodeParms` to the decoder as plain values, so a `/Predictor 12` xref stream
35
+ (the shape most PDF 1.5+ producers emit) is un-predicted before its entries
36
+ are read.
37
+
38
+ **Trailer merge across sections.** The trailer `readDocument`
39
+ returns is the merge of every section's trailer dict, newest first. The
40
+ newest dict is kept whole. Each document key it lacks (`/Root`, `/Info`,
41
+ `/ID`, `/Encrypt`, `/Size`) comes from the newest older section that carries
42
+ it. Section-local keys are never inherited: `/Prev`, `/XRefStm`, and a
43
+ cross-reference stream's `/Type`, `/W`, `/Index`, `/Length` and filter
44
+ entries. Each section's own `/Prev` drives the walk. So a linearized file
45
+ whose main xref stream omits `/Root` reads, and so does an incremental update
46
+ that omits it. A chain where **no** section supplies `/Root` still throws
47
+ `pdf/trailer/missing-root`.
48
+
49
+ **Free entries.** Sometimes the winning (newest) xref entry of a
50
+ referenced object is free. The resolver then uses the newest section that
51
+ still defines the object, and records `pdf/document/free-entry-fallback` in
52
+ `doc.losses`. When every section marks the object free, the resolver records
53
+ `pdf/document/free-object` and the reference reads as the null object
54
+ (ISO 32000-2 §7.3.10). A page-tree kid in that state contributes no page. A
55
+ `/Root` that is free in every section is still refused with
56
+ `pdf/document/free-object`.
57
+
58
+ ## Resolve
59
+
60
+ ```js
61
+ const docMod = runtime.resolve('pdfDocument');
62
+ // Returns: { readDocument, readHeader }
63
+ ```
64
+
65
+ ## API
66
+
67
+ | Method | Signature | Returns |
68
+ |--------|-----------|---------|
69
+ | `readDocument` | `(bytes: Uint8Array, opts?: { allowEncrypted?: boolean }) => Document` | Full model. |
70
+ | `readHeader` | `(bytes: Uint8Array) => { version, end }` | Header only. |
71
+
72
+ ### `Document` shape
73
+
74
+ ```js
75
+ {
76
+ version: string, // '2.0', '1.7', …
77
+ catalog: TypedCatalog, // see pdfCatalog
78
+ pages: TypedPage[], // already resolved and typed
79
+ trailer: TypedTrailer, // see pdfTrailer
80
+ xref: {
81
+ // classical entries: { offset, gen, free }
82
+ // xref-stream entries also carry `type` (0 | 1 | 2); a type-2
83
+ // entry is { type: 2, objStm, index, offset: 0, gen: 0, free }
84
+ entries: { [num]: { offset, gen, free, type? } },
85
+ sections: Array<{ at, kind, entries }> // kind: 'table' | 'stream'
86
+ },
87
+ // Read-path degradations, e.g. 'pdf/document/free-entry-fallback',
88
+ // 'pdf/document/free-object'. Live: later _raw.resolve calls append to it.
89
+ losses: Array<{ code, message, context }>,
90
+ _raw: {
91
+ resolve: (ref) => PdfObject, // generic cached resolver
92
+ bytes: Uint8Array,
93
+ headerEnd: number,
94
+ // an object materialised from an object stream carries
95
+ // `objStm` (the container's object number) and `offset: 0`
96
+ indirects: Map<'num:gen', { value, offset, objStm? }>
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Examples
102
+
103
+ ### Full read
104
+
105
+ ```js
106
+ const docMod = runtime.resolve('pdfDocument');
107
+ const doc = docMod.readDocument(bytes);
108
+ console.log(doc.version, doc.pages.length);
109
+ ```
110
+
111
+ ### Header only
112
+
113
+ ```js
114
+ docMod.readHeader(bytes);
115
+ // → { version: '2.0', end: 9 }
116
+ ```
117
+
118
+ ### Resolve an arbitrary reference
119
+
120
+ ```js
121
+ if (doc.catalog.metadata) {
122
+ const xmp = doc._raw.resolve(doc.catalog.metadata);
123
+ // xmp.type === 'stream'; xmp.raw === XMP Uint8Array
124
+ }
125
+ ```
126
+
127
+ ## Encrypted documents
128
+
129
+ `readDocument` fails loud on an encrypted input: when the
130
+ trailer carries `/Encrypt`, it throws `pdf/document/encrypted` instead
131
+ of silently returning a model whose strings and streams are still
132
+ ciphertext. Pass `{ allowEncrypted: true }` to opt into today's raw
133
+ behaviour (the object graph is returned unmodified — no decrypt is
134
+ performed):
135
+
136
+ ```js
137
+ try {
138
+ docMod.readDocument(bytes);
139
+ } catch (e) {
140
+ if (e.code === 'pdf/document/encrypted') {
141
+ // bytes are encrypted; no decrypt path is composed here.
142
+ }
143
+ }
144
+
145
+ // Explicit opt-out — returns the raw (still-encrypted) container:
146
+ const raw = docMod.readDocument(bytes, { allowEncrypted: true });
147
+ ```
148
+
149
+ The full compose-decrypt read path (password API, V4/V5/V6 handler
150
+ selection, per-object decrypt through `resolveByKey`) is **not provided**
151
+ by this module — it only fails loud on an encrypted input.
152
+
153
+ ## Errors
154
+
155
+ | Code | Class | When |
156
+ |------|-------|------|
157
+ | `pdf/document/short` | `ParseError` | Input shorter than 8 bytes. |
158
+ | `pdf/document/bad-header` | `ParseError` | No `%PDF-` in the first 1024 bytes. |
159
+ | `pdf/document/bad-input` | `ParseError` | Argument is not a `Uint8Array`. |
160
+ | `pdf/document/no-startxref` | `ParseError` | No `startxref` at the end of the file. |
161
+ | `pdf/document/no-trailer` | `ParseError` | No usable trailer. |
162
+ | `pdf/document/encrypted` | `ParseError` | Trailer carries `/Encrypt` and `opts.allowEncrypted` is not `true`. |
163
+ | `pdf/document/missing-xref` | `ParseError` | Reference absent from the table. |
164
+ | `pdf/document/free-object` | `ParseError` | The catalog (`/Root`) is free in every xref section. Any other free reference is recorded in `doc.losses` instead of thrown. |
165
+ | `pdf/document/bad-offset` | `ParseError` | Xref offset out of range. |
166
+ | `pdf/document/xref-mismatch` | `ParseError` | The definition at the offset does not match the expected `num gen`. |
167
+ | `pdf/document/bad-xref-section` | `ParseError` | The bytes at a `startxref` / `/Prev` / `/XRefStm` offset are neither an `xref` table nor a `/Type /XRef` stream. |
168
+ | `pdf/document/xrefstm-indirect-length` | `ParseError` | A cross-reference stream uses an indirect `/Length`, which cannot be resolved before the xref exists. |
169
+ | `pdf/document/xref-stream-unwired` | `ParseError` | The instance was built without `pdfCrossRefStream`, `pdfObjStream` and `pdfFilterDispatch`, and the input needs the stream path. |
170
+ | `pdf/document/objstm-nested` | `ParseError` | An object stream is itself stored inside another object stream. |
171
+ | `pdf/document/objstm-not-stream` | `ParseError` | The object a type-2 entry names as its container is not a stream. |
172
+ | `pdf/document/objstm-mismatch` | `ParseError` | The container member at the entry's index carries another object number. |
173
+ | `pdf/document/objstm-encrypted` | `ParseError` | A compressed object was reached under `allowEncrypted` — no decrypt path is composed. |
174
+
175
+ It also propagates every code from [`pdfXref`](../syntax/xref.md),
176
+ [`pdfTrailer`](../syntax/trailer.md), [`pdfCatalog`](./catalog.md),
177
+ [`pdfPages`](./pages.md), [`pdfPage`](./page.md),
178
+ [`pdfCrossRefStream`](../syntax/crossRefStream.md),
179
+ [`pdfObjStream`](../syntax/objStream.md) and
180
+ [`pdfFilterDispatch`](../syntax/filters/dispatch.md).
181
+
182
+ ## See also
183
+
184
+ - [`pdf`](../pdf.md) — wraps `readDocument` behind `.read()`.
185
+ - [Read pipeline](../../guide/read-pdf.md)
186
+ - [Coverage](../../guide/coverage.md)
187
+ - [`pdfErrors`](../errors.md)