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