@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
package/package.json
CHANGED
|
@@ -1,6 +1,99 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awacloud/pdf",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "AGPL-3.0-only",
|
|
5
|
+
"author": "Matthieu Bouilloux",
|
|
6
|
+
"company": "AwaCloud SAS",
|
|
7
|
+
"copyright": "Copyright (c) 2026 AwaCloud SAS",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "src/main.js",
|
|
10
|
+
"description": "Browser-safe PDF 2.0 reader/writer — ISO 32000-2:2020, PDF 1.7 legacy read, typed object graph, AES-256 encrypted write, PKCS#7/PAdES signatures (sign + verify). Zero runtime dependency beyond @awacloud/fw and @awacloud/fonts.",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"pdf",
|
|
13
|
+
"pdf-2.0",
|
|
14
|
+
"iso-32000",
|
|
15
|
+
"pades",
|
|
16
|
+
"pkcs7",
|
|
17
|
+
"tagged-pdf",
|
|
18
|
+
"pdf-a",
|
|
19
|
+
"pdf-ua",
|
|
20
|
+
"xmp",
|
|
21
|
+
"acroform",
|
|
22
|
+
"browser",
|
|
23
|
+
"worker-safe"
|
|
24
|
+
],
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"files": [
|
|
30
|
+
"src/**/*.js",
|
|
31
|
+
"!src/**/*.test.js",
|
|
32
|
+
"dist/**",
|
|
33
|
+
"docs",
|
|
34
|
+
"LICENSE",
|
|
35
|
+
"NOTICE",
|
|
36
|
+
"README.md",
|
|
37
|
+
"CHANGELOG.md"
|
|
38
|
+
],
|
|
39
|
+
"exports": {
|
|
40
|
+
".": "./src/main.js",
|
|
41
|
+
"./pdf": "./src/pdf.js",
|
|
42
|
+
"./errors": "./src/errors.js",
|
|
43
|
+
"./serializer": "./src/syntax/serializer.js",
|
|
44
|
+
"./filters/*.js": "./src/syntax/filters/*.js",
|
|
45
|
+
"./filters/*": "./src/syntax/filters/*.js",
|
|
46
|
+
"./annot/*.js": "./src/annot/*.js",
|
|
47
|
+
"./annot/*": "./src/annot/*.js",
|
|
48
|
+
"./tagged/*.js": "./src/tagged/*.js",
|
|
49
|
+
"./tagged/*": "./src/tagged/*.js",
|
|
50
|
+
"./crypto/*.js": "./src/crypto/*.js",
|
|
51
|
+
"./crypto/*": "./src/crypto/*.js",
|
|
52
|
+
"./sig/*.js": "./src/sig/*.js",
|
|
53
|
+
"./sig/*": "./src/sig/*.js",
|
|
54
|
+
"./ocg/*.js": "./src/ocg/*.js",
|
|
55
|
+
"./ocg/*": "./src/ocg/*.js",
|
|
56
|
+
"./action/*.js": "./src/action/*.js",
|
|
57
|
+
"./action/*": "./src/action/*.js",
|
|
58
|
+
"./embedded/*.js": "./src/embedded/*.js",
|
|
59
|
+
"./embedded/*": "./src/embedded/*.js",
|
|
60
|
+
"./metadata/*.js": "./src/metadata/*.js",
|
|
61
|
+
"./metadata/*": "./src/metadata/*.js",
|
|
62
|
+
"./prepress/*.js": "./src/prepress/*.js",
|
|
63
|
+
"./prepress/*": "./src/prepress/*.js",
|
|
64
|
+
"./extra/*.js": "./src/extra/*.js",
|
|
65
|
+
"./extra/*": "./src/extra/*.js",
|
|
66
|
+
"./bundles/*.js": "./src/bundles/*.js",
|
|
67
|
+
"./bundles/*": "./src/bundles/*.js",
|
|
68
|
+
"./pdf-large": "./src/bundles/pdf-large.js",
|
|
69
|
+
"./pdf-full": "./src/bundles/pdf-full.js",
|
|
70
|
+
"./pdf-legacy": "./src/bundles/pdf-legacy.js",
|
|
71
|
+
"./build/*": {
|
|
72
|
+
"default": "./dist/build/*"
|
|
73
|
+
},
|
|
74
|
+
"./standalone/*": {
|
|
75
|
+
"default": "./dist/standalone/*"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"scripts": {
|
|
79
|
+
"gen:bundles": "bun run tools/generate-bundles.mjs",
|
|
80
|
+
"lint": "eslint . --max-warnings 0"
|
|
81
|
+
},
|
|
82
|
+
"dependencies": {
|
|
83
|
+
"@awacloud/fw": "0.1.0",
|
|
84
|
+
"@awacloud/fonts": "1.0.0"
|
|
85
|
+
},
|
|
86
|
+
"awa": {
|
|
87
|
+
"maturity": "L4",
|
|
88
|
+
"coverageFloor": 0.58
|
|
89
|
+
},
|
|
90
|
+
"repository": {
|
|
91
|
+
"type": "git",
|
|
92
|
+
"url": "git+https://github.com/awacloud/awa.git",
|
|
93
|
+
"directory": "packages/front/office/pdf"
|
|
94
|
+
},
|
|
95
|
+
"homepage": "https://awaforge.eu",
|
|
96
|
+
"bugs": {
|
|
97
|
+
"url": "https://github.com/awacloud/awa/issues"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,179 @@
|
|
|
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 `pdfShared` — canonical source of PDF byte-level
|
|
8
|
+
* constants and stateless helpers previously duplicated across many
|
|
9
|
+
* `@awacloud/pdf` factories.
|
|
10
|
+
*
|
|
11
|
+
* Exposes :
|
|
12
|
+
* - **Magic bytes** : `HEADER_PREFIX` (`%PDF-`), `EOF_MARKER` (`%%EOF`),
|
|
13
|
+
* `BINARY_MARKER` (the `%¡¢£¤\n` byte tail).
|
|
14
|
+
* - **ASCII constants** : `ASCII` object grouping the byte values used
|
|
15
|
+
* by the tokenizer / parsers / writers — `SP`, `HT`, `LF`, `CR`, `FF`,
|
|
16
|
+
* `NUL`, `HASH`, `PERCENT`, `BACKSLASH`, `SLASH`, `LPAREN`, `RPAREN`,
|
|
17
|
+
* `LANGLE`, `RANGLE`, `LBRACK`, `RBRACK`, `LBRACE`, `RBRACE`, `PLUS`,
|
|
18
|
+
* `MINUS`, `DOT`, `ZERO`, `NINE`, `A_UP`, `F_UP`, `Z_UP`, `A_LO`,
|
|
19
|
+
* `F_LO`, `Z_LO`.
|
|
20
|
+
* - **Character class predicates** (PDF 32000-2 §7.2) : `isWs`, `isEol`,
|
|
21
|
+
* `isDigit`, `isHex`, `isDelim`, `isRegular`, `hexNibble`. Each is a
|
|
22
|
+
* pure function over byte values.
|
|
23
|
+
* - **Hex tables** : `HEX_LO` — 128-entry lookup `byte → nibble value`
|
|
24
|
+
* (`-1` for non-hex), used by `asciiHex` and serializer.
|
|
25
|
+
* - **UTF-8 / latin1 codec singletons** : `te` (`TextEncoder`),
|
|
26
|
+
* `tdUtf8` (`TextDecoder('utf-8')`), `tdUtf8Lenient`
|
|
27
|
+
* (`TextDecoder('utf-8', { fatal: false })`), `tdLatin1`
|
|
28
|
+
* (`TextDecoder('latin1')`). Both `tdUtf8` and `tdUtf8Lenient` are
|
|
29
|
+
* non-fatal (`fatal: false` is the `TextDecoder` default). Available to
|
|
30
|
+
* `writer.js` and `serializer.js`.
|
|
31
|
+
* - **Codec helpers** : `encodeAscii(s)` / `decodeLatin1(bytes)` /
|
|
32
|
+
* `decodeUtf8(bytes)` / `decodeUtf8Lenient(bytes)` — thin wrappers
|
|
33
|
+
* over the singletons.
|
|
34
|
+
* - **Byte helpers** : `pad10(n)`, `hexLit(bytes)`, `bytesEqual(a, b, n)`,
|
|
35
|
+
* `concatBytes(arrays)` — available to modules; `writer.js` and
|
|
36
|
+
* `serializer.js` still carry their own copies.
|
|
37
|
+
*
|
|
38
|
+
* **Worker-safe** : every export is either a constant byte array, a
|
|
39
|
+
* pure function, or a singleton instantiated inside the factory body
|
|
40
|
+
* (so `factory.toString()` produces a self-contained closure).
|
|
41
|
+
*
|
|
42
|
+
* @module pdf/_shared
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
export const pdfShared = {
|
|
46
|
+
name: 'pdfShared',
|
|
47
|
+
dependencies: [],
|
|
48
|
+
|
|
49
|
+
factory() {
|
|
50
|
+
// --- Magic bytes -----------------------------------------------
|
|
51
|
+
const HEADER_PREFIX = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2D]); // %PDF-
|
|
52
|
+
const EOF_MARKER = new Uint8Array([0x25, 0x25, 0x45, 0x4F, 0x46]); // %%EOF
|
|
53
|
+
// Binary marker line emitted right after the version header so
|
|
54
|
+
// transports treat the file as binary (per PDF 32000-2 §7.5.2).
|
|
55
|
+
const BINARY_MARKER = new Uint8Array([0x25, 0xE2, 0xE3, 0xCF, 0xD3, 0x0A]);
|
|
56
|
+
|
|
57
|
+
// --- ASCII byte constants --------------------------------------
|
|
58
|
+
const ASCII = Object.freeze({
|
|
59
|
+
NUL: 0x00, HT: 0x09, LF: 0x0A, FF: 0x0C, CR: 0x0D, SP: 0x20,
|
|
60
|
+
HASH: 0x23, PERCENT: 0x25, LPAREN: 0x28, RPAREN: 0x29,
|
|
61
|
+
PLUS: 0x2B, MINUS: 0x2D, DOT: 0x2E, SLASH: 0x2F,
|
|
62
|
+
ZERO: 0x30, NINE: 0x39,
|
|
63
|
+
LANGLE: 0x3C, RANGLE: 0x3E,
|
|
64
|
+
A_UP: 0x41, F_UP: 0x46, Z_UP: 0x5A,
|
|
65
|
+
LBRACK: 0x5B, BACKSLASH: 0x5C, RBRACK: 0x5D,
|
|
66
|
+
A_LO: 0x61, F_LO: 0x66, Z_LO: 0x7A,
|
|
67
|
+
LBRACE: 0x7B, RBRACE: 0x7D
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// --- Character class predicates (PDF 32000-2 §7.2) -------------
|
|
71
|
+
function isWs(b) {
|
|
72
|
+
return b === 0x20 || b === 0x09 || b === 0x0A
|
|
73
|
+
|| b === 0x0D || b === 0x0C || b === 0x00;
|
|
74
|
+
}
|
|
75
|
+
function isEol(b) { return b === 0x0A || b === 0x0D; }
|
|
76
|
+
function isDigit(b) { return b >= 0x30 && b <= 0x39; }
|
|
77
|
+
function isHex(b) {
|
|
78
|
+
return (b >= 0x30 && b <= 0x39)
|
|
79
|
+
|| (b >= 0x41 && b <= 0x46)
|
|
80
|
+
|| (b >= 0x61 && b <= 0x66);
|
|
81
|
+
}
|
|
82
|
+
function isDelim(b) {
|
|
83
|
+
return b === 0x28 || b === 0x29 // ( )
|
|
84
|
+
|| b === 0x3C || b === 0x3E // < >
|
|
85
|
+
|| b === 0x5B || b === 0x5D // [ ]
|
|
86
|
+
|| b === 0x2F || b === 0x25 // / %
|
|
87
|
+
|| b === 0x7B || b === 0x7D; // { }
|
|
88
|
+
}
|
|
89
|
+
function isRegular(b) { return !isWs(b) && !isDelim(b); }
|
|
90
|
+
|
|
91
|
+
function hexNibble(b) {
|
|
92
|
+
if (b >= 0x30 && b <= 0x39) return b - 0x30;
|
|
93
|
+
if (b >= 0x41 && b <= 0x46) return b - 0x41 + 10;
|
|
94
|
+
if (b >= 0x61 && b <= 0x66) return b - 0x61 + 10;
|
|
95
|
+
return -1;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// --- Hex lookup table (byte → nibble value, -1 if non-hex) -----
|
|
99
|
+
// 128 entries, indexable by ASCII byte. Identical semantics to
|
|
100
|
+
// hexNibble() but O(1) without branches.
|
|
101
|
+
const HEX_LO = (function buildHexLo() {
|
|
102
|
+
const t = new Int8Array(128);
|
|
103
|
+
t.fill(-1);
|
|
104
|
+
for (let c = 0x30; c <= 0x39; c++) t[c] = c - 0x30;
|
|
105
|
+
for (let c = 0x41; c <= 0x46; c++) t[c] = c - 0x41 + 10;
|
|
106
|
+
for (let c = 0x61; c <= 0x66; c++) t[c] = c - 0x61 + 10;
|
|
107
|
+
return t;
|
|
108
|
+
})();
|
|
109
|
+
|
|
110
|
+
// --- UTF-8 / latin1 codec singletons ---------------------------
|
|
111
|
+
const te = new TextEncoder();
|
|
112
|
+
const tdUtf8 = new TextDecoder('utf-8');
|
|
113
|
+
const tdUtf8Lenient = new TextDecoder('utf-8', { fatal: false });
|
|
114
|
+
const tdLatin1 = new TextDecoder('latin1');
|
|
115
|
+
|
|
116
|
+
function encodeAscii(s) { return te.encode(s); }
|
|
117
|
+
function decodeUtf8(bytes) { return tdUtf8.decode(bytes); }
|
|
118
|
+
function decodeUtf8Lenient(b) { return tdUtf8Lenient.decode(b); }
|
|
119
|
+
function decodeLatin1(bytes) { return tdLatin1.decode(bytes); }
|
|
120
|
+
|
|
121
|
+
// --- Byte helpers ----------------------------------------------
|
|
122
|
+
function pad10(n) { return String(n).padStart(10, '0'); }
|
|
123
|
+
|
|
124
|
+
function hexLit(bytes) {
|
|
125
|
+
const H = '0123456789ABCDEF';
|
|
126
|
+
let s = '<';
|
|
127
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
128
|
+
s += H[bytes[i] >> 4] + H[bytes[i] & 0xF];
|
|
129
|
+
}
|
|
130
|
+
return s + '>';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Constant-time-ish equality of two byte arrays.
|
|
135
|
+
*
|
|
136
|
+
* @param {Uint8Array} a
|
|
137
|
+
* @param {Uint8Array} b
|
|
138
|
+
* @param {number} [n] — optional prefix length to compare;
|
|
139
|
+
* defaults to `min(a.length, b.length)` and requires both
|
|
140
|
+
* arrays to be that length exactly.
|
|
141
|
+
*/
|
|
142
|
+
function bytesEqual(a, b, n) {
|
|
143
|
+
if (!a || !b) return false;
|
|
144
|
+
if (n == null) {
|
|
145
|
+
if (a.length !== b.length) return false;
|
|
146
|
+
n = a.length;
|
|
147
|
+
} else {
|
|
148
|
+
if (a.length < n || b.length < n) return false;
|
|
149
|
+
}
|
|
150
|
+
let diff = 0;
|
|
151
|
+
for (let i = 0; i < n; i++) diff |= (a[i] ^ b[i]);
|
|
152
|
+
return diff === 0;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function concatBytes(arrays) {
|
|
156
|
+
let total = 0;
|
|
157
|
+
for (const a of arrays) total += a.length;
|
|
158
|
+
const out = new Uint8Array(total);
|
|
159
|
+
let o = 0;
|
|
160
|
+
for (const a of arrays) { out.set(a, o); o += a.length; }
|
|
161
|
+
return out;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
// magic
|
|
166
|
+
HEADER_PREFIX, EOF_MARKER, BINARY_MARKER,
|
|
167
|
+
// ASCII constants
|
|
168
|
+
ASCII,
|
|
169
|
+
// char classes
|
|
170
|
+
isWs, isEol, isDigit, isHex, isDelim, isRegular, hexNibble,
|
|
171
|
+
HEX_LO,
|
|
172
|
+
// codec singletons
|
|
173
|
+
te, tdUtf8, tdUtf8Lenient, tdLatin1,
|
|
174
|
+
encodeAscii, decodeUtf8, decodeUtf8Lenient, decodeLatin1,
|
|
175
|
+
// byte helpers
|
|
176
|
+
pad10, hexLit, bytesEqual, concatBytes
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
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 Action orchestrator per ISO 32000-2:2020 §12.6.
|
|
8
|
+
*
|
|
9
|
+
* Dispatches on `/S` (action type) and delegates to a specialised typer
|
|
10
|
+
* when available, otherwise returns a generic `{ kind, raw, _extras }`
|
|
11
|
+
* record for action subtypes not (yet) covered by a dedicated module
|
|
12
|
+
* (Thread, Sound, Movie, Hide, SubmitForm, ResetForm, ImportData,
|
|
13
|
+
* SetOCGState, Rendition, Trans, GoTo3DView, GoToDp, JavaScript).
|
|
14
|
+
*
|
|
15
|
+
* The `/Next` entry (a single action dict or an array of them) is
|
|
16
|
+
* recursively typed, with cycle protection via a Set of seen dicts.
|
|
17
|
+
*
|
|
18
|
+
* Optional sub-typers are passed via the `typers` argument — this lets
|
|
19
|
+
* callers wire `typeGoTo`, `typeUri`, etc. without creating a hard
|
|
20
|
+
* import chain.
|
|
21
|
+
*
|
|
22
|
+
* @module pdf/action/action
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Module factory.
|
|
27
|
+
*/
|
|
28
|
+
import { pdfErrors } from '../errors.js';
|
|
29
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
30
|
+
|
|
31
|
+
export const pdfAction = {
|
|
32
|
+
name: 'pdfAction',
|
|
33
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
34
|
+
deps: [pdfErrors, pdfParser],
|
|
35
|
+
factory(errors, parser) {
|
|
36
|
+
const { ParseError } = errors;
|
|
37
|
+
const { isType } = parser;
|
|
38
|
+
|
|
39
|
+
const GENERIC_KINDS = new Set([
|
|
40
|
+
'GoTo', 'GoToR', 'GoToE', 'GoToDp', 'Launch', 'Thread', 'URI',
|
|
41
|
+
'Sound', 'Movie', 'Hide', 'Named', 'SubmitForm', 'ResetForm',
|
|
42
|
+
'ImportData', 'SetOCGState', 'Rendition', 'Trans', 'GoTo3DView',
|
|
43
|
+
'JavaScript', 'RichMediaExecute'
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
function typeAction(dict, typers, opts) {
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
const maxDepth = (opts && opts.maxDepth) || 16;
|
|
49
|
+
return walk(dict, 0);
|
|
50
|
+
|
|
51
|
+
function walk(d, depth) {
|
|
52
|
+
if (depth > maxDepth) {
|
|
53
|
+
throw new ParseError('pdf/action/max-depth',
|
|
54
|
+
'action /Next chain too deep',
|
|
55
|
+
{ context: { depth, maxDepth } });
|
|
56
|
+
}
|
|
57
|
+
if (!isType(d, 'dict')) {
|
|
58
|
+
throw new ParseError('pdf/action/not-dict',
|
|
59
|
+
'action must be a dictionary',
|
|
60
|
+
{ context: { type: d && d.type } });
|
|
61
|
+
}
|
|
62
|
+
if (seen.has(d)) {
|
|
63
|
+
throw new ParseError('pdf/action/cycle',
|
|
64
|
+
'cycle detected in action /Next chain');
|
|
65
|
+
}
|
|
66
|
+
seen.add(d);
|
|
67
|
+
|
|
68
|
+
const e = d.entries;
|
|
69
|
+
if (e.Type && (e.Type.type !== 'name' || e.Type.value !== 'Action')) {
|
|
70
|
+
throw new ParseError('pdf/action/bad-type',
|
|
71
|
+
'/Type must be /Action when present',
|
|
72
|
+
{ context: { actual: e.Type.value } });
|
|
73
|
+
}
|
|
74
|
+
if (!e.S || e.S.type !== 'name') {
|
|
75
|
+
throw new ParseError('pdf/action/missing-s',
|
|
76
|
+
'action missing /S name',
|
|
77
|
+
{ context: { type: e.S && e.S.type } });
|
|
78
|
+
}
|
|
79
|
+
const kind = e.S.value;
|
|
80
|
+
|
|
81
|
+
let rec;
|
|
82
|
+
const t = typers && typers[kind];
|
|
83
|
+
if (typeof t === 'function') {
|
|
84
|
+
rec = t(d);
|
|
85
|
+
if (!rec.kind) rec.kind = kind;
|
|
86
|
+
} else {
|
|
87
|
+
if (!GENERIC_KINDS.has(kind)) {
|
|
88
|
+
rec = { kind, vendor: true, raw: d, _extras: collectExtras(e) };
|
|
89
|
+
} else {
|
|
90
|
+
rec = { kind, raw: d, _extras: collectExtras(e) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (e.Next) {
|
|
95
|
+
if (e.Next.type === 'dict') {
|
|
96
|
+
rec.next = [walk(e.Next, depth + 1)];
|
|
97
|
+
} else if (e.Next.type === 'array') {
|
|
98
|
+
rec.next = e.Next.items.map((nx) => walk(nx, depth + 1));
|
|
99
|
+
} else {
|
|
100
|
+
throw new ParseError('pdf/action/bad-next',
|
|
101
|
+
'/Next must be a dict or array of dicts',
|
|
102
|
+
{ context: { type: e.Next.type } });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return rec;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function collectExtras(entries) {
|
|
110
|
+
const out = {};
|
|
111
|
+
for (const k of Object.keys(entries)) {
|
|
112
|
+
if (k !== 'Type' && k !== 'S' && k !== 'Next') out[k] = entries[k];
|
|
113
|
+
}
|
|
114
|
+
return out;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return { typeAction };
|
|
118
|
+
}
|
|
119
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
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 GoTo / GoToR / GoToE actions per ISO 32000-2:2020
|
|
8
|
+
* §12.6.4.2, §12.6.4.3, §12.6.4.4.
|
|
9
|
+
*
|
|
10
|
+
* GoTo — navigate to a destination in the current document.
|
|
11
|
+
* GoToR — navigate to a destination in a remote document (`/F` + `/D`).
|
|
12
|
+
* GoToE — navigate to a destination in an embedded document.
|
|
13
|
+
*
|
|
14
|
+
* These typers read the raw entries; resolution of `/F` (file
|
|
15
|
+
* specification) and `/D` (destination) is left to the caller via
|
|
16
|
+
* dedicated modules (`fileSpec`, `destination`).
|
|
17
|
+
*
|
|
18
|
+
* @module pdf/action/goTo
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Module factory.
|
|
23
|
+
*/
|
|
24
|
+
import { pdfErrors } from '../errors.js';
|
|
25
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
26
|
+
|
|
27
|
+
export const pdfActionGoTo = {
|
|
28
|
+
name: 'pdfActionGoTo',
|
|
29
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
30
|
+
deps: [pdfErrors, pdfParser],
|
|
31
|
+
factory(errors, parser) {
|
|
32
|
+
const { ParseError } = errors;
|
|
33
|
+
const { isType } = parser;
|
|
34
|
+
|
|
35
|
+
function expectDict(d, kind) {
|
|
36
|
+
if (!isType(d, 'dict')) {
|
|
37
|
+
throw new ParseError('pdf/action/' + kind.toLowerCase() + '/not-dict',
|
|
38
|
+
kind + ' action must be a dictionary',
|
|
39
|
+
{ context: { type: d && d.type } });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function typeGoTo(dict) {
|
|
44
|
+
expectDict(dict, 'GoTo');
|
|
45
|
+
const e = dict.entries;
|
|
46
|
+
if (!e.D) {
|
|
47
|
+
throw new ParseError('pdf/action/goto/missing-d',
|
|
48
|
+
'GoTo action is missing /D');
|
|
49
|
+
}
|
|
50
|
+
return { kind: 'GoTo', dest: e.D, raw: dict };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function typeGoToR(dict) {
|
|
54
|
+
expectDict(dict, 'GoToR');
|
|
55
|
+
const e = dict.entries;
|
|
56
|
+
if (!e.F) {
|
|
57
|
+
throw new ParseError('pdf/action/gotor/missing-f',
|
|
58
|
+
'GoToR action is missing /F');
|
|
59
|
+
}
|
|
60
|
+
if (!e.D) {
|
|
61
|
+
throw new ParseError('pdf/action/gotor/missing-d',
|
|
62
|
+
'GoToR action is missing /D');
|
|
63
|
+
}
|
|
64
|
+
const out = { kind: 'GoToR', file: e.F, dest: e.D, raw: dict };
|
|
65
|
+
if (e.NewWindow && e.NewWindow.type === 'bool') {
|
|
66
|
+
out.newWindow = e.NewWindow.value;
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function typeGoToE(dict) {
|
|
72
|
+
expectDict(dict, 'GoToE');
|
|
73
|
+
const e = dict.entries;
|
|
74
|
+
if (!e.D) {
|
|
75
|
+
throw new ParseError('pdf/action/gotoe/missing-d',
|
|
76
|
+
'GoToE action is missing /D');
|
|
77
|
+
}
|
|
78
|
+
const out = { kind: 'GoToE', dest: e.D, raw: dict };
|
|
79
|
+
if (e.F) out.file = e.F;
|
|
80
|
+
if (e.T) out.target = e.T;
|
|
81
|
+
if (e.NewWindow && e.NewWindow.type === 'bool') {
|
|
82
|
+
out.newWindow = e.NewWindow.value;
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return { typeGoTo, typeGoToR, typeGoToE };
|
|
88
|
+
}
|
|
89
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
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 Launch action per ISO 32000-2:2020 §12.6.4.6.
|
|
8
|
+
*
|
|
9
|
+
* `/S /Launch` actions request the PDF viewer to run an external
|
|
10
|
+
* application or open a file. Executing such an action is a known
|
|
11
|
+
* security risk; this typer **never executes anything** — it surfaces
|
|
12
|
+
* the entries plus a `securityWarning` flag so the host application can
|
|
13
|
+
* decide what to do (typically: ignore, or prompt the user).
|
|
14
|
+
*
|
|
15
|
+
* @module pdf/action/launch
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Module factory.
|
|
20
|
+
*/
|
|
21
|
+
import { pdfErrors } from '../errors.js';
|
|
22
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
23
|
+
|
|
24
|
+
export const pdfActionLaunch = {
|
|
25
|
+
name: 'pdfActionLaunch',
|
|
26
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
27
|
+
deps: [pdfErrors, pdfParser],
|
|
28
|
+
factory(errors, parser) {
|
|
29
|
+
const { ParseError } = errors;
|
|
30
|
+
const { isType } = parser;
|
|
31
|
+
|
|
32
|
+
function typeLaunch(dict) {
|
|
33
|
+
if (!isType(dict, 'dict')) {
|
|
34
|
+
throw new ParseError('pdf/action/launch/not-dict',
|
|
35
|
+
'Launch action must be a dictionary',
|
|
36
|
+
{ context: { type: dict && dict.type } });
|
|
37
|
+
}
|
|
38
|
+
const e = dict.entries;
|
|
39
|
+
const out = {
|
|
40
|
+
kind: 'Launch',
|
|
41
|
+
sandboxed: true,
|
|
42
|
+
securityWarning: 'launch actions are not executed by @awacloud/pdf',
|
|
43
|
+
raw: dict
|
|
44
|
+
};
|
|
45
|
+
if (e.F) out.file = e.F;
|
|
46
|
+
if (e.Win && e.Win.type === 'dict') out.win = e.Win;
|
|
47
|
+
if (e.Mac && e.Mac.type === 'dict') out.mac = e.Mac;
|
|
48
|
+
if (e.Unix && e.Unix.type === 'dict') out.unix = e.Unix;
|
|
49
|
+
if (e.NewWindow && e.NewWindow.type === 'bool') {
|
|
50
|
+
out.newWindow = e.NewWindow.value;
|
|
51
|
+
}
|
|
52
|
+
if (!out.file && !out.win && !out.mac && !out.unix) {
|
|
53
|
+
throw new ParseError('pdf/action/launch/empty',
|
|
54
|
+
'Launch action has no /F, /Win, /Mac, or /Unix target');
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return { typeLaunch };
|
|
60
|
+
}
|
|
61
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
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 Named action per ISO 32000-2:2020 §12.6.4.11.
|
|
8
|
+
*
|
|
9
|
+
* `/S /Named` actions carry a `/N` name. The standard predefined names
|
|
10
|
+
* are NextPage, PrevPage, FirstPage, LastPage; vendor-defined names are
|
|
11
|
+
* accepted but flagged via `standard: false`.
|
|
12
|
+
*
|
|
13
|
+
* @module pdf/action/named
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Module factory.
|
|
18
|
+
*/
|
|
19
|
+
import { pdfErrors } from '../errors.js';
|
|
20
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
21
|
+
|
|
22
|
+
export const pdfActionNamed = {
|
|
23
|
+
name: 'pdfActionNamed',
|
|
24
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
25
|
+
deps: [pdfErrors, pdfParser],
|
|
26
|
+
factory(errors, parser) {
|
|
27
|
+
const { ParseError } = errors;
|
|
28
|
+
const { isType } = parser;
|
|
29
|
+
|
|
30
|
+
const STANDARD = new Set(['NextPage', 'PrevPage', 'FirstPage', 'LastPage']);
|
|
31
|
+
|
|
32
|
+
function typeNamed(dict) {
|
|
33
|
+
if (!isType(dict, 'dict')) {
|
|
34
|
+
throw new ParseError('pdf/action/named/not-dict',
|
|
35
|
+
'Named action must be a dictionary',
|
|
36
|
+
{ context: { type: dict && dict.type } });
|
|
37
|
+
}
|
|
38
|
+
const e = dict.entries;
|
|
39
|
+
if (!e.N || e.N.type !== 'name') {
|
|
40
|
+
throw new ParseError('pdf/action/named/missing-n',
|
|
41
|
+
'Named action missing /N name',
|
|
42
|
+
{ context: { type: e.N && e.N.type } });
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
kind: 'Named',
|
|
46
|
+
name: e.N.value,
|
|
47
|
+
standard: STANDARD.has(e.N.value),
|
|
48
|
+
raw: dict
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return { typeNamed };
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
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 URI action per ISO 32000-2:2020 §12.6.4.7.
|
|
8
|
+
*
|
|
9
|
+
* `/S /URI` actions navigate to a URI; `/IsMap` indicates that mouse
|
|
10
|
+
* coordinates should be appended for image-map style links. The URI
|
|
11
|
+
* value is preserved as a raw byte string — callers decide how to
|
|
12
|
+
* decode it (typically PDFDocEncoding or UTF-8).
|
|
13
|
+
*
|
|
14
|
+
* @module pdf/action/uri
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Module factory — worker-safe, self-contained.
|
|
19
|
+
*/
|
|
20
|
+
import { pdfErrors } from '../errors.js';
|
|
21
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
22
|
+
|
|
23
|
+
export const pdfActionUri = {
|
|
24
|
+
name: 'pdfActionUri',
|
|
25
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
26
|
+
deps: [pdfErrors, pdfParser],
|
|
27
|
+
factory(errors) {
|
|
28
|
+
const { ParseError } = errors;
|
|
29
|
+
// Self-contained isType: tolerates `parser = {}` from tests.
|
|
30
|
+
function isType(node, kind) { return !!(node && node.type === kind); }
|
|
31
|
+
|
|
32
|
+
function typeUri(dict) {
|
|
33
|
+
if (!isType(dict, 'dict')) {
|
|
34
|
+
throw new ParseError('pdf/action/uri/not-dict',
|
|
35
|
+
'URI action must be a dictionary',
|
|
36
|
+
{ context: { type: dict && dict.type } });
|
|
37
|
+
}
|
|
38
|
+
const e = dict.entries;
|
|
39
|
+
if (!e.URI || e.URI.type !== 'string') {
|
|
40
|
+
throw new ParseError('pdf/action/uri/missing',
|
|
41
|
+
'URI action missing /URI string',
|
|
42
|
+
{ context: { type: e.URI && e.URI.type } });
|
|
43
|
+
}
|
|
44
|
+
const out = { kind: 'URI', uri: e.URI.value, raw: dict };
|
|
45
|
+
if (e.IsMap && e.IsMap.type === 'bool') out.isMap = e.IsMap.value;
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return { typeUri };
|
|
50
|
+
}
|
|
51
|
+
};
|