@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.
- package/CHANGELOG.md +609 -0
- package/LICENSE +661 -0
- package/NOTICE +77 -0
- package/README.md +363 -2
- package/dist/build/index.js +21 -0
- package/dist/build/pdf-full-rw.js +10972 -0
- package/dist/build/pdf-full-rw.meta.json +105 -0
- package/dist/build/pdf-full-rw.min.js +53 -0
- package/dist/build/pdf-full.js +6078 -0
- package/dist/build/pdf-full.meta.json +90 -0
- package/dist/build/pdf-full.min.js +32 -0
- package/dist/build/pdf-large-rw.js +10367 -0
- package/dist/build/pdf-large-rw.meta.json +99 -0
- package/dist/build/pdf-large-rw.min.js +53 -0
- package/dist/build/pdf-large.js +5473 -0
- package/dist/build/pdf-large.meta.json +84 -0
- package/dist/build/pdf-large.min.js +32 -0
- package/dist/build/pdf-legacy-rw.js +12402 -0
- package/dist/build/pdf-legacy-rw.meta.json +110 -0
- package/dist/build/pdf-legacy-rw.min.js +53 -0
- package/dist/build/pdf-legacy.js +7508 -0
- package/dist/build/pdf-legacy.meta.json +95 -0
- package/dist/build/pdf-legacy.min.js +32 -0
- package/dist/build/pdf-rw.js +7578 -0
- package/dist/build/pdf-rw.meta.json +77 -0
- package/dist/build/pdf-rw.min.js +53 -0
- package/dist/build/pdf.js +2684 -0
- package/dist/build/pdf.meta.json +62 -0
- package/dist/build/pdf.min.js +32 -0
- package/dist/standalone/pdf-full-rw.js +16798 -0
- package/dist/standalone/pdf-full-rw.meta.json +78 -0
- package/dist/standalone/pdf-full-rw.min.js +56 -0
- package/dist/standalone/pdf-full.js +11904 -0
- package/dist/standalone/pdf-full.meta.json +63 -0
- package/dist/standalone/pdf-full.min.js +35 -0
- package/dist/standalone/pdf-large-rw.js +16193 -0
- package/dist/standalone/pdf-large-rw.meta.json +72 -0
- package/dist/standalone/pdf-large-rw.min.js +56 -0
- package/dist/standalone/pdf-large.js +11299 -0
- package/dist/standalone/pdf-large.meta.json +57 -0
- package/dist/standalone/pdf-large.min.js +35 -0
- package/dist/standalone/pdf-legacy-rw.js +18228 -0
- package/dist/standalone/pdf-legacy-rw.meta.json +83 -0
- package/dist/standalone/pdf-legacy-rw.min.js +56 -0
- package/dist/standalone/pdf-legacy.js +13334 -0
- package/dist/standalone/pdf-legacy.meta.json +68 -0
- package/dist/standalone/pdf-legacy.min.js +35 -0
- package/dist/standalone/pdf-rw.js +13404 -0
- package/dist/standalone/pdf-rw.meta.json +50 -0
- package/dist/standalone/pdf-rw.min.js +56 -0
- package/dist/standalone/pdf.js +8510 -0
- package/dist/standalone/pdf.meta.json +35 -0
- package/dist/standalone/pdf.min.js +35 -0
- package/docs/README.md +53 -0
- package/docs/api/README.md +38 -0
- package/docs/api/_shared/README.md +91 -0
- package/docs/api/action/README.md +29 -0
- package/docs/api/action/action.md +81 -0
- package/docs/api/action/goTo.md +66 -0
- package/docs/api/action/launch.md +58 -0
- package/docs/api/action/named.md +55 -0
- package/docs/api/action/uri.md +54 -0
- package/docs/api/annot/README.md +53 -0
- package/docs/api/annot/annot.md +114 -0
- package/docs/api/annot/fileAttach.md +53 -0
- package/docs/api/annot/freeText.md +68 -0
- package/docs/api/annot/ink.md +69 -0
- package/docs/api/annot/link.md +74 -0
- package/docs/api/annot/markup.md +83 -0
- package/docs/api/annot/popup.md +52 -0
- package/docs/api/annot/projection.md +56 -0
- package/docs/api/annot/redact.md +67 -0
- package/docs/api/annot/square.md +87 -0
- package/docs/api/annot/stamp.md +54 -0
- package/docs/api/annot/text.md +69 -0
- package/docs/api/annot/widget.md +69 -0
- package/docs/api/associatedFiles/README.md +9 -0
- package/docs/api/associatedFiles/associatedFiles.md +78 -0
- package/docs/api/bundles/README.md +68 -0
- package/docs/api/bundles/dist-matrix.md +165 -0
- package/docs/api/bundles/pdf-full.md +148 -0
- package/docs/api/bundles/pdf-large.md +144 -0
- package/docs/api/bundles/pdf-legacy.md +169 -0
- package/docs/api/content/README.md +29 -0
- package/docs/api/content/color.md +99 -0
- package/docs/api/content/graphics.md +114 -0
- package/docs/api/content/images.md +124 -0
- package/docs/api/content/ops.md +100 -0
- package/docs/api/content/stream.md +107 -0
- package/docs/api/content/text.md +98 -0
- package/docs/api/crypto/README.md +29 -0
- package/docs/api/crypto/aesGcm.md +72 -0
- package/docs/api/crypto/permissions.md +79 -0
- package/docs/api/crypto/security.md +98 -0
- package/docs/api/crypto/standardV4.md +104 -0
- package/docs/api/crypto/standardV5.md +84 -0
- package/docs/api/crypto/standardV6.md +93 -0
- package/docs/api/destination/README.md +9 -0
- package/docs/api/destination/destination.md +79 -0
- package/docs/api/document/README.md +29 -0
- package/docs/api/document/builder.md +281 -0
- package/docs/api/document/catalog.md +98 -0
- package/docs/api/document/document.md +187 -0
- package/docs/api/document/encryptedWriter.md +149 -0
- package/docs/api/document/incrementalWriter.md +148 -0
- package/docs/api/document/page.md +99 -0
- package/docs/api/document/pages.md +82 -0
- package/docs/api/document/resources.md +102 -0
- package/docs/api/document/writer.md +157 -0
- package/docs/api/document/xrefStreamWriter.md +122 -0
- package/docs/api/embedded/README.md +13 -0
- package/docs/api/embedded/collection.md +80 -0
- package/docs/api/embedded/embeddedFile.md +86 -0
- package/docs/api/embedded/fileSpec.md +87 -0
- package/docs/api/errors.md +110 -0
- package/docs/api/extra/3d-richmedia.md +76 -0
- package/docs/api/extra/README.md +99 -0
- package/docs/api/extra/annot-extended.md +71 -0
- package/docs/api/extra/associated-files.md +70 -0
- package/docs/api/extra/ccitt-fax-decoder.md +74 -0
- package/docs/api/extra/color-spaces-extended.md +72 -0
- package/docs/api/extra/content-ops-extended.md +82 -0
- package/docs/api/extra/document-parts.md +69 -0
- package/docs/api/extra/embedded-files-portfolio.md +87 -0
- package/docs/api/extra/font-cid-typed.md +77 -0
- package/docs/api/extra/font-color-tagging.md +76 -0
- package/docs/api/extra/form-actions-extended.md +75 -0
- package/docs/api/extra/info-dict-deprecated.md +72 -0
- package/docs/api/extra/jbig2-read.md +80 -0
- package/docs/api/extra/legacy-deprecated-annots.md +89 -0
- package/docs/api/extra/legacy-deprecated-filters.md +78 -0
- package/docs/api/extra/legacy-rc4-read.md +74 -0
- package/docs/api/extra/legacy-xfa-read.md +65 -0
- package/docs/api/extra/linearization-write.md +71 -0
- package/docs/api/extra/misc.md +93 -0
- package/docs/api/extra/optional-content-extended.md +83 -0
- package/docs/api/extra/pdf-a-output-intent.md +65 -0
- package/docs/api/extra/pdf-sandbox.md +76 -0
- package/docs/api/extra/pdf-ua-tagged.md +63 -0
- package/docs/api/extra/pdf-x-prepress.md +65 -0
- package/docs/api/extra/redaction-iso32005.md +65 -0
- package/docs/api/extra/shading-typed.md +73 -0
- package/docs/api/extra/sig-aes-gcm.md +69 -0
- package/docs/api/extra/sig-pades.md +103 -0
- package/docs/api/extra/tagged-pdf-typed.md +78 -0
- package/docs/api/extra/transparency-typed.md +74 -0
- package/docs/api/extra/well-tagged-pdf.md +61 -0
- package/docs/api/extra/xmp-extended.md +65 -0
- package/docs/api/font/README.md +25 -0
- package/docs/api/font/embed.md +157 -0
- package/docs/api/font/encoding.md +95 -0
- package/docs/api/font/font.md +97 -0
- package/docs/api/font/type3.md +89 -0
- package/docs/api/form/README.md +35 -0
- package/docs/api/form/acroform.md +88 -0
- package/docs/api/form/appearance.md +87 -0
- package/docs/api/form/button.md +97 -0
- package/docs/api/form/choice.md +96 -0
- package/docs/api/form/fieldTree.md +93 -0
- package/docs/api/form/signature.md +90 -0
- package/docs/api/form/text.md +88 -0
- package/docs/api/linearization/README.md +11 -0
- package/docs/api/linearization/linearization.md +81 -0
- package/docs/api/main.md +116 -0
- package/docs/api/metadata/README.md +10 -0
- package/docs/api/metadata/info.md +70 -0
- package/docs/api/metadata/xmp.md +62 -0
- package/docs/api/ocg/README.md +23 -0
- package/docs/api/ocg/config.md +95 -0
- package/docs/api/ocg/ocg.md +77 -0
- package/docs/api/outline/README.md +11 -0
- package/docs/api/outline/outline.md +107 -0
- package/docs/api/pdf.md +152 -0
- package/docs/api/prepress/README.md +10 -0
- package/docs/api/prepress/outputIntent.md +79 -0
- package/docs/api/prepress/pageBoundary.md +75 -0
- package/docs/api/sig/README.md +32 -0
- package/docs/api/sig/byteRange.md +120 -0
- package/docs/api/sig/certChain.md +84 -0
- package/docs/api/sig/dss.md +111 -0
- package/docs/api/sig/oids.md +76 -0
- package/docs/api/sig/sha1.md +72 -0
- package/docs/api/sig/sign.md +317 -0
- package/docs/api/sig/signature.md +178 -0
- package/docs/api/sig/timestamp.md +84 -0
- package/docs/api/syntax/README.md +29 -0
- package/docs/api/syntax/crossRefStream.md +115 -0
- package/docs/api/syntax/filters/README.md +50 -0
- package/docs/api/syntax/filters/ascii85.md +76 -0
- package/docs/api/syntax/filters/asciiHex.md +73 -0
- package/docs/api/syntax/filters/dispatch.md +125 -0
- package/docs/api/syntax/filters/flate.md +134 -0
- package/docs/api/syntax/filters/runLength.md +78 -0
- package/docs/api/syntax/objStream.md +88 -0
- package/docs/api/syntax/parser-obj.md +97 -0
- package/docs/api/syntax/parser.md +151 -0
- package/docs/api/syntax/serializer.md +109 -0
- package/docs/api/syntax/tokenizer.md +104 -0
- package/docs/api/syntax/trailer.md +85 -0
- package/docs/api/syntax/xref.md +139 -0
- package/docs/api/tagged/README.md +25 -0
- package/docs/api/tagged/classMap.md +67 -0
- package/docs/api/tagged/markedContent.md +62 -0
- package/docs/api/tagged/parentTree.md +67 -0
- package/docs/api/tagged/roleMap.md +67 -0
- package/docs/api/tagged/structElement.md +76 -0
- package/docs/api/tagged/structTree.md +75 -0
- package/docs/guide/coverage.md +113 -0
- package/docs/guide/crypto.md +121 -0
- package/docs/guide/extending.md +76 -0
- package/docs/guide/getting-started.md +75 -0
- package/docs/guide/legacy-1.7.md +42 -0
- package/docs/guide/pades-integration.md +579 -0
- package/docs/guide/read-pdf.md +89 -0
- package/package.json +97 -4
- package/src/_shared/index.js +179 -0
- package/src/action/action.js +119 -0
- package/src/action/goTo.js +89 -0
- package/src/action/launch.js +61 -0
- package/src/action/named.js +54 -0
- package/src/action/uri.js +51 -0
- package/src/annot/annot.js +212 -0
- package/src/annot/fileAttach.js +55 -0
- package/src/annot/freeText.js +82 -0
- package/src/annot/ink.js +77 -0
- package/src/annot/link.js +77 -0
- package/src/annot/markup.js +91 -0
- package/src/annot/popup.js +53 -0
- package/src/annot/projection.js +52 -0
- package/src/annot/redact.js +87 -0
- package/src/annot/square.js +132 -0
- package/src/annot/stamp.js +48 -0
- package/src/annot/text.js +54 -0
- package/src/annot/widget.js +61 -0
- package/src/associatedFiles/associatedFiles.js +86 -0
- package/src/bundles/pdf-full.js +91 -0
- package/src/bundles/pdf-large.js +81 -0
- package/src/bundles/pdf-legacy.js +107 -0
- package/src/content/color.js +114 -0
- package/src/content/graphics.js +192 -0
- package/src/content/images.js +160 -0
- package/src/content/ops.js +137 -0
- package/src/content/stream.js +154 -0
- package/src/content/text.js +125 -0
- package/src/crypto/aesGcm.js +123 -0
- package/src/crypto/permissions.js +112 -0
- package/src/crypto/security.js +327 -0
- package/src/crypto/standardV4.js +443 -0
- package/src/crypto/standardV5.js +306 -0
- package/src/crypto/standardV6.js +334 -0
- package/src/destination/destination.js +183 -0
- package/src/document/builder.js +618 -0
- package/src/document/catalog.js +100 -0
- package/src/document/document.js +472 -0
- package/src/document/encryptedWriter.js +554 -0
- package/src/document/incrementalWriter.js +514 -0
- package/src/document/page.js +131 -0
- package/src/document/pages.js +103 -0
- package/src/document/resources.js +146 -0
- package/src/document/writer.js +211 -0
- package/src/document/xrefStreamWriter.js +353 -0
- package/src/embedded/collection.js +102 -0
- package/src/embedded/embeddedFile.js +99 -0
- package/src/embedded/fileSpec.js +137 -0
- package/src/errors.js +78 -0
- package/src/extra/3d-richmedia.js +171 -0
- package/src/extra/annot-extended.js +200 -0
- package/src/extra/associated-files.js +131 -0
- package/src/extra/ccitt-fax-decoder.js +776 -0
- package/src/extra/color-spaces-extended.js +196 -0
- package/src/extra/content-ops-extended.js +153 -0
- package/src/extra/document-parts.js +149 -0
- package/src/extra/embedded-files-portfolio.js +234 -0
- package/src/extra/font-cid-typed.js +185 -0
- package/src/extra/font-color-tagging.js +144 -0
- package/src/extra/form-actions-extended.js +196 -0
- package/src/extra/info-dict-deprecated.js +137 -0
- package/src/extra/jbig2-read.js +169 -0
- package/src/extra/legacy-deprecated-annots.js +198 -0
- package/src/extra/legacy-deprecated-filters.js +167 -0
- package/src/extra/legacy-rc4-read.js +235 -0
- package/src/extra/legacy-xfa-read.js +104 -0
- package/src/extra/linearization-write.js +97 -0
- package/src/extra/misc.js +217 -0
- package/src/extra/optional-content-extended.js +142 -0
- package/src/extra/pdf-a-output-intent.js +112 -0
- package/src/extra/pdf-sandbox.js +88 -0
- package/src/extra/pdf-ua-tagged.js +116 -0
- package/src/extra/pdf-x-prepress.js +114 -0
- package/src/extra/redaction-iso32005.js +136 -0
- package/src/extra/shading-typed.js +222 -0
- package/src/extra/sig-aes-gcm.js +135 -0
- package/src/extra/sig-pades.js +242 -0
- package/src/extra/tagged-pdf-typed.js +203 -0
- package/src/extra/transparency-typed.js +135 -0
- package/src/extra/well-tagged-pdf.js +138 -0
- package/src/extra/xmp-extended.js +190 -0
- package/src/font/embed.js +480 -0
- package/src/font/encoding.js +92 -0
- package/src/font/font.js +101 -0
- package/src/font/type3.js +75 -0
- package/src/form/acroform.js +94 -0
- package/src/form/appearance.js +90 -0
- package/src/form/button.js +105 -0
- package/src/form/choice.js +152 -0
- package/src/form/fieldTree.js +120 -0
- package/src/form/signature.js +100 -0
- package/src/form/text.js +101 -0
- package/src/linearization/linearization.js +107 -0
- package/src/main.js +411 -0
- package/src/metadata/info.js +87 -0
- package/src/metadata/xmp.js +62 -0
- package/src/ocg/config.js +156 -0
- package/src/ocg/ocg.js +124 -0
- package/src/outline/outline.js +157 -0
- package/src/pdf.js +133 -0
- package/src/prepress/outputIntent.js +118 -0
- package/src/prepress/pageBoundary.js +108 -0
- package/src/sig/byteRange.js +306 -0
- package/src/sig/certChain.js +247 -0
- package/src/sig/dss.js +317 -0
- package/src/sig/oids.js +157 -0
- package/src/sig/sha1.js +142 -0
- package/src/sig/sign.js +1899 -0
- package/src/sig/signature.js +1441 -0
- package/src/sig/timestamp.js +236 -0
- package/src/syntax/crossRefStream.js +133 -0
- package/src/syntax/filters/ascii85.js +122 -0
- package/src/syntax/filters/asciiHex.js +83 -0
- package/src/syntax/filters/dispatch.js +176 -0
- package/src/syntax/filters/flate.js +316 -0
- package/src/syntax/filters/runLength.js +96 -0
- package/src/syntax/objStream.js +99 -0
- package/src/syntax/parser-obj.js +52 -0
- package/src/syntax/parser.js +321 -0
- package/src/syntax/serializer.js +221 -0
- package/src/syntax/tokenizer.js +290 -0
- package/src/syntax/trailer.js +76 -0
- package/src/syntax/xref.js +341 -0
- package/src/tagged/classMap.js +81 -0
- package/src/tagged/markedContent.js +123 -0
- package/src/tagged/parentTree.js +126 -0
- package/src/tagged/roleMap.js +107 -0
- package/src/tagged/structElement.js +138 -0
- 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
|
+
};
|