@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,113 @@
1
+ # Coverage
2
+
3
+ What `@awacloud/pdf` covers of ISO 32000-2:2020 (PDF 2.0), of the ISO
4
+ technical specifications around it and of PDF 1.7 legacy reading — chapter
5
+ by chapter, with the caveats that bound each claim.
6
+
7
+ **Prerequisites** — the package `@awacloud/pdf` (root entry, plus the
8
+ `extra/*` modules or one of the three bundles for the rows marked "via
9
+ extra"); any modern JavaScript runtime. See
10
+ [`CHANGELOG.md`](../../CHANGELOG.md) for the module list.
11
+
12
+ ## Coverage — ISO 32000-2:2020
13
+
14
+ | Chapter | Domain | Coverage |
15
+ |----------|---------|-----------|
16
+ | §7.2-7.5 | Syntax (tokens, objects, xref, trailer) | **100%** read + write |
17
+ | §7.4 | Filters | Through `pdfFilterDispatch` — the path `read` uses to decode cross-reference and object streams: FlateDecode (with `/Predictor` PNG 10–15 and TIFF 2, encode and decode), ASCIIHexDecode, ASCII85Decode, RunLengthDecode; DCTDecode, JPXDecode and Crypt pass through undecoded. `/DecodeParms` reach the decoders as plain values, so a predictor is applied; only scalar entries (numbers, names, booleans, strings) survive that marshalling — a dictionary, array or indirect-reference entry reaches the decoder as `undefined`. LZWDecode and CCITTFaxDecode are **not** registered in the dispatch by default (`pdf/filter/unsupported`): decode them through `extra/legacy-deprecated-filters` (LZW via `@awacloud/fw`, a full ITU-T T.4 / T.6 CCITT codec), or add them with `register(name, impl)`. JBIG2Decode: segment headers only (`extra/jbig2-read`), no image decode |
18
+ | §7.5.7-8 | Object Stream + Cross-Reference Stream | Read: cross-reference streams, mixed `/Prev` chains and hybrid-reference files, object streams materialised on demand — both decoded through the dispatch path above, so a stream whose filter the dispatch does not register cannot be read; object streams inside an encrypted document are refused (`pdf/document/objstm-encrypted`). Write: `pdfXrefStreamWriter` emits `/Type /XRef` documents (opt-in `/ObjStm` grouping); `appendIncremental` extends a cross-reference-stream base with an uncompressed `/Type /XRef` section and refuses a hybrid-reference base |
19
+ | §7.6 | Encryption (Standard SH v4/v5/v6) | v4 (AESV2/RC4-128) + v5 (AES-256) + v6 (Algorithm 2.B) decrypt **and** encrypt, plus AES-GCM (TS 32003); encrypted write via `pdfEncryptedWriter`. On read, the handlers are called by the caller: `read` refuses an encrypted file (`pdf/document/encrypted`) unless `allowEncrypted: true`, and then returns the ciphertext as is |
20
+ | §7.7-7.8 | Document structure (Catalog, Pages, Resources) | **100%** |
21
+ | §7.11 | Embedded files + Portfolios | 100% via `embedded/` + `extra/embedded-files-portfolio` |
22
+ | §8.2-8.5 | Content streams (operators, path, painting) | ~70 operators catalogued |
23
+ | §8.6 | Colour spaces | Device + Cal* + Lab + ICCBased + Indexed + Separation + DeviceN + Pattern + NChannel (via extra) |
24
+ | §8.7 | Patterns + Shading | Types 1-7 + Function 0/2/3/4 (via extra) |
25
+ | §8.9 / §8.10 | Images + XObjects (Image + Form) | 100% typed |
26
+ | §8.11 | Optional Content | 100% + `/VE` evaluator (via extra) |
27
+ | §9.6-9.9 | Fonts (Type1/Type3/TrueType/Type0/CIDFont) | 100% typed; parsing delegated to `@awacloud/fonts` |
28
+ | §11 | Transparency (groups, soft masks, blend modes) | 100% via `extra/transparency-typed` |
29
+ | §12.3 | Outlines + Destinations | 100% |
30
+ | §12.5 | Annotations (25+ subtypes) | 100% typed |
31
+ | §12.6 | Actions (GoTo / URI / Named / Launch / …) | 9 subtypes + extras |
32
+ | §12.7 | AcroForm | Btn/Tx/Ch/Sig + appearance streams |
33
+ | §12.8 | Digital signatures | PKCS#7 detached, `/ByteRange` hardened validation, real public-key verification (RSA-PSS/ECDSA/Ed25519 — see [Crypto](./crypto.md)), PAdES profile detection |
34
+ | §14.3 | Metadata | Info dict + raw XMP + extended XMP (via extra) |
35
+ | §14.6-14.8 | Tagged PDF + MCID resolution | 100% via `tagged/` |
36
+ | §14.11 | Prepress + Output Intents | 100% |
37
+ | Annex F | Linearization | Read: the `/Linearized` parameter dictionary is typed (`linearization/`); hint streams are not decoded. Write: `extra/linearization-write` builds the `/Linearized` dictionary and a zero-length hint-stream placeholder — `write` never produces a linearized file |
38
+
39
+ ## ISO Technical Specifications
40
+
41
+ | TS | Spec | Status |
42
+ |----|------|--------|
43
+ | ISO 32001 | Digital signatures (PAdES B/T/LT/LTA) | profile detection via `extra/sig-pades` |
44
+ | ISO 32002 | Crypto computations | digest + signature OID dispatch; Ed25519 signatures use SHA-512 (RFC 8419) and their signing update declares the `ISO_` developer extension (`/ExtensionLevel 32002`) in the Catalog, with `/Version /2.0` below PDF 2.0 (EdDSA in viewers: see the [PAdES guide](./pades-integration.md)) |
45
+ | ISO 32003 | AES-GCM crypt filter | full, via `crypto/aesGcm` + `extra/sig-aes-gcm` |
46
+ | ISO 32004 | Document parts | typed read via `extra/document-parts` |
47
+ | ISO/TS 32005 (referenced; the TS text is not in the repository) | Redaction | read-side only: `annot/redact` types the Redact annotation (ISO 32000-2 §12.5.6.21), `extra/redaction-iso32005` types the apply-redaction audit record. No content is removed or redrawn. |
48
+ | ISO 14289-2 | PDF/UA-2 accessibility | linter via `extra/pdf-ua-tagged` |
49
+ | WTPDF 1.0 | Well-Tagged PDF | best-practice linter via `extra/well-tagged-pdf` |
50
+
51
+ ## PDF 1.7 read tolerance
52
+
53
+ Via the `pdf-legacy` bundle:
54
+
55
+ | 1.7 feature | Status |
56
+ |-------------|--------|
57
+ | `%PDF-1.x` header | accepted on read |
58
+ | Standard SH v4 (RC4 v2/v3) | password check + string / stream decryption helpers in `extra/legacy-rc4-read`, called by the caller (see §7.6 above) |
59
+ | LZWDecode filter | wrapper over `@awacloud/fw/io/compress/lzw` in `extra/legacy-deprecated-filters`; not registered in the filter dispatch |
60
+ | XFA forms | read-only, opaque surface (`extra/legacy-xfa-read`); `write` re-emits `/XFA` as it was |
61
+ | Sound / Movie annotations | typed, read-only (`extra/legacy-deprecated-annots`); not converted to RichMedia |
62
+ | CCITTFaxDecode | full ITU-T T.4 / T.6 decode (K < 0 Group 4, K = 0 Group 3 1-D, K > 0 Group 3 mixed) via `extra/legacy-deprecated-filters` and `extra/ccitt-fax-decoder`; not registered in the filter dispatch |
63
+ | JBIG2Decode | segment headers only (`extra/jbig2-read`); its `decode` throws |
64
+
65
+ **Write** emits `%PDF-2.0` through `pdf.write`;
66
+ `pdfBuilder.setVersion()` / `writeDocument({ version })` emit the requested
67
+ header. The writer re-emits the objects of the model it is given: legacy
68
+ content read from a 1.x file is written back as it was, not converted.
69
+
70
+ ## Extras (opt-in via `.use()` or a bundle)
71
+
72
+ The opt-in modules under `extra/*`, wired through [`.use()`](./extending.md) or one
73
+ of the three [bundles](../api/bundles/README.md) (`pdf-large`, `pdf-full`,
74
+ `pdf-legacy`). See [`docs/api/extra/README.md`](../api/extra/README.md) for
75
+ the full catalogue.
76
+
77
+ ## Limitation: whole-buffer reading
78
+
79
+ `@awacloud/pdf` requires the complete document to be loaded in memory
80
+ (`Uint8Array`) before any `.read(...)` call. The PDF format places the
81
+ xref table **at the end of the file** (§7.5.4), so there is no upstream
82
+ streaming mode without linearization (header hint objects). Implications:
83
+
84
+ - Reading a 100 MB PDF → peak memory ≥ 100 MB (before the resolved-object
85
+ cache).
86
+ - No `pdf.readStream(...)` API: a wrapper consuming a `ReadableStream`
87
+ must accumulate the bytes first.
88
+ - A **linearized** file does not lift this limit: the reader still needs
89
+ the whole buffer, and [`pdfLinearization`](../api/linearization/linearization.md)
90
+ only types the `/Linearized` parameter dictionary.
91
+
92
+ This is a deliberate choice — an upstream streaming mode would require
93
+ either violating the xref-at-end spec requirement, or imposing the
94
+ linearization extension on write, both incompatible with a strict PDF 2.0
95
+ model that stays tolerant on read.
96
+
97
+ Hard parser quotas are configurable per resolved `pdfParser` instance
98
+ (`parserLimits`/`setParserLimits` are returned by the factory, not
99
+ top-level module exports):
100
+
101
+ ```js
102
+ const parser = runtime.resolve('pdfParser');
103
+ console.log(parser.parserLimits.maxDepth); // 200
104
+ console.log(parser.parserLimits.maxStreamBytes); // 256 MiB
105
+ parser.setParserLimits({ maxStreamBytes: 64 * 1024 * 1024 }); // strict 64 MiB
106
+ ```
107
+
108
+ ## See also
109
+
110
+ - [Read pipeline](./read-pdf.md)
111
+ - [Extending](./extending.md)
112
+ - [Crypto — risks and limitations](./crypto.md)
113
+ - [CHANGELOG](../../CHANGELOG.md)
@@ -0,0 +1,121 @@
1
+ # Crypto — risks and limitations
2
+
3
+ > Summary of `@awacloud/pdf`'s crypto choices and the security properties it
4
+ > does (or does *not*) guarantee.
5
+
6
+ **Prerequisites** — the package `@awacloud/pdf` (root entry
7
+ `@awacloud/pdf`, or the committed `@awacloud/pdf/standalone/*` build) and its
8
+ `@awacloud/fw` / `@awacloud/fonts` dependencies; any modern JavaScript runtime
9
+ (browser main thread or Worker, Bun, Node.js 18+). The cryptography goes through `@awacloud/fw/crypto/*`
10
+ (synchronous, no Web Crypto); the modules below are `@awacloud/pdf/crypto/*`
11
+ and `@awacloud/pdf/sig/*`.
12
+
13
+ ## Standard Security Handler (V=4 R=4 / V=5 R=5 / V=5 R=6)
14
+
15
+ `crypto/standardV4.js` implements the V=4 R=4 handler (AES-128-CBC or
16
+ RC4-128 crypt filters), `crypto/standardV5.js` the V=5 R=5 handler (AES-256,
17
+ Algorithm 2.A, no hardening loop) and `crypto/standardV6.js` the PDF 2.0
18
+ V=5 R=6 handler (AES-256 with the Algorithm 2.B hardening loop). `read`
19
+ does not apply them by itself: it refuses an encrypted file unless
20
+ `allowEncrypted: true` is passed, and the caller then decrypts through
21
+ these handlers.
22
+
23
+ ### AES-CBC without a MAC: malleability risk
24
+
25
+ The PDF format mandates plain **AES-256-CBC** for encrypted strings and
26
+ streams when `/Method /AESV3` is used. Consequences:
27
+
28
+ - **No authenticated integrity protection** on an encrypted field: an
29
+ attacker able to modify ciphertext bytes of an encrypted PDF string
30
+ causes predictable changes in the decrypted plaintext (CBC
31
+ bit-flipping). Until a MAC or AEAD is applied *on top* (e.g. a digital
32
+ signature over the whole document), malleability is a property of the
33
+ format itself.
34
+ - The **TS 32003 — AES-GCM** extension covers this by replacing CBC with
35
+ GCM (authenticated encryption). The `aesGcm.js` module is shipped for
36
+ consumers who want to implement this out-of-strict-spec extension.
37
+
38
+ ### Password authentication
39
+
40
+ Algorithm 2.B (R=6) resists dictionary attacks correctly thanks to the
41
+ hardening loop (≥ 64 iterations of SHA-2 + AES-128, conditional
42
+ termination on the ciphertext). In `standardV6.js`:
43
+
44
+ - The AES-128 key-schedule scratch buffer is reused across rounds.
45
+ - A forced bail-out at 1024 rounds guards against a runaway loop
46
+ (`pdf/crypto/v6/hardening-runaway`).
47
+
48
+ ## Signatures
49
+
50
+ `sig/signature.js` and `sig/timestamp.js` type PKCS#7/CMS signatures and
51
+ RFC 3161 tokens **and execute real public-key verification** through the
52
+ `verifyPk` primitive dispatcher (RSA-PSS, ECDSA, Ed25519) — `verifyPk` is
53
+ wired by construction, called from `_verifyPkcs7Signature` on every
54
+ `verifySignature(...)`/`verifyAllSignatures(...)` call. There is no
55
+ "structural-only, PK verify left to the consumer" mode: the digest is
56
+ recomputed from the `/ByteRange`-covered bytes, the signer certificate's
57
+ SPKI is extracted, and the matching fw primitive
58
+ (`rsa.pssVerify`/`ecc.ecdsa…verify`/`ed25519.verify`) is invoked directly.
59
+
60
+ ### Semantics of `verifySignature(...)`
61
+
62
+ | Field | Meaning |
63
+ |-------|------|
64
+ | `verified` | `true` **iff** the RSA-PSS / ECDSA / Ed25519 public-key verification ran and succeeded. `false` in every other case (parse failure, digest mismatch, missing/unmatched signer cert, unsupported algorithm, or a failed public-key check). |
65
+ | `valid` | Historical alias of `verified` — kept in sync, same boolean. |
66
+ | `pkVerified` | `true` only once `_verifyPkcs7Signature` reaches and passes the `verifyPk` call; `false` on every earlier bail-out. |
67
+ | `computedDigest` | The digest recomputed over the `/ByteRange` ranges — useful for a caller that wants to re-run `rsa.pssVerify` / `ecc…verify` itself. |
68
+ | `errors` | Array of `{ code, message }` records — the parse/verification step that failed, if any (e.g. `pdf/sig/pkcs7-malformed`, `pdf/sig/signer-cert-not-found`, or a `pdf/sig/verify-pk/*` code from `verifyPk` on primitive-level failure). |
69
+
70
+ RSA PKCS#1 v1.5 signatures are refused outright
71
+ (`pdf/sig/rsa-pkcs1v15-deprecated`, NIST SP 800-131A Rev.2) rather than
72
+ verified — use RSA-PSS.
73
+
74
+ **Ceiling that remains real**: `certChain.validateChainOrder` compares
75
+ issuer/subject strings only (no cryptographic chain, revocation, or trust
76
+ anchor check). Still open: a cryptographic chain-of-trust check over the
77
+ PKCS#7 SignerInfo certificates, and PAdES long-term validation (which
78
+ needs network I/O for revocation data).
79
+ `valid`/`verified: true` proves the PKCS#7 signature was cryptographically
80
+ valid over the signed bytes and the signer certificate was structurally
81
+ matched — it is **not** proof the certificate itself is trusted or
82
+ unrevoked.
83
+
84
+ ### Hardened ByteRange verification
85
+
86
+ `auditByteRange(documentBytes, byteRange, opts)` (from L3+) detects:
87
+
88
+ - `pdf/sig/byterange/self-overlap` — the second range starts before the
89
+ first one ends.
90
+ - `pdf/sig/byterange/gap-start-mismatch` /
91
+ `pdf/sig/byterange/gap-end-mismatch` — the declared gap does not land
92
+ exactly on the `/Contents` hex string.
93
+ - `pdf/sig/byterange/cross-overlap` — overlap with another `/ByteRange`
94
+ (useful for multiple signatures / incremental updates).
95
+ - `pdf/sig/byterange/incomplete-coverage` — the second range does not
96
+ reach `documentBytes.length` (unsigned tail).
97
+ - `pdf/sig/byterange/non-zero-start` — the first range does not start at
98
+ 0.
99
+
100
+ ### Active actions (`/Launch`, `/JavaScript`, `/SubmitForm`)
101
+
102
+ The `action/launch.js` typer returns a record with:
103
+
104
+ ```js
105
+ { kind: 'Launch', sandboxed: true,
106
+ securityWarning: 'launch actions are not executed by @awacloud/pdf', … }
107
+ ```
108
+
109
+ The opt-in `pdfSandbox` linter (bundle `pdf-full`) consolidates every
110
+ active-content record into a unified audit — `lintActions(records)`
111
+ returns `{ issues, hasErrors, hasActiveContent }` with `error` severity for
112
+ `Launch` / `JavaScript` / `ImportData` and `warning` for `URI` /
113
+ `SubmitForm` / `Rendition + /JS`.
114
+
115
+ **The package never executes anything.** These helpers exist so the host
116
+ application can refuse or prompt before propagating active content.
117
+
118
+ ## See also
119
+
120
+ - [Coverage](./coverage.md)
121
+ - [CHANGELOG](../../CHANGELOG.md)
@@ -0,0 +1,76 @@
1
+ # Extending via `.use()`
2
+
3
+ The public [`pdf`](../api/pdf.md) API exposes an extension hook `.use(extension)` to add methods without modifying the core. This guide shows the extension shape, the idempotence rule and how the bundles use the same hook.
4
+
5
+ **Prerequisites** — the package `@awacloud/pdf` (root entry
6
+ `@awacloud/pdf`, or the committed `@awacloud/pdf/standalone/*` build) and its
7
+ `@awacloud/fw` / `@awacloud/fonts` dependencies; any modern JavaScript runtime
8
+ (browser main thread or Worker, Bun, Node.js 18+).
9
+
10
+ ## Shape of an extension
11
+
12
+ ```js
13
+ {
14
+ name: 'unique-identifier', // string, kebab-case recommended
15
+ register(api, ctx) { // ctx = { usedExtensions: Set }
16
+ return { someNewMethod() { /* … */ } };
17
+ }
18
+ }
19
+ ```
20
+
21
+ `register` receives the current API and can:
22
+
23
+ - consume its methods (`api.read`, `api.header`, …) to compose behaviour;
24
+ - return an object whose keys (except `use`) are merged into the public API;
25
+ - return `undefined` for a pure side effect (no new method).
26
+
27
+ ## Idempotence by name
28
+
29
+ `.use()` is **idempotent**: applying the same `name` twice is a silent no-op. No double-merge, no error. The internal `usedExtensions` set is queryable via `api.usedExtension(name)`.
30
+
31
+ ```js
32
+ const ext = { name: 'demo', register: () => ({ ping: () => 42 }) };
33
+
34
+ api.use(ext);
35
+ api.use(ext); // no-op
36
+ api.ping(); // 42
37
+ api.usedExtension('demo'); // true
38
+ ```
39
+
40
+ ## Validation
41
+
42
+ A malformed extension (missing `name` or `register`) throws `ContractError` (`pdf/use/bad-extension`). See [`pdfErrors`](../api/errors.md).
43
+
44
+ ## Example — count annotations
45
+
46
+ ```js
47
+ import { ModuleRuntime } from '@awacloud/fw/core/runtime.js';
48
+ import { fw_require, pkg_require, modules } from '@awacloud/pdf';
49
+
50
+ const rt = new ModuleRuntime();
51
+ for (const m of fw_require) rt.register(m);
52
+ for (const m of pkg_require) rt.register(m);
53
+ for (const m of modules) rt.register(m);
54
+
55
+ const api = rt.resolve('pdf');
56
+
57
+ api.use({
58
+ name: 'count-annots',
59
+ register(api) {
60
+ return {
61
+ countAnnots(bytes) {
62
+ return api.read(bytes).pages
63
+ .reduce((n, p) => n + p.annots.length, 0);
64
+ }
65
+ };
66
+ }
67
+ });
68
+
69
+ api.countAnnots(bytes); // → int
70
+ ```
71
+
72
+ ## See also
73
+
74
+ - [`pdf` orchestrator](../api/pdf.md)
75
+ - [`pdfErrors`](../api/errors.md)
76
+ - [Coverage](./coverage.md) — the extras planned/shipped through this hook.
@@ -0,0 +1,75 @@
1
+ # Getting Started
2
+
3
+ `@awacloud/pdf` reads and writes PDF documents in pure JavaScript, browser-side, with no runtime dependency beyond `@awacloud/fw` and `@awacloud/fonts`. This guide installs the package, wires it on a `ModuleRuntime` and reads a first document.
4
+
5
+ **Prerequisites** — the package `@awacloud/pdf` (root entry
6
+ `@awacloud/pdf`, or the committed `@awacloud/pdf/standalone/*` build) and its
7
+ `@awacloud/fw` / `@awacloud/fonts` dependencies; any modern JavaScript runtime
8
+ (browser main thread or Worker, Bun, Node.js 18+).
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @awacloud/pdf
14
+ ```
15
+
16
+ Browser import map:
17
+
18
+ ```html
19
+ <script type="importmap">
20
+ { "imports": {
21
+ "@awacloud/fw": "/node_modules/@awacloud/fw/src/main.js",
22
+ "@awacloud/fw/": "/node_modules/@awacloud/fw/src/",
23
+ "@awacloud/fonts": "/node_modules/@awacloud/fonts/src/main.js",
24
+ "@awacloud/fonts/": "/node_modules/@awacloud/fonts/src/",
25
+ "@awacloud/pdf": "/node_modules/@awacloud/pdf/src/main.js",
26
+ "@awacloud/pdf/": "/node_modules/@awacloud/pdf/src/"
27
+ }}
28
+ </script>
29
+ <script type="module" src="./app.js"></script>
30
+ ```
31
+
32
+ ## With `@awacloud/fw` `ModuleRuntime`
33
+
34
+ `pdf` is a **strict factory-only descriptor** — its `factory` takes 13
35
+ positional dependency arguments and has no zero-argument convenience
36
+ form. Materialise a working instance by registering the package's manifest
37
+ arrays on a `ModuleRuntime` and resolving by name (or use the committed
38
+ `@awacloud/pdf/standalone/pdf.js` build, whose `pdfBundled.factory()`
39
+ takes no arguments):
40
+
41
+ ```js
42
+ import { ModuleRuntime } from '@awacloud/fw/core/runtime.js';
43
+ import { fw_require, pkg_require, modules } from '@awacloud/pdf';
44
+
45
+ const rt = new ModuleRuntime();
46
+ for (const m of fw_require) rt.register(m); // @awacloud/fw crypto/io modules
47
+ for (const m of pkg_require) rt.register(m); // @awacloud/fonts subset helpers
48
+ for (const m of modules) rt.register(m); // @awacloud/pdf's own modules
49
+
50
+ const api = rt.resolve('pdf');
51
+ const doc = api.read(bytes); // bytes: Uint8Array
52
+
53
+ console.log(doc.version); // header version, e.g. "1.7" or "2.0"
54
+ console.log(doc.pages.length); // → page count
55
+ console.log(doc.pages[0].mediaBox); // the page's own /MediaBox, or null when inherited
56
+ ```
57
+
58
+ `modules` is topologically ordered — registration order only matters in
59
+ that every dependency must be registered before `resolve('pdf')` is
60
+ called; `ModuleRuntime` resolves each declared dependency by name
61
+ regardless of array order.
62
+
63
+ ## Reading just the header
64
+
65
+ ```js
66
+ api.header(bytes);
67
+ // → { version: '2.0', end: <offset> } (the header's own version)
68
+ ```
69
+
70
+ ## Next steps
71
+
72
+ - [Detailed read pipeline](./read-pdf.md)
73
+ - [Extending via `.use()`](./extending.md)
74
+ - [Coverage](./coverage.md)
75
+ - [API index](../api/README.md)
@@ -0,0 +1,42 @@
1
+ # Reading legacy PDF 1.7
2
+
3
+ `@awacloud/pdf` targets **ISO 32000-2:2020 (PDF 2.0)** for writing. On **read**, `%PDF-1.x` headers produced by any ISO 32000-1:2008-conformant tool are accepted. This guide states what the core reader does with a 1.x file; the legacy-only constructs (XFA, RC4, LZW, CCITT fax, Sound/Movie) are read by the `pdf-legacy` bundle's extras — see [Coverage](./coverage.md#pdf-17-read-tolerance).
4
+
5
+ **Prerequisites** — the package `@awacloud/pdf` (root entry
6
+ `@awacloud/pdf`, or the committed `@awacloud/pdf/standalone/*` build) and its
7
+ `@awacloud/fw` / `@awacloud/fonts` dependencies; any modern JavaScript runtime
8
+ (browser main thread or Worker, Bun, Node.js 18+).
9
+
10
+ ## Behaviour
11
+
12
+ `readHeader(bytes)` does not constrain the `x.y` suffix value:
13
+
14
+ ```js
15
+ api.header(bytes);
16
+ // → { version: '1.7', end: 9 }
17
+ // → { version: '1.4', end: 9 }
18
+ // → { version: '2.0', end: 9 }
19
+ ```
20
+
21
+ Whatever version is exposed in `doc.version` is the raw string found in the header (`'1.7'`, `'2.0'`, …). No normalization is applied.
22
+
23
+ ## Guarantees
24
+
25
+ - Headers `%PDF-1.0` through `%PDF-2.0` are all accepted.
26
+ - The header may be preceded by up to 1024 bytes of binary junk (§7.5.2 tolerance).
27
+ - Classical xref works identically across 1.x and 2.0.
28
+ - 2.0-exclusive constructs (associated files, document parts, extended namespaces) are preserved in `_extras` when read from a 1.x file, without erroring.
29
+
30
+ ## Cross-reference forms across 1.x and 2.0
31
+
32
+ `pdfDocument.readDocument` (the code path behind `api.read(bytes)`) walks every cross-reference section in the `/Prev` chain and picks its form from the bytes it finds: an `xref` keyword takes the classical table path (`pdfXref.parseXrefTable`), anything else is parsed as a `/Type /XRef` cross-reference stream (§7.5.8) through `pdfCrossRefStream`. A PDF 1.5+ file that uses **only** cross-reference streams therefore opens through `api.read(bytes)`, and so do mixed chains — a classical incremental section stacked on an xref-stream base, or an xref stream stacked on a classical base.
33
+
34
+ Objects stored inside a `/Type /ObjStm` container (§7.5.7) are materialised on demand through `pdfObjStream`: `doc._raw.resolve(ref)` returns them like any other indirect, and each container is decoded once per document. A hybrid file (classical xref table plus a `/XRefStm` pointer, the common PDF 1.5+ producer output) has its companion stream merged too; entries the classical table itself provides take precedence.
35
+
36
+ **Not supported.** Object streams inside an **encrypted** document stay out of the default pipeline: `readDocument`'s `resolveCompressed` throws `pdf/document/objstm-encrypted` because no decrypt path is composed for it (`resolveCompressed` in `src/document/document.js`).
37
+
38
+ ## See also
39
+
40
+ - [Coverage](./coverage.md)
41
+ - [`pdfDocument`](../api/document/document.md)
42
+ - [`pdfXref`](../api/syntax/xref.md)