@laminapdf/sdk 0.2.0-alpha.2 → 0.2.0-alpha.3
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/README.md +42 -7
- package/dist/api.d.ts +5 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +3 -2
- package/dist/api.js.map +1 -1
- package/dist/builder.d.ts +35 -19
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +114 -80
- package/dist/builder.js.map +1 -1
- package/dist/document.d.ts +47 -21
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +112 -67
- package/dist/document.js.map +1 -1
- package/dist/errors.d.ts +5 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +10 -16
- package/dist/errors.js.map +1 -1
- package/dist/extract.d.ts +57 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +5 -0
- package/dist/extract.js.map +1 -0
- package/dist/font.d.ts +13 -6
- package/dist/font.d.ts.map +1 -1
- package/dist/font.js +50 -20
- package/dist/font.js.map +1 -1
- package/dist/generated/codes.d.ts +18 -6
- package/dist/generated/codes.d.ts.map +1 -1
- package/dist/generated/codes.js +59 -4
- package/dist/generated/codes.js.map +1 -1
- package/dist/generated/explain.d.ts.map +1 -1
- package/dist/generated/explain.js +27 -10
- package/dist/generated/explain.js.map +1 -1
- package/dist/generated/extract.d.ts +235 -0
- package/dist/generated/extract.d.ts.map +1 -0
- package/dist/generated/extract.js +4 -0
- package/dist/generated/extract.js.map +1 -0
- package/dist/init.d.ts +13 -5
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +23 -11
- package/dist/init.js.map +1 -1
- package/dist/internal/handle.d.ts +58 -0
- package/dist/internal/handle.d.ts.map +1 -0
- package/dist/internal/handle.js +113 -0
- package/dist/internal/handle.js.map +1 -0
- package/dist/internal/instance.d.ts +56 -0
- package/dist/internal/instance.d.ts.map +1 -0
- package/dist/internal/instance.js +125 -0
- package/dist/internal/instance.js.map +1 -0
- package/dist/source/http.js +1 -1
- package/dist/source/http.js.map +1 -1
- package/dist/source/range.d.ts +6 -1
- package/dist/source/range.d.ts.map +1 -1
- package/dist/source/range.js +10 -6
- package/dist/source/range.js.map +1 -1
- package/dist/text.d.ts +3 -3
- package/dist/text.d.ts.map +1 -1
- package/dist/text.js +3 -3
- package/dist/text.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/dist/worker/client.d.ts +3 -2
- package/dist/worker/client.d.ts.map +1 -1
- package/dist/worker/client.js +6 -4
- package/dist/worker/client.js.map +1 -1
- package/dist/worker/entry.js +1 -1
- package/dist/worker/entry.js.map +1 -1
- package/dist/worker/server.d.ts.map +1 -1
- package/dist/worker/server.js +42 -9
- package/dist/worker/server.js.map +1 -1
- package/dist/worker/support.d.ts +6 -2
- package/dist/worker/support.d.ts.map +1 -1
- package/dist/worker/support.js +1 -0
- package/dist/worker/support.js.map +1 -1
- package/dist/worker/types.d.ts +8 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/docs/AGENTS.md +14 -0
- package/docs/api/README.md +147 -0
- package/docs/api/classes/Builder.md +467 -0
- package/docs/api/classes/Document.md +742 -0
- package/docs/api/classes/Font.md +74 -0
- package/docs/api/classes/Image.md +140 -0
- package/docs/api/classes/LaminaPdfError.md +189 -0
- package/docs/api/classes/Page.md +178 -0
- package/docs/api/classes/PageRef.md +253 -0
- package/docs/api/classes/PageText.md +129 -0
- package/docs/api/classes/PageTextRun.md +167 -0
- package/docs/api/classes/PendingPath.md +97 -0
- package/docs/api/classes/SaveJob.md +205 -0
- package/docs/api/classes/Surface.md +326 -0
- package/docs/api/classes/Transaction.md +111 -0
- package/docs/api/functions/callbackSource.md +33 -0
- package/docs/api/functions/httpRangeSource.md +48 -0
- package/docs/api/functions/init.md +36 -0
- package/docs/api/functions/isExtractLoaded.md +21 -0
- package/docs/api/functions/isInitialized.md +19 -0
- package/docs/api/functions/isLaminaPdfError.md +41 -0
- package/docs/api/functions/isTextLoaded.md +19 -0
- package/docs/api/functions/loadExtract.md +28 -0
- package/docs/api/functions/loadText.md +28 -0
- package/docs/api/functions/onLeak.md +29 -0
- package/docs/api/functions/reset.md +22 -0
- package/docs/api/functions/wasmMemory.md +22 -0
- package/docs/api/interfaces/BuilderOptions.md +108 -0
- package/docs/api/interfaces/ByteRange.md +29 -0
- package/docs/api/interfaces/ChunkOptions.md +37 -0
- package/docs/api/interfaces/Diagnostic.md +67 -0
- package/docs/api/interfaces/ExtractOptions.md +92 -0
- package/docs/api/interfaces/ExtractResult.md +37 -0
- package/docs/api/interfaces/FontInfo.md +37 -0
- package/docs/api/interfaces/HttpRangeOptions.md +78 -0
- package/docs/api/interfaces/InitOptions.md +40 -0
- package/docs/api/interfaces/Leak.md +21 -0
- package/docs/api/interfaces/Location.md +53 -0
- package/docs/api/interfaces/OpLog.md +25 -0
- package/docs/api/interfaces/OpenOptions.md +37 -0
- package/docs/api/interfaces/PageTextOptions.md +21 -0
- package/docs/api/interfaces/PathBuilder.md +195 -0
- package/docs/api/interfaces/QuadPoint.md +25 -0
- package/docs/api/interfaces/RangeOptions.md +54 -0
- package/docs/api/interfaces/RangeSource.md +59 -0
- package/docs/api/interfaces/StrokeStyle.md +61 -0
- package/docs/api/interfaces/TagSpec.md +69 -0
- package/docs/api/interfaces/TextBoxOptions.md +93 -0
- package/docs/api/interfaces/TextGlyph.md +29 -0
- package/docs/api/interfaces/TextOptions.md +101 -0
- package/docs/api/interfaces/WasmMemory.md +37 -0
- package/docs/api/type-aliases/AfRelationship.md +15 -0
- package/docs/api/type-aliases/Align.md +15 -0
- package/docs/api/type-aliases/ArtifactKind.md +15 -0
- package/docs/api/type-aliases/AttachmentOptions.md +15 -0
- package/docs/api/type-aliases/BlendMode.md +15 -0
- package/docs/api/type-aliases/BoxRect.md +15 -0
- package/docs/api/type-aliases/BuildOptions.md +15 -0
- package/docs/api/type-aliases/Cell.md +71 -0
- package/docs/api/type-aliases/Chunk.md +79 -0
- package/docs/api/type-aliases/Color.md +16 -0
- package/docs/api/type-aliases/Coordinates.md +55 -0
- package/docs/api/type-aliases/Direction.md +15 -0
- package/docs/api/type-aliases/DocumentInfo.md +15 -0
- package/docs/api/type-aliases/DropReason.md +15 -0
- package/docs/api/type-aliases/Dropped.md +59 -0
- package/docs/api/type-aliases/Edited.md +15 -0
- package/docs/api/type-aliases/ErrorCode.md +15 -0
- package/docs/api/type-aliases/ErrorKind.md +15 -0
- package/docs/api/type-aliases/ExtractFormat.md +15 -0
- package/docs/api/type-aliases/ExtractedBlock.md +82 -0
- package/docs/api/type-aliases/ExtractedPage.md +65 -0
- package/docs/api/type-aliases/ExtractedSource.md +48 -0
- package/docs/api/type-aliases/Extraction.md +22 -0
- package/docs/api/type-aliases/FillRule.md +15 -0
- package/docs/api/type-aliases/Fit.md +15 -0
- package/docs/api/type-aliases/Flags.md +15 -0
- package/docs/api/type-aliases/Generator.md +41 -0
- package/docs/api/type-aliases/GlyphQuad.md +15 -0
- package/docs/api/type-aliases/InfoPatch.md +15 -0
- package/docs/api/type-aliases/LaminaPdfWarning.md +16 -0
- package/docs/api/type-aliases/LimitName.md +15 -0
- package/docs/api/type-aliases/Limits.md +15 -0
- package/docs/api/type-aliases/LineBox.md +15 -0
- package/docs/api/type-aliases/LineCap.md +15 -0
- package/docs/api/type-aliases/LineJoin.md +15 -0
- package/docs/api/type-aliases/LinkTarget.md +15 -0
- package/docs/api/type-aliases/Metadata.md +15 -0
- package/docs/api/type-aliases/Op.md +15 -0
- package/docs/api/type-aliases/OutlineEntry.md +15 -0
- package/docs/api/type-aliases/Overflow.md +15 -0
- package/docs/api/type-aliases/PageInfo.md +15 -0
- package/docs/api/type-aliases/PageLabel.md +15 -0
- package/docs/api/type-aliases/PageSizeName.md +15 -0
- package/docs/api/type-aliases/Point.md +15 -0
- package/docs/api/type-aliases/Profile.md +15 -0
- package/docs/api/type-aliases/Progress.md +15 -0
- package/docs/api/type-aliases/ReadingOrder.md +15 -0
- package/docs/api/type-aliases/Rect.md +15 -0
- package/docs/api/type-aliases/Region.md +31 -0
- package/docs/api/type-aliases/RenderMode.md +15 -0
- package/docs/api/type-aliases/Rotation.md +15 -0
- package/docs/api/type-aliases/SaveOptions.md +15 -0
- package/docs/api/type-aliases/SaveReport.md +15 -0
- package/docs/api/type-aliases/Span.md +63 -0
- package/docs/api/type-aliases/SplitOn.md +15 -0
- package/docs/api/type-aliases/Standard14.md +15 -0
- package/docs/api/type-aliases/StructRef.md +41 -0
- package/docs/api/type-aliases/StructSource.md +17 -0
- package/docs/api/type-aliases/TableDetector.md +15 -0
- package/docs/api/type-aliases/TableMode.md +15 -0
- package/docs/api/type-aliases/TableScope.md +15 -0
- package/docs/api/type-aliases/Tag.md +15 -0
- package/docs/api/type-aliases/TagName.md +15 -0
- package/docs/api/type-aliases/TextLayout.md +15 -0
- package/docs/api/type-aliases/TextRange.md +33 -0
- package/docs/api/type-aliases/TextRunInfo.md +15 -0
- package/docs/api/type-aliases/Transform.md +15 -0
- package/docs/api/type-aliases/UndoOutcome.md +15 -0
- package/docs/api/type-aliases/ViewerPreferences.md +15 -0
- package/docs/api/type-aliases/WarningCode.md +15 -0
- package/docs/api/type-aliases/WasmSource.md +16 -0
- package/docs/api/variables/Matrix.md +99 -0
- package/docs/api/variables/PAGE_SIZES.md +15 -0
- package/docs/api/variables/TAG_NAMES.md +15 -0
- package/docs/errors/README.md +156 -0
- package/docs/errors/aes-padding-invalid.md +34 -0
- package/docs/errors/already-initialized.md +34 -0
- package/docs/errors/binary-output-to-terminal.md +35 -0
- package/docs/errors/builder-finished.md +35 -0
- package/docs/errors/cancelled.md +35 -0
- package/docs/errors/cmap-invalid.md +42 -0
- package/docs/errors/collection-index.md +33 -0
- package/docs/errors/color-components.md +33 -0
- package/docs/errors/content-bad-operands.md +36 -0
- package/docs/errors/content-path-unpainted.md +36 -0
- package/docs/errors/content-resource-missing.md +37 -0
- package/docs/errors/content-syntax.md +36 -0
- package/docs/errors/content-unbalanced-bt.md +36 -0
- package/docs/errors/content-unbalanced-marked.md +36 -0
- package/docs/errors/content-unbalanced-q.md +36 -0
- package/docs/errors/content-unknown-operator.md +37 -0
- package/docs/errors/data-pending.md +34 -0
- package/docs/errors/decompress.md +34 -0
- package/docs/errors/device-color-without-output-intent.md +33 -0
- package/docs/errors/direct-page.md +34 -0
- package/docs/errors/disposed.md +34 -0
- package/docs/errors/document-changed.md +34 -0
- package/docs/errors/embedded-file-forbidden.md +35 -0
- package/docs/errors/embedded-file-without-mime-type.md +36 -0
- package/docs/errors/encoding-full.md +34 -0
- package/docs/errors/encrypted-base.md +33 -0
- package/docs/errors/extract-limit-blocks.md +35 -0
- package/docs/errors/extract-module-not-loaded.md +37 -0
- package/docs/errors/extract-reading-order-ambiguous.md +32 -0
- package/docs/errors/extract-struct-tree-ignored.md +32 -0
- package/docs/errors/extract-table-ambiguous.md +32 -0
- package/docs/errors/extract-table-limit.md +35 -0
- package/docs/errors/extract-untagged-content.md +32 -0
- package/docs/errors/fetch-failed.md +34 -0
- package/docs/errors/flate-truncated.md +34 -0
- package/docs/errors/font-invalid.md +36 -0
- package/docs/errors/font-mismatch.md +34 -0
- package/docs/errors/font-not-embeddable.md +34 -0
- package/docs/errors/font-not-embedded.md +35 -0
- package/docs/errors/font-not-shapable.md +33 -0
- package/docs/errors/glyph-out-of-range.md +34 -0
- package/docs/errors/glyph-without-unicode.md +35 -0
- package/docs/errors/heading-level-skipped.md +36 -0
- package/docs/errors/image-data-length.md +33 -0
- package/docs/errors/image-too-large.md +32 -0
- package/docs/errors/inline-image-unterminated.md +36 -0
- package/docs/errors/input-unreadable.md +37 -0
- package/docs/errors/instance-reset.md +34 -0
- package/docs/errors/invalid-argument.md +33 -0
- package/docs/errors/invalid-axis-value.md +32 -0
- package/docs/errors/invalid-box.md +34 -0
- package/docs/errors/invalid-color.md +32 -0
- package/docs/errors/invalid-command-line.md +44 -0
- package/docs/errors/invalid-date.md +34 -0
- package/docs/errors/invalid-entry.md +34 -0
- package/docs/errors/invalid-feature.md +32 -0
- package/docs/errors/invalid-font.md +32 -0
- package/docs/errors/invalid-geometry.md +32 -0
- package/docs/errors/invalid-icc-profile.md +32 -0
- package/docs/errors/invalid-image.md +33 -0
- package/docs/errors/invalid-op-log.md +33 -0
- package/docs/errors/invalid-page-label.md +34 -0
- package/docs/errors/invalid-page-labels.md +32 -0
- package/docs/errors/invalid-page-range.md +37 -0
- package/docs/errors/invalid-rotate.md +34 -0
- package/docs/errors/invalid-structure-nesting.md +38 -0
- package/docs/errors/invalid-structure.md +34 -0
- package/docs/errors/invalid-text-range.md +33 -0
- package/docs/errors/job-finished.md +34 -0
- package/docs/errors/limit-exceeded.md +38 -0
- package/docs/errors/link-without-contents.md +33 -0
- package/docs/errors/link-without-structure.md +37 -0
- package/docs/errors/missing-alt-text.md +33 -0
- package/docs/errors/missing-glyph.md +33 -0
- package/docs/errors/missing-header.md +37 -0
- package/docs/errors/missing-lang.md +32 -0
- package/docs/errors/missing-root.md +34 -0
- package/docs/errors/missing-title.md +32 -0
- package/docs/errors/name-tree-node-skipped.md +34 -0
- package/docs/errors/nested-transaction.md +34 -0
- package/docs/errors/no-pending-save.md +32 -0
- package/docs/errors/no-transaction.md +33 -0
- package/docs/errors/not-initialized.md +35 -0
- package/docs/errors/not-pdf.md +33 -0
- package/docs/errors/not-rebased.md +35 -0
- package/docs/errors/object-number-out-of-range.md +38 -0
- package/docs/errors/objstm-index-mismatch.md +36 -0
- package/docs/errors/out-of-memory.md +38 -0
- package/docs/errors/outline-cycle.md +34 -0
- package/docs/errors/outline-item-skipped.md +34 -0
- package/docs/errors/output-unwritable.md +37 -0
- package/docs/errors/overwrite-refused.md +36 -0
- package/docs/errors/page-count-mismatch.md +34 -0
- package/docs/errors/page-index-out-of-range.md +34 -0
- package/docs/errors/page-tree-node-skipped.md +35 -0
- package/docs/errors/password-required.md +36 -0
- package/docs/errors/path-outside-roots.md +32 -0
- package/docs/errors/perms-mismatch.md +34 -0
- package/docs/errors/profile-version-conflict.md +35 -0
- package/docs/errors/reference-cycle.md +35 -0
- package/docs/errors/render-backend-unavailable.md +32 -0
- package/docs/errors/render-failed.md +33 -0
- package/docs/errors/render-too-large.md +36 -0
- package/docs/errors/repaired-base.md +34 -0
- package/docs/errors/requires-rewrite.md +38 -0
- package/docs/errors/saved-not-rebased.md +34 -0
- package/docs/errors/sink-not-empty.md +33 -0
- package/docs/errors/sink.md +31 -0
- package/docs/errors/source-budget-exceeded.md +34 -0
- package/docs/errors/source-changed.md +33 -0
- package/docs/errors/source.md +30 -0
- package/docs/errors/stale-generation.md +34 -0
- package/docs/errors/stream-length-recovered.md +37 -0
- package/docs/errors/strict.md +34 -0
- package/docs/errors/subset-failed.md +31 -0
- package/docs/errors/syntax.md +34 -0
- package/docs/errors/text-module-not-loaded.md +36 -0
- package/docs/errors/text-overflow.md +34 -0
- package/docs/errors/tounicode-conflict.md +32 -0
- package/docs/errors/type.md +34 -0
- package/docs/errors/unexpected-eof.md +34 -0
- package/docs/errors/unknown-axis.md +33 -0
- package/docs/errors/unknown-code.md +36 -0
- package/docs/errors/unknown-destination.md +33 -0
- package/docs/errors/unknown-font.md +33 -0
- package/docs/errors/unknown-option.md +33 -0
- package/docs/errors/unknown-page.md +34 -0
- package/docs/errors/unmapped-glyph.md +36 -0
- package/docs/errors/unnumbered-heading-misused.md +34 -0
- package/docs/errors/unset-object.md +30 -0
- package/docs/errors/unsupported-filter.md +34 -0
- package/docs/errors/unsupported-image.md +33 -0
- package/docs/errors/unsupported-layout-option.md +33 -0
- package/docs/errors/unsupported-security-handler.md +34 -0
- package/docs/errors/unsupported-version.md +32 -0
- package/docs/errors/untagged-content.md +35 -0
- package/docs/errors/warnings-truncated.md +35 -0
- package/docs/errors/wasm-trap.md +37 -0
- package/docs/errors/whole-font-rebuilt.md +30 -0
- package/docs/errors/worker-crashed.md +33 -0
- package/docs/errors/worker-failed.md +32 -0
- package/docs/errors/worker-version-mismatch.md +34 -0
- package/docs/errors/would-invalidate-signatures.md +38 -0
- package/docs/errors/wrong-document.md +33 -0
- package/docs/errors/wrong-password.md +34 -0
- package/docs/errors/xobject-cycle.md +36 -0
- package/docs/errors/xref-repaired.md +36 -0
- package/docs/errors/xrefstm-ignored.md +34 -0
- package/docs/llms.txt +88 -0
- package/docs/pages/concepts/dependencies.md +44 -0
- package/docs/pages/concepts/errors-and-warnings.md +64 -0
- package/docs/pages/concepts/how-lamina-thinks.md +86 -0
- package/docs/pages/concepts/pages-and-coordinates.md +67 -0
- package/docs/pages/guides/accessible-pdfs.md +260 -0
- package/docs/pages/guides/archival-pdfs.md +429 -0
- package/docs/pages/guides/edit-a-pdf.md +137 -0
- package/docs/pages/guides/fonts-and-text.md +202 -0
- package/docs/pages/guides/images-and-vectors.md +219 -0
- package/docs/pages/guides/keep-the-page-responsive.md +81 -0
- package/docs/pages/guides/links-outlines-and-metadata.md +222 -0
- package/docs/pages/guides/password-protected-files.md +70 -0
- package/docs/pages/guides/save-a-pdf.md +144 -0
- package/docs/pages/guides/untrusted-files.md +80 -0
- package/docs/pages/index.md +33 -0
- package/docs/pages/install.md +75 -0
- package/docs/pages/quick-start/browser.md +67 -0
- package/docs/pages/quick-start/bun.md +60 -0
- package/docs/pages/quick-start/deno.md +58 -0
- package/docs/pages/quick-start/node.md +61 -0
- package/docs/pages/quick-start/rust.md +58 -0
- package/docs/pages/quick-start/workers.md +139 -0
- package/docs/pages/recipes/cloudflare-worker.md +115 -0
- package/docs/pages/recipes/extract-markdown.md +114 -0
- package/docs/pages/recipes/generate-then-edit.md +135 -0
- package/docs/pages/recipes/hello.md +94 -0
- package/docs/pages/recipes/images-and-vectors.md +209 -0
- package/docs/pages/recipes/invoice.md +226 -0
- package/docs/pages/recipes/links-and-outlines.md +215 -0
- package/docs/pages/recipes/multilingual.md +189 -0
- package/docs/pages/recipes/open-untrusted.md +65 -0
- package/docs/pages/recipes/pdf-a-archive.md +205 -0
- package/docs/pages/recipes/pdf-a3-invoice-with-xml.md +222 -0
- package/docs/pages/recipes/pdf-ua-report.md +237 -0
- package/docs/pages/recipes/report.md +125 -0
- package/docs/pages/recipes/web-worker-client.md +64 -0
- package/docs/pages/recipes.md +47 -0
- package/docs/pages/reference/changelog.md +86 -0
- package/docs/pages/reference/codes.md +14 -0
- package/docs/pages/reference/glossary.md +108 -0
- package/docs/pages/reference/rust.md +36 -0
- package/docs/pages/reference/stability.md +59 -0
- package/docs/pages/start/coding-agents.md +45 -0
- package/docs/pages/start/first-pdf.md +77 -0
- package/docs/pages/troubleshooting.md +74 -0
- package/docs/renames.json +86 -0
- package/docs/schemas/error.schema.json +305 -0
- package/docs/schemas/renames.schema.json +29 -0
- package/package.json +5 -3
- package/schemas/error.schema.json +19 -2
|
@@ -37,6 +37,12 @@ export const PAGES = {
|
|
|
37
37
|
"font-invalid": "# `font-invalid`\n\n- Type: warning\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nA font dictionary read for text extraction has a missing, unreadable or malformed entry (the descendant font, `/Encoding` or its `/Differences`, `/Widths`, `/W`, `/W2`, the font descriptor or its font program). Its text was decoded with defaults: the standard encoding, the standard 14 font's widths or `/MissingWidth`, `/DW`.\n\n## Why\n\nA producer bug, a damaged file, or a font dictionary that relies on what a viewer guesses.\n\n## How to fix\n\nNothing to do. Text or positions extracted for that font may be off; regenerating the file with a current producer fixes it.\n\n## Example\n\n```text\n<< /Type /Font /Subtype /Type0 /BaseFont /Foo /Encoding /Identity-H /DescendantFonts 99 0 R >>\n```\n\nThe descendant font is missing, so text in this font is decoded with defaults: two-byte codes, default widths. The `location` is the font dictionary's `object`.\n\n## Data fields\n\nNone.\n\nThe `location` is `object`, the font dictionary's object; none for a direct font dictionary.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [B9b](../todos/done/B9b-text-extraction-core.md): text extraction\n",
|
|
38
38
|
"cmap-invalid": "# `cmap-invalid`\n\n- Type: warning\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nA font's CMap (its Type 0 `/Encoding`) or ToUnicode CMap couldn't be fully used, for one of three reasons:\n\n- entries that can't be read, which are skipped;\n- a predefined CMap Lamina PDF has no table for, read as Identity (Lamina PDF knows only `Identity-H`/`-V` and the `Uni…-UCS2-…`/`Uni…-UTF16-…` ones);\n- a `/UseCMap` chain deeper than 8 levels, cut there.\n\n## Why\n\nA producer bug (bad ranges, a missing `end…` keyword), or a CJK file using one of Adobe's character-collection CMaps without embedding it.\n\n## How to fix\n\nNothing to do. The rest of the CMap is used; affected glyphs may extract as other text or U+FFFD.\n\n## Example\n\n```text\n1 beginbfchar\n<0003> <0020\nendbfchar\n```\n\nThe destination string is not closed; the entry is skipped, and the rest of the ToUnicode CMap is used.\n\n## Data fields\n\nNone.\n\nThe `location` is `object`, the font dictionary's object; none for a direct font dictionary.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [B9b](../todos/done/B9b-text-extraction-core.md): text extraction\n",
|
|
39
39
|
"unmapped-glyph": "# `unmapped-glyph`\n\n- Type: warning\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nA font showed glyphs that its ToUnicode CMap, its encoding's glyph names and its font program's `cmap` all leave unmapped. They extract as U+FFFD; `PageText::unmapped` counts them.\n\n## Why\n\nThe file has no ToUnicode CMap for a subset or symbolic font, uses arbitrary glyph names (`g37`), or obfuscates its encoding (ISO 32000-2 §9.10.2: there is then no way to know what the glyph means).\n\n## How to fix\n\nNothing to do in Lamina PDF. A producer that writes ToUnicode CMaps (Lamina PDF does) avoids it; OCR is the only way to recover such text.\n\n## Example\n\n```text\n<< /Subtype /Type0 /BaseFont /ABCDEF+Subset /Encoding /Identity-H >> % no /ToUnicode\n```\n\nA subset font with Identity-H and no ToUnicode: unless its embedded `cmap` maps the glyphs, they extract as U+FFFD and the warning carries the font's `object`.\n\n## Data fields\n\nNone.\n\nThe `location` is `object`, the font dictionary's object; none for a direct font dictionary.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [B9b](../todos/done/B9b-text-extraction-core.md): text extraction\n",
|
|
40
|
+
"extract-limit-blocks": "# `extract-limit-blocks`\n\n- Type: warning\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nA page had more runs of text than `ExtractLimits::max_blocks_per_page` allows. Since each run can be a block of its own, extraction kept the first runs the page draws and left out the rest. It cuts them before grouping runs into blocks, so the work stays bounded.\n\n## Why\n\nA page of many tiny separate pieces of text, such as a dense table, a map with hundreds of labels, or a file built to slow extraction down.\n\n## How to fix\n\nRaise `max_blocks_per_page` if the page really holds that many blocks.\n\n## Example\n\n```rust\nlet mut options = laminapdf_extract::ExtractOptions::default();\noptions.limits.max_blocks_per_page = 50_000;\n```\n\n## Data fields\n\n- `limit`: the limit that was reached.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L3a](../todos/done/L3a-lamina-extract-reading-order.md): blocks and reading order\n",
|
|
41
|
+
"extract-reading-order-ambiguous": "# `extract-reading-order-ambiguous`\n\n- Type: warning\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nA page mixes horizontal and vertical writing. Extraction put its blocks in an order, but no layout rule tells which comes first, so the order is a guess.\n\n## Why\n\nJapanese and Chinese pages often set the body vertically and captions, headings or page numbers horizontally. Without a structure tree, nothing in the file says how the two relate.\n\n## How to fix\n\nNothing to do in Lamina PDF; the file is valid. Like every warning, it fails the call in strict mode. Check the order of that page's blocks, or ask for the order the content stream draws (`ReadingOrder::ContentStream`). A tagged file avoids the guess.\n\n## Example\n\nA page whose body text is drawn with a vertical font (`Identity-V`) and whose page number is drawn with a horizontal one.\n\n## Data fields\n\nNone.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L3a](../todos/done/L3a-lamina-extract-reading-order.md): blocks and reading order\n",
|
|
42
|
+
"extract-table-ambiguous": "# `extract-table-ambiguous`\n\n- Type: warning\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nExtraction found a table drawn with lines, but the cells its missing lines would join don't make a rectangle. Extraction kept the table and gave it one cell per square of its grid, so a merged cell's text sits in the first of the squares it covers.\n\n## Why\n\nA table's lines tell where cells are merged: a missing line between two squares joins them. Joined squares that form an L or a T shape don't describe a cell, usually because a line is drawn slightly short, drawn twice in different places, or covered by a white rectangle.\n\n## How to fix\n\nNothing to do in Lamina PDF; the file is valid. Like every warning, it fails the call in strict mode. Check that table's cells: the text of a merged cell may be split across its neighbours.\n\n## Example\n\nA table whose header spans two columns over the first row only, but whose line under that header stops halfway.\n\n## Data fields\n\nNone.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L3b](../todos/done/L3b-extract-tables-and-serialisers.md): tables and extraction output\n",
|
|
43
|
+
"extract-table-limit": "# `extract-table-limit`\n\n- Type: warning\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nA page's ruling lines would have made a table with more cells than `ExtractLimits::max_table_cells` allows, or the page drew so many lines that matching them all would cost too much. Extraction made no table from those lines; their text is still in the page's paragraphs.\n\n## Why\n\nA page drawn with thousands of lines, such as a large grid, a chart's gridlines or a file built to slow extraction down. To find a table, extraction compares every horizontal line with every vertical one, so the work grows with the square of the line count.\n\n## How to fix\n\nRaise `max_table_cells` if the page really holds a table that big.\n\n## Example\n\n```rust\nlet mut options = laminapdf_extract::ExtractOptions::default();\noptions.limits.max_table_cells = 50_000;\n```\n\n## Data fields\n\n- `limit`: the limit that was reached.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L3b](../todos/done/L3b-extract-tables-and-serialisers.md): tables and extraction output\n",
|
|
44
|
+
"extract-struct-tree-ignored": "# `extract-struct-tree-ignored`\n\n- Type: warning\n- Kind: `input` (a problem with the PDF file)\n\n## What happened\n\nThe page is tagged, but its structure tree didn't pass the checks that decide whether to trust it, so extraction read the page in layout order instead.\n\n## Why\n\nA structure tree gives a page's reading order, but trees are often incomplete or wrong. Extraction uses a page's tree only when its elements cover at least 80% of the page's visible text, not counting headers, page numbers and other text the file marks as page furniture. Its order must also jump back up into an earlier column at most once in ten moves from block to block. A tree written by a tool that tags only some of the text, or that tags it in drawing order, fails one of the checks.\n\n## How to fix\n\nNothing to do: the page reads in layout order, as an untagged page would. To use the tree anyway, extract with `ReadingOrder::Tagged` (`readingOrder: \"tagged\"`). Like every warning, it fails the call in strict mode.\n\n## Example\n\nA report whose tool tagged only its headings: the tree covers a tenth of the text, so the reason is `coverage`.\n\n## Data fields\n\n- `reason`: `coverage` or `order`, the check that failed.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0030](../decisions/0030-extraction-output-and-model-plugins.md): the extraction output and the reading-order sources\n",
|
|
45
|
+
"extract-untagged-content": "# `extract-untagged-content`\n\n- Type: warning\n- Kind: `input` (a problem with the PDF file)\n\n## What happened\n\nThe page was read in its structure tree's order, but some of its visible text isn't in the tree and isn't marked as an artifact. Extraction kept that text and put it after the tree's blocks, in layout order.\n\n## Why\n\nIn a tagged file, every piece of visible content should belong to a structure element or be marked as an artifact (ISO 32000-2 §14.8.2.2). Text that is neither has no place in the tree's order. A tool that adds text after tagging a document, such as a stamp or a page number, often leaves text like this.\n\n## How to fix\n\nNothing to do in Lamina PDF. To give that text its place in the reading order, tag it in the file, or mark it as an artifact if it isn't content. Like every warning, it fails the call in strict mode.\n\n## Example\n\nA tagged contract with a \"DRAFT\" stamp drawn after tagging: the stamp's text comes after the contract's blocks.\n\n## Data fields\n\n- `chars`: how many characters (spaces left out) lie outside the tree.\n\nThe `location` has the page's `pageIndex`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0030](../decisions/0030-extraction-output-and-model-plugins.md): the extraction output and the reading-order sources\n",
|
|
40
46
|
"not-pdf": "# `not-pdf`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nThe input does not look like a PDF at all.\n\n## Why\n\nThe bytes are empty, or no `n g obj` header appears anywhere in them: an HTML error page saved as `.pdf`, a different format, or the wrong buffer.\n\n## How to fix\n\nCheck that you passed the right bytes.\n\n## Example\n\n```rust\nlet err = laminapdf::Document::open_bytes(b\"<html>…</html>\".to_vec(), Default::default()).unwrap_err();\nassert_eq!(err.code(), \"not-pdf\");\n```\n\n## Data fields\n\nNone.\n",
|
|
41
47
|
"missing-root": "# `missing-root`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nNo document catalog (`/Root`) was found, even after repair.\n\n## Why\n\nThe file is damaged beyond repair.\n\n## How to fix\n\nUse another copy of the file.\n\n## Example\n\n```text\ntrailer << /Size 3 >> % no /Root, and no object with /Type /Catalog in the file\n```\n\nRepair found no catalog to use, so `open` fails.\n\n## Data fields\n\nNone.\n",
|
|
42
48
|
"reference-cycle": "# `reference-cycle`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nA reference chain or the page tree loops back on itself.\n\n## Why\n\nDamaged or hostile files.\n\n## How to fix\n\nUse another copy of the file.\n\n## Example\n\n```text\n5 0 obj 6 0 R endobj\n6 0 obj 5 0 R endobj\n```\n\nResolving object 5 leads back to itself; the call fails instead of looping. A page tree whose `/Kids` lead back to an ancestor fails the same way.\n\n## Data fields\n\nNone.\n",
|
|
@@ -71,30 +77,30 @@ export const PAGES = {
|
|
|
71
77
|
"requires-rewrite": "# `requires-rewrite`\n\n- Type: error (`laminapdf_save::SaveError::RequiresRewrite`)\n- Kind: `state` (the call isn't valid in the document's current state)\n\n## What happened\n\nAn incremental save was requested, but only a full rewrite is safe for this document. Nothing was written.\n\n## Why\n\nThe save planner found one of four reasons the file must be rewritten:\n\n- a repaired base, whose cross-reference data an appended revision can't build on;\n- an encrypted base being saved without its encryption;\n- a document built from scratch, with no base bytes at all;\n- a pending op, such as a redaction, that removes content an earlier revision would keep.\n\n## How to fix\n\nSave with `SaveMode::Auto` (it resolves to a full rewrite) or `SaveMode::FullRewrite`. If the document is also signed, that needs the explicit override ([`would-invalidate-signatures`](would-invalidate-signatures.md)).\n\n## Example\n\n```rust\nlet err = doc.save(&mut out, &SaveOptions::new().with_mode(SaveMode::Incremental)).unwrap_err();\nassert_eq!(err.code(), \"requires-rewrite\");\n```\n\n## Data fields\n\n- `reasons`: the rewrite reasons (`RepairedBase`, `EncryptedBase`, `NoBase`, `OpRequiresRewrite`).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0007](../decisions/0007-save-planner.md) §2\n",
|
|
72
78
|
"invalid-font": "# `invalid-font`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nFont bytes passed to `Font::from_bytes` or `Font::from_collection` (`laminapdf-text`) could not be read as a font.\n\n## Why\n\nThe bytes are not an OpenType/TrueType font or collection (WOFF/WOFF2 must be decompressed first), or a table every font needs (`head`, `hhea`, `hmtx`, `maxp`) is missing or malformed.\n\n## How to fix\n\nPass the bytes of a `.ttf`, `.otf`, `.ttc` or `.otc` file; check that the file is complete.\n\n## Example\n\n```rust\nlet err = laminapdf::Font::from_bytes(std::fs::read(\"font.woff2\")?).unwrap_err(); // invalid-font\n```\n\n## Data fields\n\n- `index`: the collection member that was asked for (0 for a single font).\n",
|
|
73
79
|
"collection-index": "# `collection-index`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Font::from_collection` was asked for a member past the end of the font collection.\n\n## Why\n\nMembers are numbered from 0; a single font counts as a collection of one.\n\n## How to fix\n\nUse an index below `Font::collection_len(bytes)`.\n\n## Example\n\n```rust\nlet font = Font::from_collection(ttc_bytes, 4)?; // the collection has 4 members (0..=3): collection-index\n```\n\n## Data fields\n\n- `index`: the member that was asked for.\n- `count`: how many members the collection has.\n",
|
|
74
|
-
"unknown-axis": "# `unknown-axis`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Font::instance` was given a variation axis the font does not have.\n\n## Why\n\nA static font has no axes; a variable font has the axes listed in `FontInfo::axes` (`fvar`).\n\n## How to fix\n\nCheck `font.info().axes` before choosing coordinates, or use a variable font.\n\n## Example\n\n```rust\nlet bold = static_font.instance(&[(
|
|
80
|
+
"unknown-axis": "# `unknown-axis`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Font::instance` was given a variation axis the font does not have.\n\n## Why\n\nA static font has no axes; a variable font has the axes listed in `FontInfo::axes` (`fvar`).\n\n## How to fix\n\nCheck `font.info().axes` before choosing coordinates, or use a variable font.\n\n## Example\n\n```rust\nlet bold = static_font.instance(&[(OpenTypeTag::WEIGHT, 700.0)])?; // unknown-axis: no wght axis\n```\n\n## Data fields\n\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n- `tag`: the axis tag that was asked for.\n",
|
|
75
81
|
"font-not-embeddable": "# `font-not-embeddable`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`FontRegistry::add` refused a font whose `OS/2.fsType` forbids embedding (restricted licence, or bitmap embedding only).\n\n## Why\n\nFont vendors mark fonts whose licence does not allow embedding in documents (OpenType `OS/2` table; research 03 §6.3). `fsType` is advisory; the licence is what counts.\n\n## How to fix\n\nUse another font, or, if your licence allows embedding, register it with `EmbedPolicy::Override`.\n\n## Example\n\n```rust\nregistry.add(restricted_font, EmbedPolicy::Respect)?; // font-not-embeddable\nregistry.add(restricted_font, EmbedPolicy::Override)?; // only if your licence allows embedding\n```\n\n## Data fields\n\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n- `fs_type`: the `fsType` bits.\n",
|
|
76
82
|
"missing-glyph": "# `missing-glyph`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\nText contained a character the font has no glyph for. Lamina PDF never draws `.notdef` (an empty box) silently.\n\n## Why\n\nThe font's `cmap` does not map the character (for example a CJK character with a Latin font).\n\n## How to fix\n\nUse a font that covers the character (check with `Font::glyph_for`), or split the text across fonts.\n\n## Example\n\n```rust\nregistry.encode(latin_font, \"東京\")?; // missing-glyph: the font has no CJK glyphs\n```\n\n## Data fields\n\n- `ch`: the character (**untrusted**: caller or document text).\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n",
|
|
77
83
|
"glyph-out-of-range": "# `glyph-out-of-range`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`FontRegistry::use_glyph` was given a glyph ID at or past the font's glyph count.\n\n## Why\n\nGlyph IDs must come from the same font (its `cmap` or a shaper run on it).\n\n## How to fix\n\nPass glyph IDs from the font you registered.\n\n## Example\n\n```rust\nregistry.use_glyph(key, GlyphId::new(60_000), \"x\")?; // the font has 1,200 glyphs\n```\n\n## Data fields\n\n- `gid`: the glyph ID.\n- `count`: the font's glyph count.\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n",
|
|
78
84
|
"unknown-font": "# `unknown-font`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA `FontKey` was used with a `FontRegistry` that did not hand it out.\n\n## Why\n\nKeys are indices into one registry; each document has its own.\n\n## How to fix\n\nUse the key returned by this registry's `add`.\n\n## Example\n\n```rust\nlet key = registry_a.add(font, EmbedPolicy::Respect)?;\nregistry_b.encode(key, \"Hi\")?; // unknown-font: key came from registry_a\n```\n\n## Data fields\n\n- `key`: the key's index.\n",
|
|
79
85
|
"subset-failed": "# `subset-failed`\n\n- Type: error\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nSubsetting a font at `FontRegistry::finish_fonts` failed.\n\n## Why\n\nThe `subsetter` crate could not rebuild the font program: a font feature it does not support, or a table it could not parse.\n\n## How to fix\n\nTry another version or format of the font (for example TrueType instead of CFF), and report the font if it is a common one.\n\n## Example\n\nA font whose tables `subsetter` can't rebuild makes `FontRegistry::finish_fonts` (and so `Builder::finish`) fail with `subset-failed`; `data.font` is the font's PostScript name.\n\n## Data fields\n\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n- `reason`: the subsetter's failure class (fixed text).\n",
|
|
80
|
-
"invalid-axis-value": "# `invalid-axis-value`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Font::instance` was given a NaN or infinite axis value.\n\n## Why\n\nVariation coordinates are user-space numbers such as `wght` 700; NaN and infinities have no position on an axis.\n\n## How to fix\n\nPass finite values; values outside the axis range are clamped, so there is no need for infinities.\n\n## Example\n\n```rust\nfont.instance(&[(
|
|
86
|
+
"invalid-axis-value": "# `invalid-axis-value`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Font::instance` was given a NaN or infinite axis value.\n\n## Why\n\nVariation coordinates are user-space numbers such as `wght` 700; NaN and infinities have no position on an axis.\n\n## How to fix\n\nPass finite values; values outside the axis range are clamped, so there is no need for infinities.\n\n## Example\n\n```rust\nfont.instance(&[(OpenTypeTag::WEIGHT, f32::NAN)])?; // invalid-axis-value\n```\n\n## Data fields\n\n- `tag`: the axis.\n",
|
|
81
87
|
"wrong-document": "# `wrong-document`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`FontRegistry::finish_fonts` was given a document in which a font's reserved object is not a free number reserved in that document.\n\n## Why\n\nA `FontRegistry` belongs to one document: `reference` reserves numbers in the document it is given, and `finish_fonts` fills those numbers. Finishing into another document would overwrite its objects, so nothing is written.\n\n## How to fix\n\nUse one `FontRegistry` per document, and pass `finish_fonts` the document its `reference` calls used.\n\n## Example\n\n```rust\nlet id = registry.reference(key, &doc_a)?;\nregistry.finish_fonts(&mut doc_b.edit())?; // wrong-document: the fonts were reserved in doc_a\n```\n\n## Data fields\n\n- `object`: the reserved object number.\n",
|
|
82
|
-
"invalid-feature": "# `invalid-feature`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nAn OpenType feature setting given to the shaper (`\"liga=0\".parse::<Feature>()`) did not parse.\n\n## Why\n\nFeature settings use HarfBuzz's syntax without ranges: `tag` or `+tag` (on), `-tag` (off), `tag=N`, `tag=on` or `tag=off`, where the tag is one to four printable ASCII characters. A sign together with a value (`+liga=1`), an empty or longer tag, or a value that is not a non-negative integer is refused.\n\n## How to fix\n\nWrite the setting as `liga=0`, `-liga`, `smcp` or `aalt=2`, or build it with `Feature::new(
|
|
88
|
+
"invalid-feature": "# `invalid-feature`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nAn OpenType feature setting given to the shaper (`\"liga=0\".parse::<Feature>()`) did not parse.\n\n## Why\n\nFeature settings use HarfBuzz's syntax without ranges: `tag` or `+tag` (on), `-tag` (off), `tag=N`, `tag=on` or `tag=off`, where the tag is one to four printable ASCII characters. A sign together with a value (`+liga=1`), an empty or longer tag, or a value that is not a non-negative integer is refused.\n\n## How to fix\n\nWrite the setting as `liga=0`, `-liga`, `smcp` or `aalt=2`, or build it with `Feature::new(OpenTypeTag::new(b\"liga\"), 0)`.\n\n## Example\n\n```rust\nlet f: Feature = \"liga[3:5]=0\".parse()?; // invalid-feature: ranges are not supported\n```\n\n## Data fields\n\n- `feature`: the setting as given (**untrusted**: caller text).\n",
|
|
83
89
|
"invalid-text-range": "# `invalid-text-range`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA byte range of a text given to `Shaper::shape_range`, `BidiParagraph::visual_runs` or `BidiParagraph::line_levels`, or the range of a `ShapedRun` given to `pdf_run`, is past the end of the text or does not start and end on character boundaries.\n\n## Why\n\nRanges are byte offsets into UTF-8 text; a range that cuts a character in two (or reaches past the end) names no text.\n\n## How to fix\n\nTake ranges from Lamina PDF's own results (`line_breaks`, `itemize`, `break_lines`, `ShapedRun::text_range`), or check them with `str::get` first, and pass the same text the range was computed on.\n\n## Example\n\n```rust\nshaper.shape_range(&font, \"héllo\", 0..2, &options)?; // byte 2 is inside 'é'\n```\n\n## Data fields\n\n- `start`, `end`: the range (bytes).\n- `len`: the text's length (bytes).\n",
|
|
84
90
|
"unsupported-layout-option": "# `unsupported-layout-option`\n\n- Type: error\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\n`break_lines` was given a layout option Lamina PDF does not implement yet: `LayoutOptions::justify` set to `true`.\n\n## Why\n\nJustification (stretching inter-word gaps, kashida) is reserved for a later plan (research 03 §7.6); silently ignoring the option would lay out ragged lines the caller did not ask for.\n\n## How to fix\n\nLeave `justify` at `false` and pick an `Alignment` (start, end, left, right or centre).\n\n## Example\n\n```rust\nlet options = LayoutOptions { justify: true, ..LayoutOptions::new(300.0, 12.0) };\nbreak_lines(&shaper, &fonts, text, &options)?; // unsupported-layout-option\n```\n\n## Data fields\n\n- `option`: the option's name (fixed text).\n",
|
|
85
91
|
"font-mismatch": "# `font-mismatch`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`pdf_run` was given a shaped run and the key of a font other than the one the run was shaped with. Nothing was recorded in the registry.\n\n## Why\n\nGlyph IDs, advances and units per em only mean something in the font that produced them; drawing them with another font would show the wrong glyphs and wrong text.\n\n## How to fix\n\nRegister every font of a layout and pass the key of the run's own font: each `LineRun::font` is an index into the font list given to `break_lines`.\n\n## Example\n\n```rust\nlet run = shaper.shape(¬o, text, &options)?;\npdf_run(&run, text, &mut registry, roboto_key)?; // font-mismatch: shaped with Noto\n```\n\n## Data fields\n\n- `font`: the registered font's PostScript name (**untrusted**: read from the font).\n- `shaped_with`: the PostScript name of the font the run was shaped with (**untrusted**: read from the font).\n",
|
|
86
|
-
"encoding-full": "# `encoding-full`\n\n- Type: error\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nA standard 14 font had no free one-byte code left for another glyph in this document.\n\n## Why\n\nA standard 14 font is a simple font: text is written one byte per character, so one font resource addresses at most 256 glyphs (ISO 32000-2 §9.6.5). Lamina PDF writes the Latin fonts in `WinAnsiEncoding`, and gives each glyph of the standard Latin character set outside it (`Lslash`, `Scedilla`, `minus`, …) one of the 37 codes `WinAnsiEncoding` leaves undefined, through `/Differences
|
|
87
|
-
"font-not-shapable": "# `font-not-shapable`\n\n- Type: error\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nA standard 14 font (`Font::standard`) was given to the shaper, `itemize`, `break_lines` or `pdf_run`.\n\n## Why\n\nThe standard 14 fonts are referred to by name and never embedded
|
|
92
|
+
"encoding-full": "# `encoding-full`\n\n- Type: error\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nA standard 14 font had no free one-byte code left for another glyph in this document.\n\n## Why\n\nA standard 14 font is a simple font: text is written one byte per character, so one font resource addresses at most 256 glyphs (ISO 32000-2 §9.6.5). Lamina PDF writes the Latin fonts in `WinAnsiEncoding`, and gives each glyph of the standard Latin character set outside it (`Lslash`, `Scedilla`, `minus`, …) one of the 37 codes `WinAnsiEncoding` leaves undefined, through `/Differences`.\n\nA document that draws more such glyphs with one font than there are free codes runs out. Assignment is all or nothing: when one `encode` call needs more new codes than are free, none are assigned and nothing of the text is recorded.\n\n## How to fix\n\nEmbed a font (`Font::from_bytes`), which addresses every glyph through a Type 0 font, or split the text across two registrations of the standard font (each is its own font resource with its own codes).\n\n## Example\n\nDrawing more than 37 different non-WinAnsi Latin glyphs (Ā, ă, Ą, …) with `Standard14::Helvetica` in one document: the 38th has no free code in the font's `/Differences`, so the call fails with `encoding-full`.\n\n## Data fields\n\n- `font`: the standard font's PostScript name (fixed text: one of the fourteen).\n- `limit`: how many codes `/Differences` can assign for this font.\n- `free`: how many of them were still free; the text needed more, so none were assigned.\n",
|
|
93
|
+
"font-not-shapable": "# `font-not-shapable`\n\n- Type: error\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nA standard 14 font (`Font::standard`) was given to the shaper, `itemize`, `break_lines` or `pdf_run`.\n\n## Why\n\nThe standard 14 fonts are referred to by name and never embedded. Lamina PDF has their metrics (Adobe's AFM files) but no font program, so there is nothing for HarfRust to shape with and no `cmap` for itemizing. Nor are there CIDs for a shaped run: a standard 14 font is written as a simple font with one-byte codes.\n\n## How to fix\n\nDraw standard 14 text with `FontRegistry::encode` (one glyph per character, kerning not applied), or load a real font with `Font::from_bytes` and shape with it.\n\n## Example\n\n```rust\nlet helvetica = Font::standard(Standard14::Helvetica);\nshaper.shape(&helvetica, \"Hello\", &options)?; // font-not-shapable\n```\n\n## Data fields\n\n- `font`: the standard font's PostScript name (fixed text: one of the fourteen).\n",
|
|
88
94
|
"tounicode-conflict": "# `tounicode-conflict`\n\n- Type: warning\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nOne glyph was used for two different texts; the ToUnicode CMap maps it to the first.\n\n## Why\n\nA ToUnicode CMap maps each code to one string (ISO 32000-2 §9.10.3), for example when one space glyph stands for both U+0020 and U+00A0.\n\n## How to fix\n\nMark the second occurrence with `/ActualText` (§14.9.4) so extraction gets its text; Lamina PDF's builder does this for you.\n\n## Example\n\nA CFF font in which one space glyph is used for both U+0020 and U+00A0: the ToUnicode CMap maps it to U+0020 (the first use), and the warning names the glyph (`gid`) and the second text.\n\n## Data fields\n\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n- `gid`: the glyph, in the original font's numbering.\n- `kept`, `dropped`: the two texts (**untrusted**: caller text).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [B5b](../todos/done/B5b-builder-text-and-document-features.md): the builder marks repeated glyphs\n",
|
|
89
|
-
"whole-font-rebuilt": "# `whole-font-rebuilt`\n\n- Type: warning\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA font whose `OS/2.fsType` forbids subsetting was embedded with every glyph, but rebuilt rather than byte for byte.\n\n## Why\n\nIt is a variable-font instance or has CFF2 outlines; PDF can embed neither as it is, so `subsetter` instanced it (or converted CFF2 to TrueType outlines) while keeping every glyph. Its `cmap` and layout tables are dropped.\n\n## How to fix\n\nCheck the font's licence allows this, or use a static TrueType/CFF version of the font.\n\n## Example\n\nRegistering a variable font instance (`font.instance(&[(
|
|
95
|
+
"whole-font-rebuilt": "# `whole-font-rebuilt`\n\n- Type: warning\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA font whose `OS/2.fsType` forbids subsetting was embedded with every glyph, but rebuilt rather than byte for byte.\n\n## Why\n\nIt is a variable-font instance or has CFF2 outlines; PDF can embed neither as it is, so `subsetter` instanced it (or converted CFF2 to TrueType outlines) while keeping every glyph. Its `cmap` and layout tables are dropped.\n\n## How to fix\n\nCheck the font's licence allows this, or use a static TrueType/CFF version of the font.\n\n## Example\n\nRegistering a variable font instance (`font.instance(&[(OpenTypeTag::WEIGHT, 700.0)])`) whose `fsType` forbids subsetting: the font is embedded with every glyph, but instanced, so not byte for byte.\n\n## Data fields\n\n- `font`: the font's PostScript name (**untrusted**: read from the font).\n",
|
|
90
96
|
"invalid-image": "# `invalid-image`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\n`Image::jpeg`, `Image::png` or `Image::png_with` (`laminapdf-build`) could not read the bytes as an image of that format.\n\n## Why\n\nA JPEG must start with a start-of-image marker and have a frame header (SOF) before its first scan, with every marker segment inside the data; a PNG must decode without errors (signature, chunk CRCs, zlib data, sizes).\n\n## How to fix\n\nPass the complete file. Check that the bytes are the format you called (a PNG passed to `Image::jpeg` fails here).\n\n## Example\n\n```rust\nlet img = Image::jpeg(std::fs::read(\"photo.png\")?)?; // invalid-image: PNG bytes given as JPEG\n```\n\n## Data fields\n\n- `format`: `Jpeg`, `Png` or `Rgba`.\n- `reason`: what was wrong (fixed text).\n",
|
|
91
97
|
"unsupported-image": "# `unsupported-image`\n\n- Type: error\n- Kind: `unsupported` (valid input that Lamina PDF doesn't implement)\n\n## What happened\n\nThe image is valid but uses a feature the builder can't embed.\n\n## Why\n\nPDF's `DCTDecode` filter (ISO 32000-2 §7.4.8) takes baseline and progressive JPEG with 8-bit samples; lossless, hierarchical and arithmetic-coded JPEG and 12-bit samples are refused, as are JPEGs with 2 or more than 4 components.\n\n## How to fix\n\nRe-encode the image as a baseline or progressive 8-bit JPEG, or as PNG.\n\n## Example\n\n```rust\nlet img = Image::jpeg(lossless_jpeg_bytes)?; // unsupported-image: data.feature says which\n```\n\n## Data fields\n\n- `format`: the image's format.\n- `feature`: the feature that is not supported (fixed text).\n",
|
|
92
98
|
"image-too-large": "# `image-too-large`\n\n- Type: error\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nDecoding a PNG would need more than `MAX_DECODED_IMAGE_BYTES` (256 MiB), or the dimensions given to `Image::rgba` describe more bytes than fit in memory's address space.\n\n## Why\n\nThe builder decodes PNGs to split colour and alpha; a bound on the decoded size keeps a small file with huge dimensions from exhausting memory.\n\n## How to fix\n\nScale the image down before adding it, or use a JPEG, which is embedded without decoding.\n\n## Example\n\n```rust\nlet img = Image::png(&png_of_30000_by_30000_pixels)?; // image-too-large: over 256 MiB decoded\n```\n\n## Data fields\n\n- `limit`: the limit in decoded bytes.\n",
|
|
93
99
|
"image-data-length": "# `image-data-length`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Image::rgba(width, height, bytes)` was given a number of bytes other than `width × height × 4`.\n\n## Why\n\nRaw RGBA samples are 4 bytes per pixel, row by row from the top, with no padding.\n\n## How to fix\n\nPass exactly 4 bytes per pixel.\n\n## Example\n\n```rust\nlet img = Image::rgba(2, 2, &[0; 12])?; // image-data-length: 16 bytes expected\n```\n\n## Data fields\n\n- `expected`: the length the dimensions call for.\n- `actual`: the length given.\n",
|
|
94
|
-
"invalid-icc-profile": "# `invalid-icc-profile`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\n`IccProfile::new` (`laminapdf-build`) rejected the bytes.\n\n## Why\n\nAn ICC profile (ICC.1:2010) starts with a 128-byte header holding its size, the `acsp` signature, its class and its data colour space. PDF's `ICCBased` colour spaces (ISO 32000-2 §8.6.5.5) take Gray, RGB, CMYK and Lab profiles
|
|
100
|
+
"invalid-icc-profile": "# `invalid-icc-profile`\n\n- Type: error\n- Kind: `input` (the input is malformed beyond what tolerance repairs)\n\n## What happened\n\n`IccProfile::new` (`laminapdf-build`) rejected the bytes.\n\n## Why\n\nAn ICC profile (ICC.1:2010) starts with a 128-byte header holding its size, the `acsp` signature, its class and its data colour space. PDF's `ICCBased` colour spaces (ISO 32000-2 §8.6.5.5) take Gray, RGB, CMYK and Lab profiles. The builder takes Gray, RGB and CMYK: Lab components fall outside `[0, 1]` and need a `/Range`, which it doesn't support yet. Device-link, abstract and named-colour profiles can't be used.\n\n## How to fix\n\nPass the complete bytes of an input, display, output or colour-space profile with a Gray, RGB or CMYK data colour space.\n\n## Example\n\n```rust\nlet profile = IccProfile::new(b\"not a profile\".to_vec())?; // invalid-icc-profile\n```\n\n## Data fields\n\n- `reason`: what was wrong (fixed text).\n",
|
|
95
101
|
"color-components": "# `color-components`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Color::icc` was given a number of components that differs from the profile's channel count.\n\n## Why\n\nAn `ICCBased` colour has one component per channel of its profile (`/N`: Gray 1, RGB and Lab 3, CMYK 4).\n\n## How to fix\n\nGive `IccProfile::components()` values.\n\n## Example\n\n```rust\nlet c = Color::icc(&cmyk_profile, &[0.1, 0.2, 0.3])?; // color-components: 4 expected\n```\n\n## Data fields\n\n- `expected`: the colour space's number of components.\n- `actual`: how many were given.\n",
|
|
96
102
|
"invalid-color": "# `invalid-color`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Color::hex` was given a string that is not `#rgb` or `#rrggbb`.\n\n## Why\n\nHex colours are a `#` followed by three or six hexadecimal digits, in either case.\n\n## How to fix\n\nWrite the colour as `#3366cc` or `#36c`, or use `Color::rgb`.\n\n## Example\n\n```rust\nlet c = Color::hex(\"#12345\")?; // invalid-color: 5 digits\n```\n\n## Data fields\n\n- `text`: the string as given (untrusted: caller text, never in the message).\n",
|
|
97
|
-
"invalid-geometry": "# `invalid-geometry`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA page size, page box, `/UserUnit`, drawing value or image size given to the builder is not usable. Drawing values are checked as the `Surface` receives them and the first bad one is reported by `PageBuilder::finish`.\n\n## Why\n\nPage sizes and `/UserUnit` must be finite and positive, page boxes, path coordinates, matrices and image rectangles finite
|
|
103
|
+
"invalid-geometry": "# `invalid-geometry`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA page size, page box, `/UserUnit`, drawing value or image size given to the builder is not usable. Drawing values are checked as the `Surface` receives them and the first bad one is reported by `PageBuilder::finish`.\n\n## Why\n\nPage sizes and `/UserUnit` must be finite and positive, and page boxes, path coordinates, matrices and image rectangles finite. Line widths and dash lengths must be finite and not negative, and a dash pattern not all zeros (ISO 32000-2 §8.4.3.6). Miter limits must be at least 1, images at least one pixel wide and tall, font sizes and line heights positive, text boxes wider than 0, and destination coordinates finite.\n\n## How to fix\n\nCheck the values passed to `Builder::page`, `PageBuilder::user_unit`, the box setters, the `Surface` (paths, `transform`, `StrokeStyle`, `image`, `text` and `text_box` sizes, positions, boxes and line heights, `link` rectangles), destinations (`Fit` coordinates) and `Image::rgba`.\n\n## Example\n\n```rust\nlet page = builder.page(PageSize::new(Pt::new(0.0), Pt::new(842.0))); // invalid-geometry at finish\n```\n\n## Data fields\n\n- `what`: which value was invalid (fixed text).\n",
|
|
98
104
|
"text-overflow": "# `text-overflow`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`Surface::text_box` laid its text out and not every line fit the box (its height, or a single grapheme cluster wider than the box), and its `TextBoxOptions` asked for `Overflow::Error`. Nothing was drawn.\n\n## Why\n\nA text box draws only lines that fit inside it. With `Overflow::Error` the caller asked to be told instead of having the text cut off.\n\n## How to fix\n\nMake the box taller or wider, the font smaller or the text shorter; or use `Overflow::Clip` (the default), which draws the lines that fit and reports where the rest starts in `TextLayout::overflow`.\n\n## Example\n\n```rust\nlet options = TextBoxOptions::default().with_overflow(Overflow::Error);\nsurface.text_box(long_text, &font, Pt::new(12.0), small_rect, &options)?; // text-overflow\n```\n\n## Data fields\n\n- `fits`: the number of lines that fit.\n- `needed`: the number of lines the text needs.\n",
|
|
99
105
|
"page-index-out-of-range": "# `page-index-out-of-range`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA link (`LinkTarget::Page`), an outline item or a named destination (`Builder::destination`) names a page index the document doesn't have when the build finishes.\n\n## Why\n\nPage targets are resolved when `Builder::finish` (or `Appender::finish`) runs, so a link can name a page added after its own; by then every index must be one of the document's pages. Indexes are 0-based.\n\n## How to fix\n\nUse an index below the document's page count, or add the page before finishing.\n\n## Example\n\n```rust\nsurface.link(rect, LinkTarget::Page { index: 5, fit: Fit::Page }, None);\nbuilder.finish()?; // page-index-out-of-range: the document has 2 pages\n```\n\n## Data fields\n\n- `index`: the 0-based index given.\n- `count`: the number of pages.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0027](../decisions/0027-coordinates-units-and-page-indexing.md) §6\n",
|
|
100
106
|
"unknown-destination": "# `unknown-destination`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA link or outline item of a new document targets `LinkTarget::Named(name)`, but `Builder::destination` never defined that name.\n\n## Why\n\nA named destination is looked up in the document's `/Names /Dests` tree (ISO 32000-2 §12.3.2.4); a name that isn't there goes nowhere in every viewer.\n\n## How to fix\n\nDefine the name with `Builder::destination(name, page_index, fit)` before `Builder::finish`, or link to the page directly with `LinkTarget::Page`.\n\n## Example\n\n```rust\nsurface.link(rect, LinkTarget::Named(\"appendix\".into()), None);\nbuilder.finish()?; // unknown-destination: call builder.destination(\"appendix\", …) first\n```\n\n## Data fields\n\n- `name`: the name as given (untrusted: caller text, never in the message).\n",
|
|
@@ -121,18 +127,29 @@ export const PAGES = {
|
|
|
121
127
|
"job-finished": "# `job-finished`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\n`step` was called on a job that had already returned its result, failed or been cancelled.\n\n## Why\n\nA job ends with its first `Step::Done`, or with its first error: an error ends the job. A step loop that keeps going after either reaches this.\n\n## How to fix\n\nStop stepping once a step returns `Done` or an error. To run the work again, create a new job.\n\n## Example\n\n```rust\nlet mut job = doc.save_job(&laminapdf::SaveOptions::new());\nwhile let laminapdf::Step::Progress { .. } = job.step(&mut doc, laminapdf::Budget::UNLIMITED)? {}\nassert_eq!(job.step(&mut doc, laminapdf::Budget::UNLIMITED).unwrap_err().code(), \"job-finished\");\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0028](../decisions/0028-facade-rules-jobs-and-cancellation.md) §3\n",
|
|
122
128
|
"document-changed": "# `document-changed`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA job's `step` was given a document other than the one the job was created from, or that document changed since: a committed transaction, an undo, a redo, a save or a rebase. Every step checks the document's instance and revision before any work, and the job is now finished.\n\n## Why\n\nJobs don't borrow the document, so other calls can run between two steps. A save or a read that went on after an edit would mix two states of the document, so the job stops instead.\n\n## How to fix\n\nPass the document the job was created from, don't change it while the job runs, and create a new job after a change. A failed save left the document as it was.\n\n## Example\n\n```rust\nlet mut job = doc.save_job(&laminapdf::SaveOptions::new());\ndoc.apply(vec![laminapdf::Op::from(set_info)])?; // the revision moves on\nassert_eq!(job.step(&mut doc, laminapdf::Budget::UNLIMITED).unwrap_err().code(), \"document-changed\");\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0028](../decisions/0028-facade-rules-jobs-and-cancellation.md) §3\n",
|
|
123
129
|
"builder-finished": "# `builder-finished`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA `WasmBuilder` method was called after the builder's `finish`, or a `WasmPageBuilder` was drawn on or finished again after its own `finish` (or after its builder's).\n\n## Why\n\n`finish` hands the work over: a builder's becomes a `WasmDocument`, a page's is written into its builder. Neither holds anything to draw on afterwards.\n\n## How to fix\n\nDraw everything on a page before finishing it, and finish every page before the builder. To build more, create a new page or builder.\n\n## Example\n\n```js\nconst b = new WasmBuilder(undefined);\nconst page = b.page(595, 842);\npage.finish();\npage.save(); // throws { code: \"builder-finished\", … }\n```\n\n## Data fields\n\n- `argument`: always `builder`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §7: the binding owns its pages\n",
|
|
130
|
+
"disposed": "# `disposed`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA `Document`, `Builder` or other handle of `@laminapdf/sdk` was used after `free()` released it, or after the `using` block that held it ended (`Symbol.dispose`). A page or save job is freed with its document, and a builder's page with its builder.\n\n## Why\n\nEach handle owns memory inside the WebAssembly module. Freeing it returns that memory at once, so the handle has nothing left to work on.\n\n## How to fix\n\nFree a handle only after its last use. To keep working with the document, open it again from its bytes, or create a new builder.\n\n## Example\n\n```ts\nconst doc = Document.open(bytes);\ndoc.free();\ndoc.save(); // throws LaminaPdfError { code: \"disposed\", … }\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2b](../todos/done/L2b-disposal-and-memory.md): the check on every handle, and on the pages and save jobs of `@laminapdf/wasm`\n",
|
|
124
131
|
"invalid-argument": "# `invalid-argument`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA value passed from JavaScript to `@laminapdf/wasm` is not of the type its declaration describes. It might be a record with a field of the wrong type, or a string that names no known value (a blend mode, a fill rule, a standard 14 font, an op). It might also be a flat-encoded path cut short, a colour with the wrong number of components, or an ID that isn't 32 hex digits.\n\n## Why\n\nThe `.d.ts` types describe each argument, but JavaScript (and code written without the types) can pass anything. The binding checks each value as it converts it.\n\n## How to fix\n\nPass what the declaration says. When the value names an unknown string, `didYouMean` lists the closest allowed ones; `data.detail` says what the conversion found.\n\n## Example\n\n```js\npage.blendMode(\"multiplly\"); // throws { code: \"invalid-argument\", didYouMean: [\"multiply\"], … }\n```\n\n## Data fields\n\n- `argument`: the parameter that was wrong (`options`, `path`, `mode`, …).\n- `detail`: what the conversion said (untrusted: it may quote the value passed).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §7\n- [ADR 0028](../decisions/0028-facade-rules-jobs-and-cancellation.md) F6\n",
|
|
125
132
|
"source-budget-exceeded": "# `source-budget-exceeded`\n\n- Type: error\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nA sparse source (`WasmSparseSource` in `@laminapdf/wasm`, or a `@laminapdf/sdk` range document) was handed bytes that would make it hold more than the byte budget it was created with. The bytes were not added.\n\n## Why\n\nA range source keeps every byte it has fetched: the document may already have read them, so nothing is evicted. The budget bounds how much of a remote or lazily read file one document may hold in memory.\n\n## How to fix\n\nCreate the source with a larger budget, or fetch less per round: smaller blocks and no readahead. A file that must be read whole (a full rewrite, or a repaired file with no usable xref) needs a budget of at least its size.\n\n## Example\n\n```js\nconst source = new WasmSparseSource(10_000_000, 1_000_000);\nsource.supply(0, new Uint8Array(2_000_000)); // throws { code: \"source-budget-exceeded\", … }\n```\n\n## Data fields\n\n- `argument`: `bytes`.\n- `detail`: how many bytes the source would hold and its budget (Lamina PDF's own numbers).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2c](../todos/done/L2c-range-byte-source.md): the range byte source\n- [ADR 0005](../decisions/0005-document-model.md) §2\n",
|
|
126
133
|
"unknown-option": "# `unknown-option`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nAn options record passed to `@laminapdf/wasm` (`OpenOptionsInit`, `SaveOptionsInit`, `BuildOptionsInit`, …) has a key Lamina PDF doesn't know.\n\n## Why\n\nRecords refuse unknown keys instead of ignoring them, so a misspelt option fails loudly rather than silently doing nothing.\n\n## How to fix\n\nRemove the key or correct its spelling. `didYouMean` lists the known keys within two edits of it.\n\n## Example\n\n```js\nWasmDocument.openBytes(bytes, { pasword: \"secret\" }); // throws { code: \"unknown-option\", didYouMean: [\"password\"], … }\n```\n\n## Data fields\n\n- `argument`: the parameter whose record had the key (`options`, `metadata`, …).\n- `option`: the key given (untrusted: caller text, never in the message).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0028](../decisions/0028-facade-rules-jobs-and-cancellation.md) F6\n- [ADR 0026](../decisions/0026-error-and-diagnostic-contract.md) §1\n",
|
|
127
134
|
"already-initialized": "# `already-initialized`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\n`init()` or `loadText()` of `@laminapdf/sdk` named a source (a URL, `Response`, bytes or `WebAssembly.Module`) for a module that an earlier call had already loaded, or started loading, from another source (or from the default file).\n\n## Why\n\nEach module is instantiated once per JavaScript realm: every document and builder lives in that instance. Loading a second copy from another source would leave two instances whose objects can't be mixed, so the second source is refused rather than silently ignored.\n\n## How to fix\n\nPass the source on the first call only; later calls (from other parts of the app) can call `init()` without one, which waits for the same load. Calling again with the very same source object is allowed.\n\n## Example\n\n```js\nawait init(new URL(\"/wasm/lamina_pdf_base.wasm\", location.href));\nawait init(); // fine: the module is loaded\nawait init(otherBytes); // throws { code: \"already-initialized\", … }\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §3\n",
|
|
128
135
|
"extract-module-not-loaded": "# `extract-module-not-loaded`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\n`page.text()` of `@laminapdf/sdk` was called on a page of a document opened in the base module, which has no text extraction.\n\n## Why\n\n`@laminapdf/sdk` ships three WebAssembly modules: base (open, read, edit, save), extract (base plus text extraction) and text (base plus fonts, shaping and extraction). A document lives in the module it was opened in, and opening uses the richest one loaded at that moment: text, then extract, then base. A document opened before the extract or text module was loaded stays in the base module.\n\n## How to fix\n\nLoad the extract module (about half the size of the text module) before opening the document: `await init({ extract: true })` or `await loadExtract()`. A document already open in the base module can be moved by saving it and opening the bytes again.\n\n## Example\n\n```js\nawait init();\nconst doc = Document.open(bytes);\ndoc.page(0).text(); // throws { code: \"extract-module-not-loaded\", … }\n\nawait loadExtract();\nDocument.open(bytes).page(0).text().text(); // works\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §4\n",
|
|
129
|
-
"fetch-failed": "# `fetch-failed`\n\n- Type: error\n- Kind: `io` (the host failed to supply bytes; often transient)\n\n## What happened\n\nA range source of `@laminapdf/sdk` (`httpRangeSource`) couldn't get bytes it asked for
|
|
136
|
+
"fetch-failed": "# `fetch-failed`\n\n- Type: error\n- Kind: `io` (the host failed to supply bytes; often transient)\n\n## What happened\n\nA range source of `@laminapdf/sdk` (`httpRangeSource`) couldn't get bytes it asked for. The request failed (a network error, a CORS refusal, DNS), or the server answered with a status other than `200` or `206`, or with a `206` whose `Content-Range` (or length) doesn't match the range asked for. A `Content-Range` that the browser hides, because CORS doesn't expose it, looks the same. It is also raised when a `callbackSource`'s read returns a different number of bytes than it was asked for.\n\n## Why\n\nOpening a remote file range by range depends on the server: it must allow the `Range` request (and, across origins, expose `Content-Range`, `Content-Length` and `ETag` through CORS), and must not compress the response (`Content-Encoding` breaks byte ranges). Lamina PDF never retries on its own; the error says the bytes are not available.\n\n## How to fix\n\nCheck that the URL is reachable from where the code runs and that the server sends `Access-Control-Allow-Origin`, `Access-Control-Allow-Headers: Range` and `Access-Control-Expose-Headers: Content-Range, Content-Length, ETag`. Serve PDFs without `Content-Encoding`. Retry the call yourself if the failure was transient.\n\n## Example\n\n```js\nconst doc = await Document.openRange(httpRangeSource(url)); // throws { code: \"fetch-failed\", data: { status: 403 } }\n```\n\n## Data fields\n\n- `reason`: `network`, `status`, `content-range` or `length` (Lamina PDF's own words). The URL is never included.\n- `status`: the HTTP status, when there was a response.\n- `expected`, `got`: for `length`, the bytes asked for and the bytes returned.\n",
|
|
130
137
|
"not-initialized": "# `not-initialized`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA function or class of `@laminapdf/sdk` (`Document.open`, `new Builder`, …) was called before `init()` had finished loading and instantiating the WebAssembly module.\n\n## Why\n\n`@laminapdf/sdk` is synchronous after `init()`, but fetching and compiling the `.wasm` file is asynchronous, so it happens once, up front, in `init()`. Until that promise resolves there is no module to call.\n\n## How to fix\n\nAwait `init()` once, before the first call; calling it again is cheap (it is idempotent). In a Cloudflare Worker, pass the imported module: `await init({ module: wasm })`.\n\n## Example\n\n```js\nimport { Document, init } from \"@laminapdf/sdk\";\nDocument.open(bytes); // throws { code: \"not-initialized\", … }\nawait init();\nDocument.open(bytes); // works\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §3\n",
|
|
131
138
|
"source-changed": "# `source-changed`\n\n- Type: error\n- Kind: `io` (the host failed to supply bytes; often transient)\n\n## What happened\n\nA remote file changed while `@laminapdf/sdk` was reading it range by range: a response's `ETag` or total length differs from the first one (or the server ignored `If-Range` and sent a different file).\n\n## Why\n\nA range document is assembled from many responses. If the file changed between them, the parts no longer belong to one file, and the document would read a mix of two versions. `httpRangeSource` sends `If-Range` with the first `ETag` and compares each response's `ETag` and `Content-Range` length with the first.\n\n## How to fix\n\nOpen the file again (a new source, a new document). If the file changes often, download it whole with `Document.open(bytes)` instead.\n\n## Example\n\n```js\nconst doc = await Document.openRange(httpRangeSource(url));\nawait doc.ensure(() => doc.pages); // throws { code: \"source-changed\", … } if the file was replaced meanwhile\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2c](../todos/done/L2c-range-byte-source.md): the range byte source\n",
|
|
132
139
|
"text-module-not-loaded": "# `text-module-not-loaded`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA font or text method (`Font` use, `surface.text`, `surface.textBox`, `builder.font`) was called on a `Builder` created while only the base WebAssembly module was loaded, or `new Builder({ text: true })` was called before the text module was loaded.\n\n## Why\n\n`@laminapdf/sdk` ships two modules: the base module (open, edit, save, vector and image pages) and the larger text module (all of the base plus fonts, shaping and text layout). A document that draws text is built entirely in the text module, and loading it is asynchronous, so it can't happen inside a synchronous drawing call. A builder created without the text module can't gain it later.\n\n## How to fix\n\nLoad the text module before creating the builder that draws text: `await init({ text: true })`, or `await loadText()` after `init()`. Builders created after that use the text module.\n\n## Example\n\n```js\nawait init();\nconst b = new Builder();\nb.page(\"A4\").surface().text(\"Hi\", { font: Font.standard(\"Helvetica\"), size: 12, at: [72, 72] });\n// throws { code: \"text-module-not-loaded\", … }\nawait loadText(); // then create a new Builder\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0016](../decisions/0016-package-design.md) §4\n",
|
|
133
|
-
"disposed": "# `disposed`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA `Document`, `Builder` or other handle of `@laminapdf/sdk` was used after `free()` released it, or after the `using` block that held it ended (`Symbol.dispose`).\n\n## Why\n\nEach handle owns memory inside the WebAssembly module. Freeing it returns that memory at once, so the handle has nothing left to work on.\n\n## How to fix\n\nFree a handle only after its last use. To keep working with the document, open it again from its bytes, or create a new builder.\n\n## Example\n\n```ts\nconst doc = Document.open(bytes);\ndoc.free();\ndoc.save(); // throws LaminaPdfError { code: \"disposed\", … }\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2b](../todos/ready/L2b-disposal-and-memory.md): adds the check that raises this code\n",
|
|
134
140
|
"worker-version-mismatch": "# `worker-version-mismatch`\n\n- Type: error\n- Kind: `usage` (the caller did something the API doesn't allow)\n\n## What happened\n\n`connect()` from `@laminapdf/sdk/worker` started a Web Worker, and its handshake named a different protocol or package version than the client. The client rejected `connect()` and sent nothing else.\n\n## Why\n\nThe client and the Web Worker exchange messages whose shape belongs to one build. A Web Worker from another version (an older deploy, a CDN copy, a separately bundled copy) could misread them, so the handshake fails loudly instead. PDF.js learned the same lesson.\n\n## How to fix\n\nLet the bundler serve the Web Worker from the same `@laminapdf/sdk` package as the page: `connect()` contains the literal `new Worker(new URL(…, import.meta.url))` that Vite and webpack follow. If you pass `{ worker }` yourself, build it from the same package version.\n\n## Example\n\n```ts\nconst client = await connect({ worker: new Worker(\"/old/lamina-worker.js\", { type: \"module\" }) });\n// rejects: LaminaPdfError { code: \"worker-version-mismatch\", … }\n```\n\n## Data fields\n\n- `expected`: the client's `{ protocol, version }`.\n- `actual`: what the Web Worker answered.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2a](../todos/done/L2a-worker-client.md): the worker client\n",
|
|
135
141
|
"worker-crashed": "# `worker-crashed`\n\n- Type: error\n- Kind: `internal` (a bug or an environment failure, not the caller's input)\n\n## What happened\n\nThe Web Worker running `@laminapdf/sdk` (from `@laminapdf/sdk/worker`) stopped: an uncaught error, a WebAssembly trap or the browser killing it (out of memory). Every call still in flight was rejected with this code, and the client emitted a `crashed` event.\n\n## Why\n\nA long synchronous call can keep the Web Worker busy without answering, so Lamina PDF has no heartbeat and never treats silence as a crash. Only the Web Worker's `error` or `messageerror` event, or a trap it reports, counts as a crash.\n\n## How to fix\n\nCall `client.restart()`, then open the document again: handles from the old Web Worker are gone. An encrypted document needs its password again. If one file keeps crashing the Web Worker, report it.\n\n## Example\n\n```ts\nclient.on(\"crashed\", () => client.restart());\nawait doc.save(); // rejects with LaminaPdfError { code: \"worker-crashed\", … } if the Web Worker died\n```\n\n## Data fields\n\n- `reason`: what ended the Web Worker: `error`, `messageerror` or `trap` (a crash, which emits `crashed`), or `terminated` (`client.terminate()`, `restart()`, or a call made when no Web Worker runs).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2a](../todos/done/L2a-worker-client.md): the worker client\n- [ADR 0009](../decisions/0009-web-client-architecture.md) §3.6\n",
|
|
136
142
|
"worker-failed": "# `worker-failed`\n\n- Type: error\n- Kind: `internal` (a bug or an environment failure, not the caller's input)\n\n## What happened\n\nA call through `@laminapdf/sdk/worker` failed inside the Web Worker with an error that isn't a `LaminaPdfError`. The call was rejected with this code and the error's message; the Web Worker and its documents keep working.\n\n## Why\n\nThe Web Worker passes Lamina PDF's own errors through unchanged and rejects caller mistakes it can detect (an unknown method, a parameter it can't receive) with `invalid-argument`. Anything else is a failure of Lamina PDF's client code, such as a result it couldn't send back or a bug in its code.\n\n## How to fix\n\nReport it, with the call you made and the message. The same call through the sync API on the main thread is a workaround while it is fixed.\n\n## Example\n\n```ts\nawait doc.pageCount(); // rejects with LaminaPdfError { code: \"worker-failed\", kind: \"internal\", … } on a bug in Lamina PDF's client\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2a](../todos/done/L2a-worker-client.md): the worker client\n",
|
|
143
|
+
"wasm-trap": "# `wasm-trap`\n\n- Type: error\n- Kind: `internal` (a bug in Lamina PDF or a broken invariant)\n\n## What happened\n\nThe WebAssembly module trapped during the call: Lamina PDF hit a bug and stopped. `@laminapdf/sdk` discarded the module's instance, so the next call runs in a fresh one. Every document, page and builder from the old instance now throws `instance-reset`.\n\n## Why\n\nA trap stops the module in the middle of its work, so its memory may hold half-written state. Nothing in that instance can be trusted afterwards. A fresh instance keeps one failed call from breaking every call after it.\n\n## How to fix\n\nOpen the document again from its bytes and retry. If the same call on the same file traps again, report it with the file: a trap is always a bug in Lamina PDF.\n\n## Example\n\n```ts\ntry {\n lines = doc.page(0).text().lines;\n} catch (e) {\n if (!isLaminaPdfError(e, \"wasm-trap\")) throw e;\n doc = Document.open(bytes); // the old document throws instance-reset from now on\n}\n```\n\n## Data fields\n\n- `module`: the module that trapped: `base`, `text` or `extract`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2b](../todos/done/L2b-disposal-and-memory.md): trap recovery and the fresh instance\n- [ADR 0016](../decisions/0016-package-design.md): the modules and their build\n",
|
|
144
|
+
"out-of-memory": "# `out-of-memory`\n\n- Type: error\n- Kind: `limit` (a `Limits` value or another resource bound was hit)\n\n## What happened\n\nThe WebAssembly module needed more memory than it could get, so it stopped in the middle of the call. Each module may grow to at most 2 GiB, and a browser tab or server can run out before that. `@laminapdf/sdk` discarded the module's instance, so the next call runs in a fresh one. Every document, page and builder from the old instance now throws `instance-reset`.\n\n## Why\n\nA module's memory grows as the module needs more and never shrinks. Many open documents, a huge image, or a file built to exhaust memory can each push it to its limit. The open limits stop most hostile files before memory runs out, and the maximum catches the rest.\n\n## How to fix\n\nOpen the document again, then keep less in memory at once. Free each document and builder as soon as you're done with it, or use `using`. For files from people you don't trust, lower the open limits, such as `maxStreamDecoded` and `maxImagePixels`, so they fail with `limit-exceeded` first. An app can also open each document in its own Web Worker, with `@laminapdf/sdk/worker`, and end the Web Worker afterwards: that returns all of its memory.\n\n## Example\n\n```ts\ntry {\n doc = Document.open(bytes, { limits: { maxStreamDecoded: 64_000_000 } });\n} catch (e) {\n if (isLaminaPdfError(e, \"out-of-memory\")) showError(\"This file is too large to open here.\");\n else throw e;\n}\n```\n\n## Data fields\n\n- `module`: the module that ran out: `base`, `text` or `extract`.\n- `memoryBytes`: the size of its memory when it stopped.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2b](../todos/done/L2b-disposal-and-memory.md): the memory maximum and the fresh instance\n- [ADR 0016](../decisions/0016-package-design.md): the maximum, set when the modules are built\n- [ADR 0003](../decisions/0003-reader-tolerance-and-limits.md) §3: the limits that come first\n",
|
|
145
|
+
"instance-reset": "# `instance-reset`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nA document, page, builder or save job was used after its WebAssembly instance was replaced. `reset()` replaces every loaded module's instance, and a trap (`wasm-trap` or `out-of-memory`) replaces the instance that trapped. The handle belonged to the old instance, so it has nothing left to work on.\n\n## Why\n\nEach handle lives in one instance's memory, and a fresh instance starts empty. Lamina PDF can't move a document across, so every handle from the old instance stops working at once.\n\n## How to fix\n\nOpen the document again from its bytes, or create a new builder. Unsaved edits are lost with the old instance, so save often in an app that calls `reset()` or may run out of memory.\n\n## Example\n\n```ts\nconst doc = Document.open(bytes);\nreset();\ndoc.pageCount; // throws LaminaPdfError { code: \"instance-reset\", … }\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [L2b](../todos/done/L2b-disposal-and-memory.md): `reset()` and trap recovery\n",
|
|
146
|
+
"invalid-command-line": "# `invalid-command-line`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nThe command line didn't parse: a command or flag `laminapdf` doesn't have, a missing argument, a value of the wrong form, or `-` (standard input) named as more than one input.\n\n## Why\n\nThe CLI checks its whole command line before it reads any file, so a typo never runs half a command. Exit code 2 tells a script that the call itself was wrong, not the document.\n\n## How to fix\n\nRun the command with `--help` to see its arguments, and `laminapdf --help` for the commands. Read standard input at most once per command.\n\n## Example\n\n```console\n$ laminapdf info --pages 1 report.pdf\nerror[invalid-command-line]: unexpected argument '--pages' found\n\nUsage: laminapdf info [OPTIONS] <INPUT>\n\nFor more information, try '--help'.\n$ echo $?\n2\n```\n\nWith `--json`, the line on standard error has the message \"the command line doesn't parse\" and the parser's finding in `data.detail`.\n\n## Data fields\n\nWhich field is there depends on what was wrong:\n\n- `detail`: when the parser refused the line, the kind of problem it found, such as `UnknownArgument` or `MissingRequiredArgument`.\n- `argument`: when a value parsed but means nothing, the value given: the angle of `pages rotate`, a `help` topic or a `--fields` key (untrusted: caller text, never in the message).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
147
|
+
"invalid-page-range": "# `invalid-page-range`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA page range doesn't fit the grammar, or it names a page the document doesn't have, such as page 9 of a 5-page file.\n\n## Why\n\nRanges count pages from 1, as people do. A range that can't be read, or that reaches past the last page, fails before anything is written, so a command never works on the wrong pages.\n\n## How to fix\n\nWrite pages as `1-5`, `z` for the last page, `r2` for the second from the end, `x3` to leave page 3 out, and `:odd` or `:even` at the end for every other page of the result. `data.position` is the character where the range went wrong.\n\n## Example\n\n```console\n$ laminapdf pages rotate scan.pdf +90:1-9 -o out.pdf\nerror[invalid-page-range]: the document has 5 pages\n = hint: write pages as 1-5, z for the last page, …\n$ echo $?\n2\n```\n\n## Data fields\n\n- `range`: the range given (untrusted: caller text, never in the message).\n- `position`: the 1-based character of `range` where it went wrong.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
148
|
+
"binary-output-to-terminal": "# `binary-output-to-terminal`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\nA command that writes a PDF was told to write it to standard output (`-o -`), and standard output is a terminal.\n\n## Why\n\nA PDF's bytes would fill the terminal with noise and can leave it in a strange state. The CLI writes binary output only to a file or a pipe.\n\n## How to fix\n\nRedirect standard output to a file or a pipe, or write to a file with `-o`.\n\n## Example\n\n```console\n$ laminapdf pages rotate scan.pdf +90 -o -\nerror[binary-output-to-terminal]: standard output is a terminal\n = hint: redirect standard output to a file or a pipe, or write to a file with -o\n$ laminapdf pages rotate scan.pdf +90 -o - > rotated.pdf\n```\n\n## Data fields\n\nNone.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
149
|
+
"unknown-code": "# `unknown-code`\n\n- Type: error\n- Kind: `usage` (the caller misused the API)\n\n## What happened\n\n`laminapdf explain` was given a code that isn't one of Lamina PDF's error or warning codes.\n\n## Why\n\nEvery code Lamina PDF reports is listed once, with its own page. A code that isn't listed has no explanation to print.\n\n## How to fix\n\nCheck the spelling: `didYouMean` lists the known codes closest to the one given. The tables in this folder's README list every code.\n\n## Example\n\n```console\n$ laminapdf explain xref-repaird\nerror[unknown-code]: not a Lamina PDF code\n = did you mean: xref-repaired\n$ echo $?\n2\n```\n\n## Data fields\n\n- `code`: the code given (untrusted: caller text, never in the message).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
150
|
+
"overwrite-refused": "# `overwrite-refused`\n\n- Type: error\n- Kind: `state` (the call isn't valid in the object's current state)\n\n## What happened\n\nThe output file already exists, or the command was asked to change its input in place with `--in-place`, and `--force` wasn't given.\n\n## Why\n\nThe CLI never replaces a file without being told to, so a mistyped `-o` can't destroy a document. It never prompts either, because scripts and agents can't answer a prompt. Exit code 4 tells a script the command needs `--force`.\n\n## How to fix\n\nPass `--force` to replace the file, or write to a new file with `-o`. The CLI writes to a temporary file and renames it, so a replaced file is never left half written.\n\n## Example\n\n```console\n$ laminapdf pages rotate scan.pdf 90:z --in-place\nerror[overwrite-refused]: refusing to replace a file without --force\n = hint: pass --force, or write to a new file with -o\n$ echo $?\n4\n```\n\n## Data fields\n\n- `output`: the file that would have been replaced (untrusted: caller text, never in the message).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
151
|
+
"input-unreadable": "# `input-unreadable`\n\n- Type: error\n- Kind: `io` (the host failed to supply or take bytes)\n\n## What happened\n\nAn input couldn't be read: the PDF named on the command line, standard input, or the file given to `--password-file`.\n\n## Why\n\nThe file may not exist, may be a folder, or may not be readable by the user running the command.\n\n## How to fix\n\nCheck that the file exists and that you can read it. `data.input` names the file, and `data.reason` says what the system reported.\n\n## Example\n\n```console\n$ laminapdf info missing.pdf\nerror[input-unreadable]: couldn't read an input\n = hint: check that the file exists and that you can read it; data.input names it\n$ echo $?\n1\n```\n\n## Data fields\n\n- `input`: the file that couldn't be read, or `-` for standard input (untrusted: caller text, never in the message).\n- `reason`: the system's error kind, such as `NotFound` or `PermissionDenied`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
152
|
+
"output-unwritable": "# `output-unwritable`\n\n- Type: error\n- Kind: `io` (the host failed to supply or take bytes)\n\n## What happened\n\nThe output couldn't be written: its folder is missing or read-only, the disk is full, or standard output was closed before the command finished.\n\n## Why\n\nThe system refused the write, or standard output closed while the command was writing to it. The CLI writes to a temporary file beside the output and renames it into place, so a failed write leaves any old file as it was.\n\n## How to fix\n\nCheck that the output's folder exists, that you can write to it and that the disk has room. When piping, make sure the reading command doesn't exit early.\n\n## Example\n\n```console\n$ laminapdf pages rotate scan.pdf +90 -o /no/such/folder/out.pdf\nerror[output-unwritable]: couldn't write the output\n = hint: check that the output's folder exists, …\n$ echo $?\n1\n```\n\n## Data fields\n\n- `output`: the file that couldn't be written, or `-` for standard output (untrusted: caller text, never in the message).\n- `reason`: the system's error kind, such as `NotFound` or `StorageFull`.\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §4, §5 and §8\n- [L4a](../todos/done/L4a-lamina-cli.md): the `laminapdf` CLI and its first commands\n",
|
|
153
|
+
"path-outside-roots": "# `path-outside-roots`\n\n- Type: error\n- Kind: `security` (encryption, permissions or signatures block the call)\n\n## What happened\n\nA tool of `laminapdf mcp` was given a path the server may not use: one outside every `--root` folder it was started with, one that climbs out with `..`, or a symbolic link inside a root that leads out of it. A missing file outside the roots, and a link that leads nowhere, get this answer too, so a call can't tell whether a file outside the roots exists.\n\n## Why\n\nAn MCP server acts for a model that may have read instructions planted in a document or a web page. So the server touches only the folders named on its command line by the person who started it. It resolves every path, links included, before it checks the path, so a link can't lead it elsewhere.\n\n## How to fix\n\nUse a path inside one of the server's `--root` folders; a relative path is read from the first root. To work on files elsewhere, start the server with another `--root`.\n\n## Example\n\n```json\n{\"schema\":\"laminapdf.error/1\",\"error\":{\"code\":\"path-outside-roots\",\"kind\":\"security\",\"message\":\"the path is outside the server's --root folders\",\"data\":{\"path\":\"../secret.pdf\"},\"exitCode\":1,…}}\n```\n\n## Data fields\n\n- `path`: the path the tool was given (untrusted: caller text, never in the message).\n\n## For contributors\n\nThe decisions and todos behind this code:\n\n- [ADR 0031](../decisions/0031-cli-and-mcp-contract.md) §9\n- [L4c](../todos/done/L4c-mcp-mode.md): `laminapdf mcp` and its path policy\n",
|
|
137
154
|
};
|
|
138
155
|
//# sourceMappingURL=explain.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/generated/explain.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,6FAA6F;AAC7F,qFAAqF;AAIrF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,KAAK,GAAwD;IACxE,gBAAgB,EAAE,o8BAAo8B;IACt9B,eAAe,EAAE,u8BAAu8B;IACx9B,iBAAiB,EAAE,8yBAA8yB;IACj0B,yBAAyB,EAAE,0pBAA0pB;IACrrB,kBAAkB,EAAE,6sBAA6sB;IACjuB,wBAAwB,EAAE,myBAAmyB;IAC7zB,qBAAqB,EAAE,ulBAAulB;IAC9mB,iBAAiB,EAAE,iqBAAiqB;IACprB,uBAAuB,EAAE,6nBAA6nB;IACtpB,4BAA4B,EAAE,mmBAAmmB;IACjoB,qBAAqB,EAAE,qxBAAqxB;IAC5yB,gBAAgB,EAAE,gnBAAgnB;IACloB,oBAAoB,EAAE,itBAAitB;IACvuB,aAAa,EAAE,6yBAA6yB;IAC5zB,gBAAgB,EAAE,0kBAA0kB;IAC5lB,wBAAwB,EAAE,oqBAAoqB;IAC9rB,eAAe,EAAE,sgBAAsgB;IACvhB,sBAAsB,EAAE,wkBAAwkB;IAChmB,cAAc,EAAE,kkBAAkkB;IACllB,oBAAoB,EAAE,8oBAA8oB;IACpqB,eAAe,EAAE,yoBAAyoB;IAC1pB,0BAA0B,EAAE,kjCAAkjC;IAC9kC,sBAAsB,EAAE,q1BAAq1B;IAC72B,sBAAsB,EAAE,o7BAAo7B;IAC58B,uBAAuB,EAAE,48BAA48B;IACr+B,2BAA2B,EAAE,6/BAA6/B;IAC1hC,gBAAgB,EAAE,8+BAA8+B;IAChgC,0BAA0B,EAAE,2uCAA2uC;IACvwC,2BAA2B,EAAE,2+BAA2+B;IACxgC,eAAe,EAAE,4zBAA4zB;IAC70B,wBAAwB,EAAE,g4BAAg4B;IAC15B,cAAc,EAAE,8uCAA8uC;IAC9vC,cAAc,EAAE,yrCAAyrC;IACzsC,gBAAgB,EAAE,+sCAA+sC;IACjuC,SAAS,EAAE,+kBAA+kB;IAC1lB,cAAc,EAAE,qeAAqe;IACrf,iBAAiB,EAAE,ohBAAohB;IACviB,gBAAgB,EAAE,snCAAsnC;IACxoC,QAAQ,EAAE,+mBAA+mB;IACznB,cAAc,EAAE,guBAAguB;IAChvB,QAAQ,EAAE,6dAA6d;IACve,MAAM,EAAE,4oBAA4oB;IACppB,mBAAmB,EAAE,ukBAAukB;IAC5lB,cAAc,EAAE,+gBAA+gB;IAC/hB,eAAe,EAAE,gpBAAgpB;IACjqB,gBAAgB,EAAE,gsCAAgsC;IACltC,mBAAmB,EAAE,kkBAAkkB;IACvlB,gBAAgB,EAAE,8rBAA8rB;IAChtB,8BAA8B,EAAE,wuBAAwuB;IACxwB,gBAAgB,EAAE,ijBAAijB;IACnkB,QAAQ,EAAE,+iBAA+iB;IACzjB,oBAAoB,EAAE,8nBAA8nB;IACppB,YAAY,EAAE,4eAA4e;IAC1f,oBAAoB,EAAE,ylBAAylB;IAC/mB,gBAAgB,EAAE,2bAA2b;IAC7c,cAAc,EAAE,mgBAAmgB;IACnhB,aAAa,EAAE,oyBAAoyB;IACnzB,qBAAqB,EAAE,4iBAA4iB;IACnkB,gBAAgB,EAAE,6pBAA6pB;IAC/qB,mBAAmB,EAAE,25BAA25B;IACh7B,iBAAiB,EAAE,ohBAAohB;IACviB,MAAM,EAAE,61BAA61B;IACr2B,aAAa,EAAE,ozBAAozB;IACn0B,gBAAgB,EAAE,wxBAAwxB;IAC1yB,6BAA6B,EAAE,k4DAAk4D;IACj6D,kBAAkB,EAAE,6yCAA6yC;IACj0C,cAAc,EAAE,gxBAAgxB;IAChyB,kBAAkB,EAAE,ylBAAylB;IAC7mB,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"explain.js","sourceRoot":"","sources":["../../src/generated/explain.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/** One cell of a table block. */
|
|
2
|
+
export type Cell = {
|
|
3
|
+
/** Its box in page space. */
|
|
4
|
+
bbox: [number, number, number, number];
|
|
5
|
+
/** The first column it covers, 0 at the left. */
|
|
6
|
+
col: number;
|
|
7
|
+
/** How many columns it covers. */
|
|
8
|
+
colSpan: number;
|
|
9
|
+
/** Whether it is in a header row. */
|
|
10
|
+
header: boolean;
|
|
11
|
+
/** The first row it covers, 0 at the top. */
|
|
12
|
+
row: number;
|
|
13
|
+
/** How many rows it covers. */
|
|
14
|
+
rowSpan: number;
|
|
15
|
+
/** Its visible text, lines joined by a space. */
|
|
16
|
+
text: string;
|
|
17
|
+
};
|
|
18
|
+
/** One chunk. */
|
|
19
|
+
export type Chunk = {
|
|
20
|
+
/** The blocks it holds, in order. */
|
|
21
|
+
blockIds: string[];
|
|
22
|
+
/** The headings above its first block, outermost first. */
|
|
23
|
+
headingPath: string[];
|
|
24
|
+
/** `c<n>`, from 0, in order. */
|
|
25
|
+
id: string;
|
|
26
|
+
/** The pages its blocks are on, ascending. */
|
|
27
|
+
pages: number[];
|
|
28
|
+
/** Its area on each of those pages. */
|
|
29
|
+
regions: Region[];
|
|
30
|
+
/** The Markdown from the first block's start to the last block's end. */
|
|
31
|
+
text: string;
|
|
32
|
+
/** Where `text` sits in the Markdown. */
|
|
33
|
+
textRange: TextRange;
|
|
34
|
+
/** [`tokens_approx`] of `text`. */
|
|
35
|
+
tokensApprox: number;
|
|
36
|
+
};
|
|
37
|
+
/** ADR 0027 §4's `coordinates` block: top-left points of the displayed box. */
|
|
38
|
+
export type Coordinates = {
|
|
39
|
+
/** `"CropBox"`, or `"default"` when the page had no usable box and US Letter was used. */
|
|
40
|
+
box: string;
|
|
41
|
+
/** Always `"top-left"`. */
|
|
42
|
+
origin: string;
|
|
43
|
+
/** The `/Rotate` applied, in degrees clockwise. */
|
|
44
|
+
rotate: number;
|
|
45
|
+
/** Always `"pt"`. */
|
|
46
|
+
unit: string;
|
|
47
|
+
/** The `/UserUnit` applied. */
|
|
48
|
+
userUnit: number;
|
|
49
|
+
};
|
|
50
|
+
/** Why text was left out. */
|
|
51
|
+
export type DropReason = "invisible" | "off-page" | "tiny" | "clipped" | "low-contrast" | "artifact" | "running-header" | "running-footer" | "page-number";
|
|
52
|
+
/**
|
|
53
|
+
* Text left out of the output ([ADR 0030] §4). It records a count, never the text, so a log of
|
|
54
|
+
* the output can't leak what was hidden.
|
|
55
|
+
*
|
|
56
|
+
* [ADR 0030]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0030-extraction-output-and-model-plugins.md
|
|
57
|
+
*/
|
|
58
|
+
export type Dropped = {
|
|
59
|
+
/** Where it was, in page space. */
|
|
60
|
+
bbox: [number, number, number, number];
|
|
61
|
+
/** How many characters were left out. */
|
|
62
|
+
chars: number;
|
|
63
|
+
/** The page index. */
|
|
64
|
+
page: number;
|
|
65
|
+
/** Why it was left out (the first reason when there are several). */
|
|
66
|
+
reason: DropReason;
|
|
67
|
+
/**
|
|
68
|
+
* The run itself, only when [`DropOptions::keep_spans`](crate::DropOptions::keep_spans)
|
|
69
|
+
* asked for it.
|
|
70
|
+
*/
|
|
71
|
+
spans?: Span[];
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* One extracted page ([ADR 0027] §4).
|
|
75
|
+
*
|
|
76
|
+
* [ADR 0027]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0027-coordinates-units-and-page-indexing.md
|
|
77
|
+
*/
|
|
78
|
+
export type ExtractedPage = {
|
|
79
|
+
/** The frame the boxes are in. */
|
|
80
|
+
coordinates: Coordinates;
|
|
81
|
+
/** The displayed height in points. */
|
|
82
|
+
height: number;
|
|
83
|
+
/** 0-based. */
|
|
84
|
+
index: number;
|
|
85
|
+
/** The page label (`/PageLabels`), when there is one. */
|
|
86
|
+
label?: string | null;
|
|
87
|
+
/** 1-based, as people count. */
|
|
88
|
+
number: number;
|
|
89
|
+
/** The displayed width in points (after `/Rotate` and `/UserUnit`). */
|
|
90
|
+
width: number;
|
|
91
|
+
};
|
|
92
|
+
/** The input, as ADR 0030 §1's `source` describes it. */
|
|
93
|
+
export type ExtractedSource = {
|
|
94
|
+
/** The document's page count. */
|
|
95
|
+
pageCount: number;
|
|
96
|
+
/**
|
|
97
|
+
* The input's SHA-256 in hex: filled by the caller that holds the bytes (the façade), since
|
|
98
|
+
* a windowed source can't be hashed without reading it whole.
|
|
99
|
+
*/
|
|
100
|
+
sha256?: string | null;
|
|
101
|
+
/** Where the reading order came from. */
|
|
102
|
+
structSource: StructSource;
|
|
103
|
+
/** Whether the catalog's `/MarkInfo` says `/Marked true`. */
|
|
104
|
+
tagged: boolean;
|
|
105
|
+
};
|
|
106
|
+
/** Why a run would be hidden from a reader; empty for visible text. */
|
|
107
|
+
export type Flags = DropReason[];
|
|
108
|
+
/** Who made the extraction (ADR 0030 §1's `generator`). */
|
|
109
|
+
export type Generator = {
|
|
110
|
+
/** `"rules"`, or `"rules+models"` once model plug-ins exist. */
|
|
111
|
+
mode: string;
|
|
112
|
+
models: unknown[];
|
|
113
|
+
name: string;
|
|
114
|
+
version: string;
|
|
115
|
+
};
|
|
116
|
+
/** A block and where its text sits in the Markdown. */
|
|
117
|
+
export type JsonBlock = {
|
|
118
|
+
/** The block's box in page space. */
|
|
119
|
+
bbox: [number, number, number, number];
|
|
120
|
+
/**
|
|
121
|
+
* The box divided by the page's width and height, clamped to [0, 1]; `None` when the
|
|
122
|
+
* block lies wholly outside the page.
|
|
123
|
+
*/
|
|
124
|
+
bboxNorm?: [number, number, number, number] | null;
|
|
125
|
+
/** A table's cells, row by row; empty for every other block. */
|
|
126
|
+
cells?: Cell[];
|
|
127
|
+
/** In [0, 1]: 1 for structure from the tree, lower for structure inferred from layout. */
|
|
128
|
+
confidence: number;
|
|
129
|
+
/** `p<page index>-b<position in the page's reading order>`. */
|
|
130
|
+
id: string;
|
|
131
|
+
/** The page index. */
|
|
132
|
+
page: number;
|
|
133
|
+
/** The runs of text, in reading order. */
|
|
134
|
+
spans: Span[];
|
|
135
|
+
/** The structure types from the root down to the block; empty when untagged. */
|
|
136
|
+
structPath: string[];
|
|
137
|
+
/** The structure element the block comes from, when it comes from one. */
|
|
138
|
+
structRef?: StructRef | null;
|
|
139
|
+
/** The visible text, lines joined by a space after the text fixes (ADR 0030 §5). */
|
|
140
|
+
text: string;
|
|
141
|
+
textRange: TextRange;
|
|
142
|
+
} & ({
|
|
143
|
+
/** 1–6. */
|
|
144
|
+
level: number;
|
|
145
|
+
type: "heading";
|
|
146
|
+
} | {
|
|
147
|
+
type: "paragraph";
|
|
148
|
+
} | {
|
|
149
|
+
/** 0 for the outermost list. */
|
|
150
|
+
depth: number;
|
|
151
|
+
/** The bullet or number that starts it. */
|
|
152
|
+
marker: string;
|
|
153
|
+
type: "list-item";
|
|
154
|
+
} | {
|
|
155
|
+
type: "caption";
|
|
156
|
+
} | {
|
|
157
|
+
type: "footnote";
|
|
158
|
+
} | {
|
|
159
|
+
type: "other";
|
|
160
|
+
} | {
|
|
161
|
+
/** The grid's columns. */
|
|
162
|
+
cols: number;
|
|
163
|
+
/** What found it. */
|
|
164
|
+
detector: TableDetector;
|
|
165
|
+
/** The grid's rows. */
|
|
166
|
+
rows: number;
|
|
167
|
+
type: "table";
|
|
168
|
+
});
|
|
169
|
+
/** A chunk's area on one page. */
|
|
170
|
+
export type Region = {
|
|
171
|
+
/** The union of the chunk's blocks' boxes on that page, in page space. */
|
|
172
|
+
bbox: [number, number, number, number];
|
|
173
|
+
/** The page index. */
|
|
174
|
+
page: number;
|
|
175
|
+
};
|
|
176
|
+
/** One run of text in a block or a dropped entry. */
|
|
177
|
+
export type Span = {
|
|
178
|
+
/** The baseline's y in page space (ADR 0027 §5). */
|
|
179
|
+
baseline: number;
|
|
180
|
+
/** Its box in page space. */
|
|
181
|
+
bbox: [number, number, number, number];
|
|
182
|
+
/** Why the run would be hidden; empty for visible text. */
|
|
183
|
+
flags: Flags;
|
|
184
|
+
/** The font's `/BaseFont`. */
|
|
185
|
+
font: string;
|
|
186
|
+
/** The glyph size in points. */
|
|
187
|
+
size: number;
|
|
188
|
+
/** The run's text. */
|
|
189
|
+
text: string;
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* A structure element ([ADR 0030] §1's `structRef`).
|
|
193
|
+
*
|
|
194
|
+
* [ADR 0030]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0030-extraction-output-and-model-plugins.md
|
|
195
|
+
*/
|
|
196
|
+
export type StructRef = {
|
|
197
|
+
/** Its generation. */
|
|
198
|
+
gen: number;
|
|
199
|
+
/** The marked-content identifiers it covers on the page. */
|
|
200
|
+
mcids: number[];
|
|
201
|
+
/** The element's object number. */
|
|
202
|
+
obj: number;
|
|
203
|
+
};
|
|
204
|
+
/**
|
|
205
|
+
* Where the reading order came from ([ADR 0030] §2).
|
|
206
|
+
*
|
|
207
|
+
* [ADR 0030]: https://github.com/laudebugs/laminapdf/blob/main/docs/decisions/0030-extraction-output-and-model-plugins.md
|
|
208
|
+
*/
|
|
209
|
+
export type StructSource = "tagged" | "xycut" | "content";
|
|
210
|
+
/** What found a table. */
|
|
211
|
+
export type TableDetector = "lattice" | "stream" | "tagged";
|
|
212
|
+
/**
|
|
213
|
+
* Where a piece of text sits in a rendering, in Unicode scalar values (`char`s), `start`
|
|
214
|
+
* inclusive and `end` exclusive. Code points, not bytes or UTF-16 units, so Python slices a
|
|
215
|
+
* rendering with them as they are; [`Rendered::slice`] does it in Rust.
|
|
216
|
+
*/
|
|
217
|
+
export type TextRange = {
|
|
218
|
+
/** One past the last character. */
|
|
219
|
+
end: number;
|
|
220
|
+
/** The first character. */
|
|
221
|
+
start: number;
|
|
222
|
+
};
|
|
223
|
+
/** The whole document. */
|
|
224
|
+
export type Extraction = {
|
|
225
|
+
blocks: JsonBlock[];
|
|
226
|
+
chunks?: Chunk[] | null;
|
|
227
|
+
dropped: Dropped[];
|
|
228
|
+
generator: Generator;
|
|
229
|
+
pages: ExtractedPage[];
|
|
230
|
+
/** Always `"laminapdf.extract/1"`. */
|
|
231
|
+
schema: string;
|
|
232
|
+
source: ExtractedSource;
|
|
233
|
+
warnings: unknown[];
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/generated/extract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../../src/generated/extract.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,6DAA6D"}
|
package/dist/init.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as baseGlue from "@laminapdf/wasm/base";
|
|
2
|
+
import { Instance } from "./internal/instance.js";
|
|
2
3
|
/** The base module's wasm-bindgen glue. */
|
|
3
4
|
export type BaseGlue = typeof baseGlue;
|
|
4
5
|
/** The text module's wasm-bindgen glue (a superset of the base module's API). */
|
|
@@ -39,14 +40,14 @@ export declare function loadTextWith(locate: Locate, source?: WasmSource): Promi
|
|
|
39
40
|
export declare function loadExtractWith(locate: Locate, source?: WasmSource): Promise<void>;
|
|
40
41
|
/** `init` for an export condition's `locate`. */
|
|
41
42
|
export declare function initWith(locate: Locate, input?: WasmSource | InitOptions): Promise<void>;
|
|
42
|
-
/** The base module
|
|
43
|
-
export declare function baseModule(): BaseGlue
|
|
43
|
+
/** The base module. @throws {@link LaminaPdfError} `not-initialized` before `init()`. */
|
|
44
|
+
export declare function baseModule(): Instance<BaseGlue>;
|
|
44
45
|
/**
|
|
45
46
|
* The module documents are opened in: the text module when loaded, else the extract module, else
|
|
46
47
|
* the base one (each a superset of the base module's reading API; the first two extract text).
|
|
47
48
|
* @throws {@link LaminaPdfError} `not-initialized` before `init()`.
|
|
48
49
|
*/
|
|
49
|
-
export declare function readingModule(): BaseGlue
|
|
50
|
+
export declare function readingModule(): Instance<BaseGlue>;
|
|
50
51
|
/**
|
|
51
52
|
* Whether documents opened or built from now on can extract text: the extract or the text module
|
|
52
53
|
* is loaded. A document opened earlier stays in the module it was opened in; ask it with
|
|
@@ -55,8 +56,8 @@ export declare function readingModule(): BaseGlue;
|
|
|
55
56
|
export declare function isExtractLoaded(): boolean;
|
|
56
57
|
/** Whether `doc` lives in a module that extracts text (the extract or the text module). */
|
|
57
58
|
export declare function extractsText(doc: object): boolean;
|
|
58
|
-
/** The text module
|
|
59
|
-
export declare function textModule(): TextGlue | undefined;
|
|
59
|
+
/** The text module, when loaded. */
|
|
60
|
+
export declare function textModule(): Instance<TextGlue> | undefined;
|
|
60
61
|
/** Whether `init()` has finished. */
|
|
61
62
|
export declare function isInitialized(): boolean;
|
|
62
63
|
/** Whether the text module is loaded (builders created now can draw text). */
|
|
@@ -77,4 +78,11 @@ export interface WasmMemory {
|
|
|
77
78
|
* @returns the byte length of each loaded module's memory.
|
|
78
79
|
*/
|
|
79
80
|
export declare function wasmMemory(): WasmMemory;
|
|
81
|
+
/**
|
|
82
|
+
* Replaces each loaded module's instance with a fresh one, so its memory returns to the size it
|
|
83
|
+
* had after `init()`: WebAssembly memory grows and never shrinks, and this gives it back. Every
|
|
84
|
+
* document, page, builder and save job made before throws `instance-reset` afterwards, so call it
|
|
85
|
+
* while none is in use, such as between jobs on a server. Images and fonts keep working.
|
|
86
|
+
*/
|
|
87
|
+
export declare function reset(): void;
|
|
80
88
|
//# sourceMappingURL=init.d.ts.map
|
package/dist/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAElD,2CAA2C;AAC3C,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC;AACvC,iFAAiF;AACjF,MAAM,MAAM,QAAQ,GAAG,cAAc,sBAAsB,CAAC,CAAC;AAI7D;;;GAGG;AACH,MAAM,MAAM,UAAU,GAClB,GAAG,GACH,MAAM,GACN,QAAQ,GACR,WAAW,CAAC,QAAQ,CAAC,GACrB,WAAW,GACX,eAAe,GACf,WAAW,CAAC,MAAM,CAAC;AAEvB,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,uGAAuG;IACvG,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CACzC;AAED;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;AA6DvH,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlF;AAED,iDAAiD;AACjD,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAe9F;AAED,yFAAyF;AACzF,wBAAgB,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAK/C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAGlD;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKjD;AAED,oCAAoC;AACpC,wBAAgB,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,SAAS,CAE3D;AAED,qCAAqC;AACrC,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,qDAAqD;IACrD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,UAAU,CAMvC;AAED;;;;;GAKG;AACH,wBAAgB,KAAK,IAAI,IAAI,CAE5B"}
|