@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/src/errors.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
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 Typed error hierarchy for `@awacloud/pdf` — exposed as the
|
|
8
|
+
* `pdfErrors` module factory.
|
|
9
|
+
*
|
|
10
|
+
* Five classes inheriting from `PdfError` :
|
|
11
|
+
*
|
|
12
|
+
* - `ParseError` — malformed input encountered while reading
|
|
13
|
+
* (bad header, truncated xref, unbalanced dict,
|
|
14
|
+
* unknown filter, …).
|
|
15
|
+
* - `RenderError` — invalid model encountered while writing
|
|
16
|
+
* (e.g. circular indirect reference, missing
|
|
17
|
+
* required field on Page).
|
|
18
|
+
* - `ContractError` — the consumer violated the API contract
|
|
19
|
+
* (e.g. `.use()` called twice with the same
|
|
20
|
+
* extension, passing a non-Uint8Array to
|
|
21
|
+
* `.read()`).
|
|
22
|
+
* - `EncryptionError` — encryption / decryption failure (bad password,
|
|
23
|
+
* unsupported Security Handler revision,
|
|
24
|
+
* PKCS#7 verification mismatch).
|
|
25
|
+
*
|
|
26
|
+
* Each error carries a kebab-case `code` (e.g. `'pdf/bad-header'`,
|
|
27
|
+
* `'pdf/xref/truncated'`), an optional `context` object, and an
|
|
28
|
+
* optional `cause`.
|
|
29
|
+
*
|
|
30
|
+
* Classes are declared **inside the factory body** so the factory is a
|
|
31
|
+
* self-contained closure that can be serialised to a Worker via
|
|
32
|
+
* `factory.toString()`. Consumers obtain the classes by resolving the
|
|
33
|
+
* `pdfErrors` module via a `ModuleRuntime` (which caches the resolved
|
|
34
|
+
* instance, providing stable class identities for `instanceof`).
|
|
35
|
+
*
|
|
36
|
+
* ```js
|
|
37
|
+
* const { PdfError, ParseError } = runtime.resolve('pdfErrors');
|
|
38
|
+
* try { pdf.read(bytes); }
|
|
39
|
+
* catch (e) { if (e instanceof PdfError) console.log(e.code, e.context); }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* **Migration (passe 1/2/2a/2b/2c/TD-1 — complete)** — top-level error
|
|
43
|
+
* classes are no longer exported as named ESM bindings and no longer
|
|
44
|
+
* live at module scope. All consumers (source and tests) resolve them
|
|
45
|
+
* via `pdfErrors.factory()` (or, preferably, through a `ModuleRuntime`
|
|
46
|
+
* to share class identities). The transitional compatibility shim that
|
|
47
|
+
* re-exported `PdfError`, `ParseError`, `RenderError`, `ContractError`
|
|
48
|
+
* and `EncryptionError` was removed at the end of passe 2c.
|
|
49
|
+
*
|
|
50
|
+
* @module pdf/errors
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
export const pdfErrors = {
|
|
54
|
+
name: 'pdfErrors',
|
|
55
|
+
dependencies: [],
|
|
56
|
+
factory() {
|
|
57
|
+
class PdfError extends Error {
|
|
58
|
+
constructor(code, message, opts) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = new.target.name;
|
|
61
|
+
this.code = code;
|
|
62
|
+
if (opts && opts.context) this.context = opts.context;
|
|
63
|
+
if (opts && opts.cause) this.cause = opts.cause;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
class ParseError extends PdfError {}
|
|
67
|
+
class RenderError extends PdfError {}
|
|
68
|
+
class ContractError extends PdfError {}
|
|
69
|
+
class EncryptionError extends PdfError {}
|
|
70
|
+
|
|
71
|
+
function isPdfError(e) { return e instanceof PdfError; }
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
PdfError, ParseError, RenderError, ContractError, EncryptionError,
|
|
75
|
+
isPdfError
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,171 @@
|
|
|
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: 3D and RichMedia annotation typing.
|
|
8
|
+
*
|
|
9
|
+
* ISO 32000-2:2020 §13.6 defines two interactive multimedia annotation
|
|
10
|
+
* subtypes:
|
|
11
|
+
*
|
|
12
|
+
* - `/Subtype /3D` (§13.6.2) — references a 3D stream via `/3DD`,
|
|
13
|
+
* default view (`/3DV`), activation dict (`/3DA`), interactive
|
|
14
|
+
* dict (`/3DI`).
|
|
15
|
+
*
|
|
16
|
+
* - `/Subtype /RichMedia` (§13.6.3) — `/RichMediaContent` with
|
|
17
|
+
* `/Assets`, `/Configurations`, `/Views`; `/RichMediaSettings`
|
|
18
|
+
* with `/Activation`, `/Deactivation`, instance state.
|
|
19
|
+
*
|
|
20
|
+
* @module pdf/extra/3d-richmedia
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Module factory.
|
|
25
|
+
*/
|
|
26
|
+
import { pdfErrors } from '../errors.js';
|
|
27
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
28
|
+
|
|
29
|
+
export const pdf3dRichMedia = {
|
|
30
|
+
name: 'pdf3dRichMedia',
|
|
31
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
32
|
+
deps: [pdfErrors, pdfParser],
|
|
33
|
+
factory(errors, parser) {
|
|
34
|
+
const { ParseError } = errors;
|
|
35
|
+
const { isType } = parser;
|
|
36
|
+
|
|
37
|
+
const THREE_D_KNOWN = new Set([
|
|
38
|
+
'Type', 'Subtype', 'Rect', '3DD', '3DV', '3DA', '3DI', '3DB'
|
|
39
|
+
]);
|
|
40
|
+
const RM_KNOWN = new Set([
|
|
41
|
+
'Type', 'Subtype', 'Rect', 'RichMediaContent', 'RichMediaSettings'
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
const RM_INSTANCE_STATES = Object.freeze({
|
|
45
|
+
A: 'active',
|
|
46
|
+
L: 'loaded',
|
|
47
|
+
U: 'uninstantiated'
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const ACTIVATION_CONDITIONS = Object.freeze({
|
|
51
|
+
XA: 'explicit activate',
|
|
52
|
+
PO: 'page open',
|
|
53
|
+
PV: 'page visible'
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
function type3DAnnot(dict) {
|
|
57
|
+
if (!isType(dict, 'dict')) {
|
|
58
|
+
throw new ParseError('pdf/extra/3d/not-dict',
|
|
59
|
+
'3D annotation must be a dictionary',
|
|
60
|
+
{ context: { type: dict && dict.type } });
|
|
61
|
+
}
|
|
62
|
+
const e = dict.entries;
|
|
63
|
+
if (e.Subtype && (e.Subtype.type !== 'name' || e.Subtype.value !== '3D')) {
|
|
64
|
+
throw new ParseError('pdf/extra/3d/bad-subtype',
|
|
65
|
+
'/Subtype must be /3D',
|
|
66
|
+
{ context: { actual: e.Subtype.value } });
|
|
67
|
+
}
|
|
68
|
+
if (!e['3DD']) {
|
|
69
|
+
throw new ParseError('pdf/extra/3d/missing-3dd',
|
|
70
|
+
'3D annotation requires /3DD entry');
|
|
71
|
+
}
|
|
72
|
+
const out = {
|
|
73
|
+
threeDD: e['3DD'],
|
|
74
|
+
threeDV: e['3DV'] || null,
|
|
75
|
+
threeDA: isType(e['3DA'], 'dict') ? type3DActivation(e['3DA']) : null,
|
|
76
|
+
threeDI: isType(e['3DI'], 'bool') ? e['3DI'].value : null,
|
|
77
|
+
threeDB: e['3DB'] || null,
|
|
78
|
+
raw: dict,
|
|
79
|
+
_extras: {}
|
|
80
|
+
};
|
|
81
|
+
for (const k of Object.keys(e)) {
|
|
82
|
+
if (!THREE_D_KNOWN.has(k)) out._extras[k] = e[k];
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function type3DActivation(dict) {
|
|
88
|
+
if (!isType(dict, 'dict')) {
|
|
89
|
+
throw new ParseError('pdf/extra/3d/act/not-dict',
|
|
90
|
+
'/3DA must be a dictionary',
|
|
91
|
+
{ context: { type: dict && dict.type } });
|
|
92
|
+
}
|
|
93
|
+
const e = dict.entries;
|
|
94
|
+
return {
|
|
95
|
+
a: isType(e.A, 'name') ? e.A.value : null,
|
|
96
|
+
ais: isType(e.AIS, 'name') ? e.AIS.value : null,
|
|
97
|
+
d: isType(e.D, 'name') ? e.D.value : null,
|
|
98
|
+
dis: isType(e.DIS, 'name') ? e.DIS.value : null,
|
|
99
|
+
tb: isType(e.TB, 'bool') ? e.TB.value : null,
|
|
100
|
+
np: isType(e.NP, 'bool') ? e.NP.value : null,
|
|
101
|
+
raw: dict
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function typeRichMediaAnnot(dict) {
|
|
106
|
+
if (!isType(dict, 'dict')) {
|
|
107
|
+
throw new ParseError('pdf/extra/rm/not-dict',
|
|
108
|
+
'RichMedia annotation must be a dictionary',
|
|
109
|
+
{ context: { type: dict && dict.type } });
|
|
110
|
+
}
|
|
111
|
+
const e = dict.entries;
|
|
112
|
+
if (e.Subtype && (e.Subtype.type !== 'name' || e.Subtype.value !== 'RichMedia')) {
|
|
113
|
+
throw new ParseError('pdf/extra/rm/bad-subtype',
|
|
114
|
+
'/Subtype must be /RichMedia',
|
|
115
|
+
{ context: { actual: e.Subtype.value } });
|
|
116
|
+
}
|
|
117
|
+
if (!e.RichMediaContent) {
|
|
118
|
+
throw new ParseError('pdf/extra/rm/missing-content',
|
|
119
|
+
'RichMedia annotation requires /RichMediaContent');
|
|
120
|
+
}
|
|
121
|
+
const out = {
|
|
122
|
+
content: isType(e.RichMediaContent, 'dict')
|
|
123
|
+
? typeRichMediaContent(e.RichMediaContent) : e.RichMediaContent,
|
|
124
|
+
settings: isType(e.RichMediaSettings, 'dict')
|
|
125
|
+
? e.RichMediaSettings : null,
|
|
126
|
+
raw: dict,
|
|
127
|
+
_extras: {}
|
|
128
|
+
};
|
|
129
|
+
for (const k of Object.keys(e)) {
|
|
130
|
+
if (!RM_KNOWN.has(k)) out._extras[k] = e[k];
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function typeRichMediaContent(dict) {
|
|
136
|
+
if (!isType(dict, 'dict')) {
|
|
137
|
+
throw new ParseError('pdf/extra/rm/content/not-dict',
|
|
138
|
+
'/RichMediaContent must be a dictionary',
|
|
139
|
+
{ context: { type: dict && dict.type } });
|
|
140
|
+
}
|
|
141
|
+
const e = dict.entries;
|
|
142
|
+
return {
|
|
143
|
+
assets: e.Assets || null,
|
|
144
|
+
configurations: e.Configurations || null,
|
|
145
|
+
views: e.Views || null,
|
|
146
|
+
raw: dict
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function classifyRmInstanceState(name) {
|
|
151
|
+
if (name == null) return null;
|
|
152
|
+
if (typeof name !== 'string') {
|
|
153
|
+
throw new ParseError('pdf/extra/rm/state/bad',
|
|
154
|
+
'state must be a string',
|
|
155
|
+
{ context: { type: typeof name } });
|
|
156
|
+
}
|
|
157
|
+
return RM_INSTANCE_STATES[name] || null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
type3DAnnot,
|
|
162
|
+
type3DActivation,
|
|
163
|
+
typeRichMediaAnnot,
|
|
164
|
+
typeRichMediaContent,
|
|
165
|
+
classifyRmInstanceState,
|
|
166
|
+
RM_INSTANCE_STATES,
|
|
167
|
+
ACTIVATION_CONDITIONS
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
@@ -0,0 +1,200 @@
|
|
|
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 annotation subtypes per
|
|
8
|
+
* ISO 32000-2:2020 §12.5.6.
|
|
9
|
+
*
|
|
10
|
+
* Covers: Watermark (§12.5.6.22), 3D (§13.6), RichMedia (§13.6.2),
|
|
11
|
+
* Sound (§12.5.6.16 legacy), Movie (§12.5.6.17 legacy),
|
|
12
|
+
* Screen (§12.5.6.18), PrinterMark (§12.5.6.20), TrapNet (§12.5.6.21),
|
|
13
|
+
* and FreeText-extended (`/RC`, `/DS`, `/LE`, §12.5.6.6).
|
|
14
|
+
*
|
|
15
|
+
* Each typer composes `typeBaseAnnot` from `../annot/annot.js` so the
|
|
16
|
+
* common annotation entries are preserved.
|
|
17
|
+
*
|
|
18
|
+
* @module pdf/extra/annot-extended
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Module factory.
|
|
23
|
+
*/
|
|
24
|
+
import { pdfErrors } from '../errors.js';
|
|
25
|
+
import { pdfParserObj } from '../syntax/parser-obj.js';
|
|
26
|
+
import { pdfAnnot } from '../annot/annot.js';
|
|
27
|
+
|
|
28
|
+
export const pdfAnnotExtended = {
|
|
29
|
+
name: 'pdfAnnotExtended',
|
|
30
|
+
dependencies: ['pdfErrors', 'pdfParserObj', 'pdfAnnot'],
|
|
31
|
+
deps: [pdfErrors, pdfParserObj, pdfAnnot],
|
|
32
|
+
factory(errors, parserObj, annot) {
|
|
33
|
+
const { ParseError } = errors;
|
|
34
|
+
const { isType } = parserObj;
|
|
35
|
+
const { typeBaseAnnot, captureExtras } = annot;
|
|
36
|
+
|
|
37
|
+
const SUBTYPES = new Set([
|
|
38
|
+
'Watermark', '3D', 'RichMedia', 'Sound', 'Movie', 'Screen',
|
|
39
|
+
'PrinterMark', 'TrapNet', 'FreeText'
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
const FREETEXT_LINE_ENDINGS = Object.freeze([
|
|
43
|
+
'Square', 'Circle', 'Diamond', 'OpenArrow', 'ClosedArrow', 'None',
|
|
44
|
+
'Butt', 'ROpenArrow', 'RClosedArrow', 'Slash'
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
function typeAnnotExtended(dict) {
|
|
48
|
+
if (!isType(dict, 'dict')) {
|
|
49
|
+
throw new ParseError('pdf/extra/annot-ext/not-dict',
|
|
50
|
+
'annotation must be a dictionary',
|
|
51
|
+
{ context: { type: dict && dict.type } });
|
|
52
|
+
}
|
|
53
|
+
const sub = dict.entries.Subtype;
|
|
54
|
+
if (!isType(sub, 'name') || !SUBTYPES.has(sub.value)) {
|
|
55
|
+
throw new ParseError('pdf/extra/annot-ext/unsupported',
|
|
56
|
+
'unsupported extended annotation subtype',
|
|
57
|
+
{ context: { subtype: sub && sub.value } });
|
|
58
|
+
}
|
|
59
|
+
switch (sub.value) {
|
|
60
|
+
case 'Watermark': return typeWatermarkAnnot(dict);
|
|
61
|
+
case '3D': return type3DAnnot(dict);
|
|
62
|
+
case 'RichMedia': return typeRichMediaAnnot(dict);
|
|
63
|
+
case 'Sound': return typeSoundAnnot(dict);
|
|
64
|
+
case 'Movie': return typeMovieAnnot(dict);
|
|
65
|
+
case 'Screen': return typeScreenAnnot(dict);
|
|
66
|
+
case 'PrinterMark': return typePrinterMarkAnnot(dict);
|
|
67
|
+
case 'TrapNet': return typeTrapNetAnnot(dict);
|
|
68
|
+
case 'FreeText': return typeFreeTextExtended(dict);
|
|
69
|
+
}
|
|
70
|
+
/* istanbul ignore next */
|
|
71
|
+
throw new ParseError('pdf/extra/annot-ext/unreachable', 'unreachable');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function typeWatermarkAnnot(dict) {
|
|
75
|
+
const base = typeBaseAnnot(dict);
|
|
76
|
+
base.kind = 'Watermark';
|
|
77
|
+
const e = dict.entries;
|
|
78
|
+
base.fixedPrint = isType(e.FixedPrint, 'dict') ? e.FixedPrint : null;
|
|
79
|
+
captureExtras(base, dict, new Set(['FixedPrint']));
|
|
80
|
+
return base;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function type3DAnnot(dict) {
|
|
84
|
+
const base = typeBaseAnnot(dict);
|
|
85
|
+
base.kind = '3D';
|
|
86
|
+
const e = dict.entries;
|
|
87
|
+
base['3DD'] = e['3DD'] || null;
|
|
88
|
+
base['3DV'] = e['3DV'] || null;
|
|
89
|
+
base['3DA'] = e['3DA'] || null;
|
|
90
|
+
base['3DI'] = isType(e['3DI'], 'bool') ? e['3DI'].value : null;
|
|
91
|
+
base['3DB'] = e['3DB'] || null;
|
|
92
|
+
captureExtras(base, dict, new Set(['3DD', '3DV', '3DA', '3DI', '3DB']));
|
|
93
|
+
return base;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function typeRichMediaAnnot(dict) {
|
|
97
|
+
const base = typeBaseAnnot(dict);
|
|
98
|
+
base.kind = 'RichMedia';
|
|
99
|
+
const e = dict.entries;
|
|
100
|
+
base.richMediaContent = e.RichMediaContent || null;
|
|
101
|
+
base.richMediaSettings = e.RichMediaSettings || null;
|
|
102
|
+
captureExtras(base, dict, new Set(['RichMediaContent', 'RichMediaSettings']));
|
|
103
|
+
return base;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function typeSoundAnnot(dict) {
|
|
107
|
+
const base = typeBaseAnnot(dict);
|
|
108
|
+
base.kind = 'Sound';
|
|
109
|
+
const e = dict.entries;
|
|
110
|
+
base.sound = e.Sound || null;
|
|
111
|
+
base.name = isType(e.Name, 'name') ? e.Name.value : null;
|
|
112
|
+
captureExtras(base, dict, new Set(['Sound', 'Name']));
|
|
113
|
+
return base;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function typeMovieAnnot(dict) {
|
|
117
|
+
const base = typeBaseAnnot(dict);
|
|
118
|
+
base.kind = 'Movie';
|
|
119
|
+
const e = dict.entries;
|
|
120
|
+
base.t = isType(e.T, 'string') ? e.T.value : null;
|
|
121
|
+
base.movie = e.Movie || null;
|
|
122
|
+
base.activation = e.A || null;
|
|
123
|
+
captureExtras(base, dict, new Set(['T', 'Movie', 'A']));
|
|
124
|
+
return base;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function typeScreenAnnot(dict) {
|
|
128
|
+
const base = typeBaseAnnot(dict);
|
|
129
|
+
base.kind = 'Screen';
|
|
130
|
+
const e = dict.entries;
|
|
131
|
+
base.t = isType(e.T, 'string') ? e.T.value : null;
|
|
132
|
+
base.mk = e.MK || null;
|
|
133
|
+
base.a = e.A || null;
|
|
134
|
+
base.aa = e.AA || null;
|
|
135
|
+
captureExtras(base, dict, new Set(['T', 'MK', 'A', 'AA']));
|
|
136
|
+
return base;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function typePrinterMarkAnnot(dict) {
|
|
140
|
+
const base = typeBaseAnnot(dict);
|
|
141
|
+
base.kind = 'PrinterMark';
|
|
142
|
+
const e = dict.entries;
|
|
143
|
+
base.mn = isType(e.MN, 'name') ? e.MN.value : null;
|
|
144
|
+
captureExtras(base, dict, new Set(['MN']));
|
|
145
|
+
return base;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function typeTrapNetAnnot(dict) {
|
|
149
|
+
const base = typeBaseAnnot(dict);
|
|
150
|
+
base.kind = 'TrapNet';
|
|
151
|
+
const e = dict.entries;
|
|
152
|
+
base.lastModified = isType(e.LastModified, 'string') ? e.LastModified.value : null;
|
|
153
|
+
base.version = e.Version || null;
|
|
154
|
+
base.annotStates = e.AnnotStates || null;
|
|
155
|
+
base.fontFauxing = e.FontFauxing || null;
|
|
156
|
+
captureExtras(base, dict, new Set(['LastModified', 'Version', 'AnnotStates', 'FontFauxing']));
|
|
157
|
+
return base;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function typeFreeTextExtended(dict) {
|
|
161
|
+
const base = typeBaseAnnot(dict);
|
|
162
|
+
base.kind = 'FreeText';
|
|
163
|
+
const e = dict.entries;
|
|
164
|
+
base.da = isType(e.DA, 'string') ? e.DA.value : null;
|
|
165
|
+
base.q = (e.Q && (e.Q.type === 'int' || e.Q.type === 'real')) ? (e.Q.value | 0) : null;
|
|
166
|
+
base.rc = isType(e.RC, 'string') ? e.RC.value : (isType(e.RC, 'stream') ? e.RC : null);
|
|
167
|
+
base.ds = isType(e.DS, 'string') ? e.DS.value : null;
|
|
168
|
+
base.cl = isType(e.CL, 'array') ? toNumArray(e.CL) : null;
|
|
169
|
+
base.it = isType(e.IT, 'name') ? e.IT.value : null;
|
|
170
|
+
base.be = e.BE || null;
|
|
171
|
+
base.rd = isType(e.RD, 'array') ? toNumArray(e.RD) : null;
|
|
172
|
+
let le = null;
|
|
173
|
+
if (isType(e.LE, 'name')) le = e.LE.value;
|
|
174
|
+
else if (isType(e.LE, 'array')) {
|
|
175
|
+
le = e.LE.items.filter(it => isType(it, 'name')).map(it => it.value);
|
|
176
|
+
}
|
|
177
|
+
base.le = le;
|
|
178
|
+
captureExtras(base, dict, new Set(['DA', 'Q', 'RC', 'DS', 'CL', 'IT', 'BE', 'RD', 'LE']));
|
|
179
|
+
return base;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function toNumArray(v) {
|
|
183
|
+
const out = [];
|
|
184
|
+
for (const it of v.items) {
|
|
185
|
+
if (!it || (it.type !== 'int' && it.type !== 'real')) return null;
|
|
186
|
+
out.push(it.value);
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return {
|
|
192
|
+
typeAnnotExtended,
|
|
193
|
+
typeWatermarkAnnot, type3DAnnot, typeRichMediaAnnot,
|
|
194
|
+
typeSoundAnnot, typeMovieAnnot, typeScreenAnnot,
|
|
195
|
+
typePrinterMarkAnnot, typeTrapNetAnnot, typeFreeTextExtended,
|
|
196
|
+
FREETEXT_LINE_ENDINGS
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
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 /AF (Associated Files) typing.
|
|
8
|
+
*
|
|
9
|
+
* PDF 2.0 lets /AF live on the Catalog, Page, XObject (Form), Mark,
|
|
10
|
+
* StructElem, Annot, or DParams. Each item references a File
|
|
11
|
+
* Specification dictionary that MUST carry /AFRelationship.
|
|
12
|
+
*
|
|
13
|
+
* Relationship vocabulary: Source, Data, Alternative, Supplement,
|
|
14
|
+
* EncryptedPayload, FormData, Schema, Unspecified.
|
|
15
|
+
*
|
|
16
|
+
* @module pdf/extra/associated-files
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { pdfErrors } from '../errors.js';
|
|
20
|
+
|
|
21
|
+
export const pdfAssociatedFiles2 = {
|
|
22
|
+
name: 'pdfAssociatedFiles2',
|
|
23
|
+
dependencies: ['pdfErrors'],
|
|
24
|
+
deps: [pdfErrors],
|
|
25
|
+
|
|
26
|
+
factory(errors) {
|
|
27
|
+
const { ParseError } = errors;
|
|
28
|
+
const STANDARD_REL = new Set([
|
|
29
|
+
'Source', 'Data', 'Alternative', 'Supplement',
|
|
30
|
+
'EncryptedPayload', 'FormData', 'Schema', 'Unspecified'
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
const CARRIER_HINTS = new Set([
|
|
34
|
+
'Catalog', 'Page', 'XObject', 'StructElem', 'Annot', 'Mark', 'DParams'
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
function isDict(v) { return v && v.type === 'dict'; }
|
|
38
|
+
function isName(v) { return v && v.type === 'name'; }
|
|
39
|
+
function isArr(v) { return v && v.type === 'array'; }
|
|
40
|
+
function isRef(v) { return v && v.type === 'ref'; }
|
|
41
|
+
|
|
42
|
+
function resolveFileSpec(entry, resolveRef) {
|
|
43
|
+
if (isRef(entry)) {
|
|
44
|
+
if (typeof resolveRef === 'function') {
|
|
45
|
+
const r = resolveRef(entry);
|
|
46
|
+
return { resolved: true, dict: r, ref: { num: entry.num, gen: entry.gen } };
|
|
47
|
+
}
|
|
48
|
+
return { resolved: false, ref: { num: entry.num, gen: entry.gen } };
|
|
49
|
+
}
|
|
50
|
+
if (isDict(entry)) return { resolved: true, dict: entry };
|
|
51
|
+
throw new ParseError('pdf/af2/bad-entry',
|
|
52
|
+
'/AF entry must be a dict or indirect reference',
|
|
53
|
+
{ context: { type: entry && entry.type } });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function typeAfEntry(entry, resolveRef, index) {
|
|
57
|
+
const res = resolveFileSpec(entry, resolveRef);
|
|
58
|
+
if (!res.resolved) {
|
|
59
|
+
return { ref: res.ref, resolved: false };
|
|
60
|
+
}
|
|
61
|
+
const dict = res.dict;
|
|
62
|
+
if (!isDict(dict)) {
|
|
63
|
+
throw new ParseError('pdf/af2/not-filespec',
|
|
64
|
+
'resolved /AF entry must be a dict',
|
|
65
|
+
{ context: { index } });
|
|
66
|
+
}
|
|
67
|
+
const e = dict.entries;
|
|
68
|
+
if (e.Type && (!isName(e.Type) || e.Type.value !== 'Filespec')) {
|
|
69
|
+
throw new ParseError('pdf/af2/bad-filespec-type',
|
|
70
|
+
'expected /Type /Filespec',
|
|
71
|
+
{ context: { index, actual: e.Type && e.Type.value } });
|
|
72
|
+
}
|
|
73
|
+
let rel = null, standard = false;
|
|
74
|
+
if (e.AFRelationship) {
|
|
75
|
+
if (!isName(e.AFRelationship)) {
|
|
76
|
+
throw new ParseError('pdf/af2/bad-relationship',
|
|
77
|
+
'/AFRelationship must be a name',
|
|
78
|
+
{ context: { index, type: e.AFRelationship.type } });
|
|
79
|
+
}
|
|
80
|
+
rel = e.AFRelationship.value;
|
|
81
|
+
standard = STANDARD_REL.has(rel);
|
|
82
|
+
}
|
|
83
|
+
const out = {
|
|
84
|
+
filespec: dict,
|
|
85
|
+
relationship: rel,
|
|
86
|
+
standard,
|
|
87
|
+
resolved: true
|
|
88
|
+
};
|
|
89
|
+
if (res.ref) out.ref = res.ref;
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function typeAf(afArray, opts) {
|
|
94
|
+
const resolveRef = opts && opts.resolveRef;
|
|
95
|
+
const carrier = opts && opts.carrier;
|
|
96
|
+
if (carrier && !CARRIER_HINTS.has(carrier)) {
|
|
97
|
+
throw new ParseError('pdf/af2/bad-carrier',
|
|
98
|
+
'unknown /AF carrier hint',
|
|
99
|
+
{ context: { carrier } });
|
|
100
|
+
}
|
|
101
|
+
if (!isArr(afArray)) {
|
|
102
|
+
throw new ParseError('pdf/af2/not-array',
|
|
103
|
+
'/AF must be an array',
|
|
104
|
+
{ context: { type: afArray && afArray.type } });
|
|
105
|
+
}
|
|
106
|
+
const out = [];
|
|
107
|
+
for (let i = 0; i < afArray.items.length; i++) {
|
|
108
|
+
out.push(typeAfEntry(afArray.items[i], resolveRef, i));
|
|
109
|
+
}
|
|
110
|
+
return { entries: out, carrier: carrier || null };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isStandardRelationship(name) {
|
|
114
|
+
return STANDARD_REL.has(String(name));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function listStandardRelationships() {
|
|
118
|
+
return Array.from(STANDARD_REL);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
typeAf,
|
|
123
|
+
typeAfEntry,
|
|
124
|
+
resolveFileSpec,
|
|
125
|
+
isStandardRelationship,
|
|
126
|
+
listStandardRelationships,
|
|
127
|
+
STANDARD_REL,
|
|
128
|
+
CARRIER_HINTS
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|