@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,196 @@
1
+ // Copyright (c) 2026 AwaCloud SAS
2
+ // Author: Matthieu Bouilloux
3
+ // SPDX-License-Identifier: AGPL-3.0-only
4
+ // Dual-licensed; see the NOTICE file for licensing and any additional terms.
5
+
6
+ /**
7
+ * @fileoverview Opt-in: extended action subtypes per
8
+ * ISO 32000-2:2020 §12.6.4 — GoTo3DView (§12.6.4.15),
9
+ * SetOCGState (§12.6.4.12), Trans (§12.6.4.13), Rendition (§12.6.4.14),
10
+ * Hide (§12.6.4.10), SubmitForm (§12.6.4.4), ResetForm (§12.6.4.5),
11
+ * ImportData (§12.6.4.6), JavaScript (§12.6.4.7, sandboxed flag only).
12
+ *
13
+ * Each typer returns a typed record ; unknowns are preserved in
14
+ * `_extras`. The orchestrator returns `{ kind, ...typed, raw, _extras }`.
15
+ *
16
+ * @module pdf/extra/form-actions-extended
17
+ */
18
+
19
+ /**
20
+ * Module factory.
21
+ */
22
+ import { pdfErrors } from '../errors.js';
23
+ import { pdfParserObj } from '../syntax/parser-obj.js';
24
+
25
+ export const pdfFormActionsExtended = {
26
+ name: 'pdfFormActionsExtended',
27
+ dependencies: ['pdfErrors', 'pdfParserObj'],
28
+ deps: [pdfErrors, pdfParserObj],
29
+ factory(errors, parserObj) {
30
+ const { ParseError } = errors;
31
+ const { isType } = parserObj;
32
+
33
+ const EXTENDED_ACTION_SUBTYPES = new Set([
34
+ 'GoTo3DView', 'SetOCGState', 'Trans', 'Rendition', 'Hide',
35
+ 'SubmitForm', 'ResetForm', 'ImportData', 'JavaScript'
36
+ ]);
37
+
38
+ const KNOWN = {
39
+ GoTo3DView: new Set(['Type', 'S', 'Next', 'TA', 'V']),
40
+ SetOCGState: new Set(['Type', 'S', 'Next', 'State', 'PreserveRB']),
41
+ Trans: new Set(['Type', 'S', 'Next', 'Trans']),
42
+ Rendition: new Set(['Type', 'S', 'Next', 'R', 'AN', 'OP', 'JS']),
43
+ Hide: new Set(['Type', 'S', 'Next', 'T', 'H']),
44
+ SubmitForm: new Set(['Type', 'S', 'Next', 'F', 'Fields', 'Flags', 'CharSet']),
45
+ ResetForm: new Set(['Type', 'S', 'Next', 'Fields', 'Flags']),
46
+ ImportData: new Set(['Type', 'S', 'Next', 'F']),
47
+ JavaScript: new Set(['Type', 'S', 'Next', 'JS'])
48
+ };
49
+
50
+ function knownFor(s) { return KNOWN[s] || new Set(['Type', 'S', 'Next']); }
51
+
52
+ function typeExtendedAction(dict) {
53
+ if (!isType(dict, 'dict')) {
54
+ throw new ParseError('pdf/extra/action-ext/not-dict',
55
+ 'action must be a dictionary',
56
+ { context: { type: dict && dict.type } });
57
+ }
58
+ const e = dict.entries;
59
+ if (e.Type && (e.Type.type !== 'name' || e.Type.value !== 'Action')) {
60
+ throw new ParseError('pdf/extra/action-ext/bad-type',
61
+ '/Type entry must be /Action',
62
+ { context: { actual: e.Type.value } });
63
+ }
64
+ if (!isType(e.S, 'name') || !EXTENDED_ACTION_SUBTYPES.has(e.S.value)) {
65
+ throw new ParseError('pdf/extra/action-ext/unsupported',
66
+ 'unsupported extended action subtype',
67
+ { context: { subtype: e.S && e.S.value } });
68
+ }
69
+ let rec;
70
+ switch (e.S.value) {
71
+ case 'GoTo3DView': rec = readGoTo3DView(e); break;
72
+ case 'SetOCGState': rec = readSetOCGState(e); break;
73
+ case 'Trans': rec = readTrans(e); break;
74
+ case 'Rendition': rec = readRendition(e); break;
75
+ case 'Hide': rec = readHide(e); break;
76
+ case 'SubmitForm': rec = readSubmitForm(e); break;
77
+ case 'ResetForm': rec = readResetForm(e); break;
78
+ case 'ImportData': rec = readImportData(e); break;
79
+ case 'JavaScript': rec = readJavaScript(e); break;
80
+ }
81
+ rec.kind = e.S.value;
82
+ rec.raw = dict;
83
+ rec._extras = collectExtras(e, knownFor(e.S.value));
84
+ return rec;
85
+ }
86
+
87
+ function readGoTo3DView(e) {
88
+ return { ta: e.TA || null, v: e.V || null };
89
+ }
90
+
91
+ function readSetOCGState(e) {
92
+ if (!isType(e.State, 'array')) {
93
+ throw new ParseError('pdf/extra/action-ext/bad-state',
94
+ '/State must be an array',
95
+ { context: { type: e.State && e.State.type } });
96
+ }
97
+ return {
98
+ state: e.State.items,
99
+ preserveRB: isType(e.PreserveRB, 'bool') ? e.PreserveRB.value : true
100
+ };
101
+ }
102
+
103
+ function readTrans(e) {
104
+ if (!isType(e.Trans, 'dict')) {
105
+ throw new ParseError('pdf/extra/action-ext/bad-trans',
106
+ '/Trans must be a dict',
107
+ { context: { type: e.Trans && e.Trans.type } });
108
+ }
109
+ return { trans: e.Trans };
110
+ }
111
+
112
+ function readRendition(e) {
113
+ const op = (e.OP && (e.OP.type === 'int' || e.OP.type === 'real'))
114
+ ? (e.OP.value | 0) : null;
115
+ const hasJs = isType(e.JS, 'string') || isType(e.JS, 'stream');
116
+ return {
117
+ r: e.R || null,
118
+ an: e.AN || null,
119
+ op,
120
+ js: isType(e.JS, 'string') ? e.JS.value : (isType(e.JS, 'stream') ? e.JS : null),
121
+ sandboxed: hasJs ? true : undefined
122
+ };
123
+ }
124
+
125
+ function readHide(e) {
126
+ if (!e.T) {
127
+ throw new ParseError('pdf/extra/action-ext/missing-t',
128
+ 'Hide action requires /T');
129
+ }
130
+ let targets;
131
+ if (isType(e.T, 'string') || e.T.type === 'ref') targets = [e.T];
132
+ else if (isType(e.T, 'array')) targets = e.T.items;
133
+ else {
134
+ throw new ParseError('pdf/extra/action-ext/bad-t',
135
+ '/T must be string, ref, or array',
136
+ { context: { type: e.T.type } });
137
+ }
138
+ return { targets, h: isType(e.H, 'bool') ? e.H.value : true };
139
+ }
140
+
141
+ function readSubmitForm(e) {
142
+ if (!e.F) {
143
+ throw new ParseError('pdf/extra/action-ext/missing-f',
144
+ 'SubmitForm requires /F (URL)');
145
+ }
146
+ return {
147
+ url: e.F,
148
+ fields: isType(e.Fields, 'array') ? e.Fields.items : null,
149
+ flags: (e.Flags && (e.Flags.type === 'int' || e.Flags.type === 'real'))
150
+ ? (e.Flags.value | 0) : 0,
151
+ charSet: isType(e.CharSet, 'string') ? e.CharSet.value : null,
152
+ sandboxed: true
153
+ };
154
+ }
155
+
156
+ function readResetForm(e) {
157
+ return {
158
+ fields: isType(e.Fields, 'array') ? e.Fields.items : null,
159
+ flags: (e.Flags && (e.Flags.type === 'int' || e.Flags.type === 'real'))
160
+ ? (e.Flags.value | 0) : 0
161
+ };
162
+ }
163
+
164
+ function readImportData(e) {
165
+ if (!e.F) {
166
+ throw new ParseError('pdf/extra/action-ext/missing-f',
167
+ 'ImportData requires /F (file spec)');
168
+ }
169
+ return { file: e.F, sandboxed: true };
170
+ }
171
+
172
+ function readJavaScript(e) {
173
+ if (!e.JS) {
174
+ throw new ParseError('pdf/extra/action-ext/missing-js',
175
+ 'JavaScript action requires /JS');
176
+ }
177
+ if (!isType(e.JS, 'string') && !isType(e.JS, 'stream')) {
178
+ throw new ParseError('pdf/extra/action-ext/bad-js',
179
+ '/JS must be string or stream',
180
+ { context: { type: e.JS.type } });
181
+ }
182
+ return { js: e.JS, sandboxed: true };
183
+ }
184
+
185
+ function collectExtras(entries, known) {
186
+ const out = {};
187
+ for (const k of Object.keys(entries)) {
188
+ if (!known.has(k)) out[k] = entries[k];
189
+ }
190
+ return out;
191
+ }
192
+
193
+ return { typeExtendedAction, EXTENDED_ACTION_SUBTYPES };
194
+ }
195
+ };
196
+
@@ -0,0 +1,137 @@
1
+ // Copyright (c) 2026 AwaCloud SAS
2
+ // Author: Matthieu Bouilloux
3
+ // SPDX-License-Identifier: AGPL-3.0-only
4
+ // Dual-licensed; see the NOTICE file for licensing and any additional terms.
5
+
6
+ /**
7
+ * @fileoverview Opt-in: /Info dict deprecation lint.
8
+ *
9
+ * PDF 2.0 (ISO 32000-2:2020 §14.3.3) deprecates the Document
10
+ * Information Dictionary in favour of XMP metadata streams. This module
11
+ * inspects a Catalog + /Info pair and emits structured warnings when
12
+ * /Info is present on a PDF 2.0 document, including a suggested XMP
13
+ * mapping per the standard's recommended namespaces.
14
+ *
15
+ * @module pdf/extra/info-dict-deprecated
16
+ */
17
+
18
+ import { pdfErrors } from '../errors.js';
19
+
20
+ export const pdfInfoDictDeprecated = {
21
+ name: 'pdfInfoDictDeprecated',
22
+ dependencies: ['pdfErrors'],
23
+ deps: [pdfErrors],
24
+
25
+ factory(errors) {
26
+ const { ParseError } = errors;
27
+ const INFO_TO_XMP = {
28
+ Title: { ns: 'dc', field: 'title' },
29
+ Author: { ns: 'dc', field: 'creator' },
30
+ Subject: { ns: 'dc', field: 'description' },
31
+ Keywords: { ns: 'pdf', field: 'Keywords' },
32
+ Creator: { ns: 'xmp', field: 'CreatorTool' },
33
+ Producer: { ns: 'pdf', field: 'Producer' },
34
+ CreationDate: { ns: 'xmp', field: 'CreateDate' },
35
+ ModDate: { ns: 'xmp', field: 'ModifyDate' },
36
+ Trapped: { ns: 'pdf', field: 'Trapped' }
37
+ };
38
+
39
+ function isDict(v) { return v && v.type === 'dict'; }
40
+
41
+ function parsePdfVersion(v) {
42
+ if (typeof v === 'string') return v;
43
+ if (v && v.type === 'name') return v.value;
44
+ if (v && v.type === 'string') {
45
+ const b = v.value;
46
+ if (b instanceof Uint8Array) return new TextDecoder('latin1').decode(b);
47
+ return String(b);
48
+ }
49
+ if (typeof v === 'number') return String(v);
50
+ throw new ParseError('pdf/info-deprecated/bad-version',
51
+ 'PDF version must be string or PDF name',
52
+ { context: { type: v && v.type } });
53
+ }
54
+
55
+ function isVersion2OrHigher(versionStr) {
56
+ const m = /^(\d+)\.(\d+)/.exec(versionStr || '');
57
+ if (!m) return false;
58
+ const major = parseInt(m[1], 10);
59
+ return major >= 2;
60
+ }
61
+
62
+ function suggestionsFor(infoDict) {
63
+ if (!isDict(infoDict)) return [];
64
+ const out = [];
65
+ for (const k of Object.keys(infoDict.entries)) {
66
+ const map = INFO_TO_XMP[k];
67
+ if (map) {
68
+ out.push({
69
+ infoKey: k,
70
+ xmpNamespace: map.ns,
71
+ xmpField: map.field
72
+ });
73
+ } else {
74
+ out.push({
75
+ infoKey: k,
76
+ xmpNamespace: null,
77
+ xmpField: null,
78
+ note: 'no standard XMP equivalent'
79
+ });
80
+ }
81
+ }
82
+ return out;
83
+ }
84
+
85
+ function lint(opts) {
86
+ opts = opts || {};
87
+ const version = parsePdfVersion(opts.version);
88
+ const info = opts.info;
89
+ const xmpPresent = !!opts.xmpPresent;
90
+ const warnings = [];
91
+
92
+ if (info != null) {
93
+ if (!isDict(info)) {
94
+ throw new ParseError('pdf/info-deprecated/bad-info',
95
+ '/Info must be a dict',
96
+ { context: { type: info && info.type } });
97
+ }
98
+ }
99
+
100
+ const v2 = isVersion2OrHigher(version);
101
+ if (v2 && info) {
102
+ warnings.push({
103
+ code: 'pdf/info-deprecated',
104
+ severity: 'warn',
105
+ message: '/Info is deprecated in PDF 2.0 — use the XMP metadata stream instead',
106
+ suggestions: suggestionsFor(info)
107
+ });
108
+ }
109
+ if (v2 && info && !xmpPresent) {
110
+ warnings.push({
111
+ code: 'pdf/info-without-xmp',
112
+ severity: 'warn',
113
+ message: 'PDF 2.0 document carries /Info but no XMP /Metadata stream'
114
+ });
115
+ }
116
+ return {
117
+ version,
118
+ isPdf2: v2,
119
+ hasInfo: info != null,
120
+ xmpPresent,
121
+ warnings
122
+ };
123
+ }
124
+
125
+ function mapInfoKey(name) {
126
+ return INFO_TO_XMP[name] || null;
127
+ }
128
+
129
+ return {
130
+ lint,
131
+ mapInfoKey,
132
+ suggestionsFor,
133
+ INFO_TO_XMP,
134
+ isVersion2OrHigher
135
+ };
136
+ }
137
+ };
@@ -0,0 +1,169 @@
1
+ // Copyright (c) 2026 AwaCloud SAS
2
+ // Author: Matthieu Bouilloux
3
+ // SPDX-License-Identifier: AGPL-3.0-only
4
+ // Dual-licensed; see the NOTICE file for licensing and any additional terms.
5
+
6
+ /**
7
+ * @fileoverview Opt-in: JBIG2Decode partial reader.
8
+ *
9
+ * JBIG2 is the bilevel image codec referenced by /Filter /JBIG2Decode
10
+ * (ISO 32000-2:2020 §7.4.7). A full decoder is out of scope; this
11
+ * module parses the segment header chain (ISO/IEC 14492:2001 §7.2) and
12
+ * returns descriptors so callers can at least enumerate the embedded
13
+ * data without pulling in a heavyweight decoder.
14
+ *
15
+ * Status: PARTIAL — header-only.
16
+ *
17
+ * @module pdf/extra/jbig2-read
18
+ */
19
+
20
+ import { pdfErrors } from '../errors.js';
21
+
22
+ export const pdfJbig2Read = {
23
+ name: 'pdfJbig2Read',
24
+ dependencies: ['pdfErrors'],
25
+ deps: [pdfErrors],
26
+
27
+ factory(errors) {
28
+ const { ParseError } = errors;
29
+ const SEGMENT_TYPES = {
30
+ 0: 'symbolDictionary',
31
+ 4: 'intermediateTextRegion',
32
+ 6: 'immediateTextRegion',
33
+ 7: 'immediateLosslessTextRegion',
34
+ 16: 'patternDictionary',
35
+ 20: 'intermediateHalftoneRegion',
36
+ 22: 'immediateHalftoneRegion',
37
+ 23: 'immediateLosslessHalftoneRegion',
38
+ 36: 'intermediateGenericRegion',
39
+ 38: 'immediateGenericRegion',
40
+ 39: 'immediateLosslessGenericRegion',
41
+ 40: 'intermediateGenericRefinementRegion',
42
+ 42: 'immediateGenericRefinementRegion',
43
+ 43: 'immediateLosslessGenericRefinementRegion',
44
+ 48: 'pageInformation',
45
+ 49: 'endOfPage',
46
+ 50: 'endOfStripe',
47
+ 51: 'endOfFile',
48
+ 52: 'profiles',
49
+ 53: 'tables',
50
+ 62: 'extension'
51
+ };
52
+
53
+ function readUint32BE(b, o) {
54
+ return (b[o] * 0x1000000) + ((b[o + 1] << 16) | (b[o + 2] << 8) | b[o + 3]);
55
+ }
56
+
57
+ function readReferredSegmentCount(b, o) {
58
+ // First byte's top 3 bits = count; if = 7 => long form (next 3 bytes hold (count<<5)|reserved).
59
+ const head = b[o];
60
+ const small = head >>> 5;
61
+ if (small !== 7) {
62
+ return { count: small, fieldBytes: 1 };
63
+ }
64
+ // Long form: 4 bytes total, count uses 29 high bits of next 32-bit value.
65
+ const longVal = readUint32BE(b, o) & 0x1FFFFFFF;
66
+ return { count: longVal, fieldBytes: 4 };
67
+ }
68
+
69
+ function refSegSize(count) {
70
+ // Each retention flag bit + alignment to byte, plus references.
71
+ // We don't need the retention flag bytes' contents; just to skip.
72
+ return Math.ceil((count + 1) / 8);
73
+ }
74
+
75
+ function refNumberSize(maxSegNum) {
76
+ if (maxSegNum <= 0xFF) return 1;
77
+ if (maxSegNum <= 0xFFFF) return 2;
78
+ return 4;
79
+ }
80
+
81
+ function parseSegments(bytes) {
82
+ if (!(bytes instanceof Uint8Array)) {
83
+ throw new ParseError('pdf/jbig2/bad-input',
84
+ 'JBIG2Decode expects Uint8Array');
85
+ }
86
+ const out = [];
87
+ let o = 0;
88
+ let lastSegNum = 0;
89
+ while (o + 11 <= bytes.length) {
90
+ const start = o;
91
+ const segNum = readUint32BE(bytes, o); o += 4;
92
+ const flags = bytes[o++];
93
+ const type = flags & 0x3F;
94
+ const retainBit = (flags >> 6) & 1;
95
+ const deferredNonRetainBit = (flags >> 7) & 1;
96
+
97
+ const ref = readReferredSegmentCount(bytes, o);
98
+ o += ref.fieldBytes;
99
+ // Skip retention flag bytes (count+1 bits rounded up).
100
+ o += refSegSize(ref.count);
101
+ // Skip referred segment numbers.
102
+ const rns = refNumberSize(Math.max(segNum, lastSegNum));
103
+ o += ref.count * rns;
104
+ if (o + 4 > bytes.length) {
105
+ throw new ParseError('pdf/jbig2/truncated-header',
106
+ 'JBIG2 segment header truncated',
107
+ { context: { segNum, offset: start } });
108
+ }
109
+ // Page association — 1 or 4 bytes; we assume 1-byte mode
110
+ // unless the page-association-size flag in the header
111
+ // suggests 4 (we have no header — JBIG2 sequential
112
+ // streams in PDF are headerless, defaulting to 1).
113
+ o += 1;
114
+ if (o + 4 > bytes.length) {
115
+ throw new ParseError('pdf/jbig2/truncated-data-length',
116
+ 'JBIG2 segment data length truncated',
117
+ { context: { segNum, offset: start } });
118
+ }
119
+ const dataLength = readUint32BE(bytes, o); o += 4;
120
+ const dataStart = o;
121
+ if (dataLength !== 0xFFFFFFFF) {
122
+ if (dataStart + dataLength > bytes.length) {
123
+ throw new ParseError('pdf/jbig2/truncated-data',
124
+ 'JBIG2 segment data truncated',
125
+ { context: { segNum, dataLength } });
126
+ }
127
+ o = dataStart + dataLength;
128
+ } else {
129
+ // Unknown length — caller must scan for EOF.
130
+ // We bail and surface the partial descriptor.
131
+ o = bytes.length;
132
+ }
133
+ out.push({
134
+ segmentNumber: segNum,
135
+ type,
136
+ typeName: SEGMENT_TYPES[type] || 'unknown',
137
+ referredCount: ref.count,
138
+ retain: !!retainBit,
139
+ deferredNonRetain: !!deferredNonRetainBit,
140
+ dataOffset: dataStart,
141
+ dataLength: dataLength === 0xFFFFFFFF ? null : dataLength,
142
+ unknownLength: dataLength === 0xFFFFFFFF
143
+ });
144
+ lastSegNum = Math.max(lastSegNum, segNum);
145
+ if (type === 51) break; // endOfFile
146
+ }
147
+ return out;
148
+ }
149
+
150
+ function enumerateGenericRegions(bytes) {
151
+ const segs = parseSegments(bytes);
152
+ return segs.filter(s => s.type === 36 || s.type === 38 || s.type === 39);
153
+ }
154
+
155
+ function decode(_bytes) {
156
+ throw new ParseError('pdf/jbig2/not-implemented',
157
+ 'JBIG2Decode full decode not implemented — header-only',
158
+ { context: { status: 'partial' } });
159
+ }
160
+
161
+ return {
162
+ parseSegments,
163
+ enumerateGenericRegions,
164
+ decode,
165
+ SEGMENT_TYPES,
166
+ STATUS: 'partial — header-only'
167
+ };
168
+ }
169
+ };