documents.js 1.32.0 → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,20 @@
1
1
  # documents.js
2
2
 
3
- > Bidirectional docx/pptx ⇄ PDF conversion and a read+write editable OOXML document model, built on [ooxml.js](https://github.com/ExaDev/ooxml.js) and Zod 4 codecs.
3
+ [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/documents.js) [![npm](https://img.shields.io/npm/v/documents.js?logo=npm)](https://www.npmjs.com/package/documents.js) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/documents.js/ci.yml?branch=main)](https://github.com/ExaDev/documents.js/actions)
4
4
 
5
- `documents.js` depends on `ooxml.js` for lossless docx/pptx/xlsxJSON handling and extends it in two directions `ooxml.js` deliberately does not cover: full PDF support, and a read-**and-write** manipulation API for docx/pptx content (`ooxml.js`'s own typed readers are one-way and explicitly forbid write-back). PDF reading, writing, and the docx⇄pdf/pptx⇄pdf conversion codecs are entirely hand-written — no external PDF library is a dependency.
5
+ > Bidirectional docx/pptx ⇄ PDF conversion, a read-and-write live-view editor for docx/pptx content, and a fully hand-written PDF codec, built on [ooxml.js](https://github.com/ExaDev/ooxml.js).
6
6
 
7
- **Status: early bootstrap.** This repository currently contains only project scaffolding; the source tree, tooling, and package have not been built yet.
7
+ `documents.js` depends on `ooxml.js` for lossless docx/pptx/xlsx ⇄ JSON handling and extends it in two directions `ooxml.js` deliberately does not cover: full PDF support (parsing arbitrary real-world PDFs and generating new ones), and a read-**and-write** manipulation API for docx/pptx content — `ooxml.js`'s own typed readers (`readDocx`/`readPptx`) are one-way and explicitly forbid write-back. PDF reading, writing, and the docx⇄PDF/pptx⇄PDF conversion pipeline are entirely hand-written: no external PDF library (`pdf-lib`, `pdfjs-dist`, `mupdf`, or any other) is a dependency. The one exception is [`fflate`](https://github.com/101arrowz/fflate) for raw DEFLATE/zlib compression underneath PDF's `FlateDecode` filter and PNG's `IDAT` chunks — the same dependency `ooxml.js` itself already relies on for ZIP handling.
8
+
9
+ ## Why
10
+
11
+ Converting docx/pptx to PDF and back is usually solved by wrapping a mature third-party PDF library. This package takes the opposite approach: every layer of the PDF format — the object model, the cross-reference table, the content-stream operators, standard-font metrics, the parser's cross-reference/object-stream resolution and content-stream interpreter — is hand-written against the ISO 32000-1 specification. That is a genuinely large undertaking (the PDF codec is comparable in size to the rest of the package combined), and it comes with an honest trade-off spelled out in [Fidelity](#fidelity) below: this is not, and does not attempt to be, as robust against adversarial or badly malformed real-world PDFs as a library with 15+ years of hardening. What it buys instead is a dependency-free, fully auditable PDF implementation with no supply-chain surface beyond `ooxml.js` and `fflate`.
12
+
13
+ The read-and-write editor exists because `ooxml.js`'s own typed readers are a deliberate one-way, lossy projection — reading is fine, but there is no way to add a paragraph, style a run, or insert an image and get a valid docx/pptx back out. `documents.js`'s editors are live views directly over the `XmlElement` objects inside a decoded `Package`: a mutation edits that tree in place, and everything you don't touch round-trips byte-faithful, because it never stopped being the original XML.
8
14
 
9
15
  ## Getting started
10
16
 
11
- Requires Node.js `>=20` and pnpm `11.6.0` (pinned via `packageManager` in `package.json`, once it exists).
17
+ Requires Node.js `>=20` and pnpm `11.6.0` (pinned via `packageManager` in `package.json`).
12
18
 
13
19
  ```sh
14
20
  pnpm install
@@ -22,9 +28,96 @@ pnpm add documents.js
22
28
  npm install documents.js
23
29
  ```
24
30
 
25
- ## Build, test, and lint
31
+ ## Usage
32
+
33
+ The four ergonomic conversions:
34
+
35
+ ```ts
36
+ import { docxToPdf, pdfToDocx, pptxToPdf, pdfToPptx } from 'documents.js';
37
+
38
+ const pdfBytes = docxToPdf(docxBytes);
39
+ const docxBytes2 = pdfToDocx(pdfBytes);
40
+
41
+ const pdfFromSlides = pptxToPdf(pptxBytes);
42
+ const pptxBytes2 = pdfToPptx(pdfFromSlides);
43
+ ```
44
+
45
+ Each accepts an optional `signal` (`AbortSignal`) and either a `onSubstitution` callback (docx/pptx → PDF, called once per character not representable in a standard-14 font) or a `sink` (PDF → docx/pptx, called once per recoverable parse diagnostic).
46
+
47
+ The same four conversions behind a swappable port, for a caller that wants to inject a different implementation later without changing call sites:
48
+
49
+ ```ts
50
+ import { createLocalDocumentConverter } from 'documents.js';
51
+
52
+ const converter = createLocalDocumentConverter();
53
+ const { document, diagnostics } = await converter.convert(
54
+ { source: { format: 'docx', bytes: docxBytes }, targetFormat: 'pdf' },
55
+ { signal: new AbortController().signal },
56
+ );
57
+ ```
58
+
59
+ Reading and editing docx/pptx content directly, without going through PDF at all:
60
+
61
+ ```ts
62
+ import { openDocx, createDocx } from 'documents.js';
63
+
64
+ const editor = openDocx(existingDocxBytes);
65
+ const paragraph = editor.body.appendParagraph({ alignment: 'center' });
66
+ const run = paragraph.appendRun({ text: 'Hello' });
67
+ run.bold = true;
68
+ run.color = { r: 1, g: 0, b: 0 };
69
+ const bytes = editor.toBytes();
70
+
71
+ // or start from nothing:
72
+ const fresh = createDocx();
73
+ fresh.body.appendParagraph().appendRun({ text: 'New document' });
74
+ ```
75
+
76
+ `openPptx`/`createPptx` and `PptxSlide`/`PptxShape` are the pptx equivalent (`slide.addTextBox`, `slide.addImage`, `shape.setParagraphs` for multi-paragraph styled text).
77
+
78
+ Reading and writing PDF bytes directly, without going through docx/pptx:
79
+
80
+ ```ts
81
+ import { readPdf, writePdf } from 'documents.js';
82
+
83
+ const layout = readPdf(pdfBytes); // -> LayoutDocument: pages of positioned text/image/rect/link items
84
+ const bytes = writePdf(layout);
85
+ ```
86
+
87
+ The same three round trips (PDF ⇄ `LayoutDocument`, docx ⇄ PDF, pptx ⇄ PDF) are each also available as a schema-validated [`z.codec()`](https://zod.dev) pair, mirroring `ooxml.js`'s own `packageCodec` — `z.decode`/`z.encode` validate both the raw bytes (against the magic-byte schemas below) and the parsed value (against `LayoutDocumentSchema`) on every call, catching a malformed value that a bare function call wouldn't. This is the no-extra-options form: `readPdf`/`writePdf`/`docxToPdf`/etc. remain the entry points for cancellation (`signal`), diagnostics (`sink`), or substitution reporting (`onSubstitution`), none of which fit `z.codec()`'s fixed `decode(input)`/`encode(output)` signature.
26
88
 
27
- Once the tooling scaffold lands, the scripts mirror `ooxml.js` exactly:
89
+ ```ts
90
+ import { z } from 'zod';
91
+ import { docxPdfCodec, pdfCodec, pptxPdfCodec } from 'documents.js';
92
+
93
+ const layout = z.decode(pdfCodec, pdfBytes); // throws a ZodError if pdfBytes has no %PDF- header
94
+ const pdfBytes2 = z.encode(pdfCodec, layout);
95
+
96
+ const pdfFromDocx = z.decode(docxPdfCodec, docxBytes);
97
+ const docxBack = z.encode(docxPdfCodec, pdfFromDocx);
98
+ ```
99
+
100
+ `readDocxContent`/`readPptxContent` (docx/pptx → `ContentDocument`), `convertWordprocessingToLayout`/`convertPresentationToLayout` (`ContentDocument` → `LayoutDocument`), and `reconstructWordprocessing`/`reconstructPresentation` (`LayoutDocument` → `ContentDocument`) are each exported individually too, for a caller that wants one stage of the pipeline without the rest.
101
+
102
+ ## Architecture
103
+
104
+ The package is layered from generic primitives outward to the two conversion directions:
105
+
106
+ - **`src/model/`** — Zod schemas only, no behaviour: unit conversions (EMU/twip/point/half-point), geometry (`Box`, `PageSize`, `Margins`, the one deliberate `flipY` between OOXML's top-left/y-down space and PDF's bottom-left/y-up space), colour, and the two pivot models — `LayoutDocument` (the PDF-side pivot: pages of positioned text/image/rect/line/ellipse/link items, PDF-native coordinates and units) and `ContentDocument` (the semantic pivot: a discriminated union of `wordprocessing` and `presentation` variants sharing paragraph/run/table/image building blocks).
107
+ - **`src/bytes/`** and **`src/image/`** — generic byte and image-container primitives with zero PDF or OOXML knowledge: a chunked byte writer, a backtracking byte reader, CRC32, and a hand-written PNG decoder/encoder (palette/gray/RGB/alpha, multi-`IDAT` files, all five scanline filters) plus JPEG marker scanning for dimensions only — JPEG's compressed bytes pass through completely unchanged in both directions. `src/bytes/flate.ts` is the only file that imports `fflate`, mirroring how `ooxml.js`'s own `src/zip.ts` wraps it for ZIP handling.
108
+ - **`src/xml/`** and **`src/opc/`** — parent-aware XML query/mutation and OPC package mechanics (relationship IDs, content-type entries, atomic media-part insertion) built over `ooxml.js`'s `Package`/`XmlNode`, needed because `ooxml.js`'s own XML nodes have no parent pointers and `ooxml.js` never writes new parts into an existing package.
109
+ - **`src/edit/`** — the read-and-write editable model: live-view classes (`DocxEditor`/`DocxParagraph`/`DocxRun`/`DocxTable`, `PptxEditor`/`PptxSlide`/`PptxShape`) wrapping the actual `XmlElement` objects inside a decoded `Package`, plus `buildDocxPackage`/`buildPptxPackage` bridging a `ContentDocument` to a fresh package built entirely through those same primitives.
110
+ - **`src/pdf/`** — the hand-written PDF codec, importing only `model`/`bytes`/`image` (no OOXML knowledge at all):
111
+ - **Write**: `objects.ts` (the `PdfObject` discriminated union), `afm-widths.ts`/`encoding.ts`/`winansi.ts`/`fonts.ts` (standard-14 metrics, WinAnsi encoding, family resolution), `measure.ts`/`text-layout.ts` (greedy line-wrapping), `matrix.ts`, `content-write.ts` (`LayoutItem[]` → content-stream operators), `write.ts` (the full object graph, classic cross-reference table, trailer).
112
+ - **Read**: `lexer.ts`/`parse.ts` (byte tokenizer and tokens → `PdfObject`), `filters.ts`/`predictors.ts` (Flate/LZW/ASCII85/ASCIIHex/RunLength, TIFF/PNG predictors), `xref.ts`/`document.ts` (classic and cross-reference-stream resolution, object streams, `/Prev` chains, linear-scan recovery, the page tree with attribute inheritance), `content-read.ts`/`interpret.ts` (the content-stream tokenizer and graphics/text state machine, including form-XObject recursion), `cmap.ts`/`font-style.ts`/`font-read.ts` (`/ToUnicode` CMaps, font-dictionary resolution), `images-read.ts` (Image XObjects → PNG/JPEG bytes), `read.ts` (`readPdf`, assembling all of the above into a `LayoutDocument`).
113
+ - `codec.ts` — `pdfCodec`, a `z.codec()` pair over `readPdf`/`writePdf` (PDF bytes ⇄ `LayoutDocument`).
114
+ - **`src/ooxml/`** — resolves a `Package` into a `ContentDocument`: `docx/styles.ts` implements the full docx style cascade (`docDefaults` → named-style `basedOn` chains → paragraph-mark run properties → character styles → direct formatting) and `docx/read.ts` walks `word/document.xml`; `pptx/inherit.ts` implements the placeholder → layout → master → theme inheritance cascade (the single highest-value correctness feature for pptx, since most real shapes carry no position of their own) and `pptx/read.ts` walks the slide tree, resolving slide order through the presentation's own relationships rather than filename order.
115
+ - **`src/layout/`** — the pure conversion algorithms, importing only `model` (no I/O): `engine.ts` (`ContentDocument` wordprocessing → `LayoutDocument`: flow, line-breaking, pagination), `slides.ts` (`ContentDocument` presentation → `LayoutDocument`: direct EMU-to-point placement, no pagination needed), `reconstruct.ts` (`LayoutDocument` → `ContentDocument`, both variants: baseline-proximity line clustering, then paragraph/text-block clustering from geometry — PDF has no semantic paragraph or shape structure to recover, only positioned glyphs).
116
+ - **`src/convert/`** — `convert.ts` (the four ergonomic wrappers), `codec.ts` (`docxPdfCodec`/`pptxPdfCodec`, a `z.codec()` pair over each), `port.ts`/`local.ts` (the swappable `DocumentConverter` contract and its synchronous local implementation).
117
+
118
+ Dependency direction is strictly downward and checkable: `model`/`bytes` import nothing local; `image` imports `bytes` only; `pdf` imports `model`+`bytes`+`image` only; `ooxml/*` imports `xml`/`model` only (no PDF knowledge); `layout` imports `model` only; `convert` composes everything else. No `PdfObject`/`PdfDict`/`PdfStream` type appears outside `src/pdf/`.
119
+
120
+ ## Build, test, and lint
28
121
 
29
122
  ```sh
30
123
  pnpm build # tsdown -> dist/ (ESM + CJS + .d.ts)
@@ -32,40 +125,53 @@ pnpm typecheck # tsc --noEmit
32
125
  pnpm lint # eslint . --max-warnings 0
33
126
  pnpm test # vitest run --project unit
34
127
  pnpm test:watch # vitest --project unit
35
- pnpm test:smoke # rebuilds dist/, then verifies ESM/CJS parity
36
- pnpm test:corpus # optional real-world PDF conformance checks against a local, gitignored test/corpus/
128
+ pnpm test:smoke # rebuilds dist/, then verifies ESM/CJS parity and a real docxToPdf/pdfToDocx round trip from the built CJS bundle
129
+ pnpm test:corpus # optional real-world PDF conformance checks against a local, gitignored test/corpus/ (see Fidelity)
37
130
  ```
38
131
 
39
132
  To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
40
133
 
41
- ## Architecture
42
-
43
- The package is layered from a lossless OOXML core (delegated entirely to `ooxml.js`) outward to conversion and editing:
44
-
45
- - **`src/model/`** — Zod schemas only: unit conversions (EMU/twip/point/half-point), geometry, color, and the two pivot models — `LayoutDocument` (the PDF-side pivot: pages of positioned text/image/rect/line/ellipse/link items, PDF-native coordinates) and `ContentDocument` (the semantic pivot: a discriminated union of `wordprocessing` and `presentation` variants sharing paragraph/run/table/image building blocks).
46
- - **`src/bytes/`** and **`src/image/`** — generic byte and image-container primitives (PNG decode/encode, JPEG marker scanning) with zero PDF or OOXML knowledge. `src/bytes/flate.ts` is the only file that imports `fflate`, mirroring how `ooxml.js`'s own `src/zip.ts` wraps `fflate` for ZIP handling.
47
- - **`src/xml/`** and **`src/opc/`** — parent-aware XML query/mutation and OPC package mechanics (relationships, content types, media parts) built over `ooxml.js`'s `Package`/`XmlNode`.
48
- - **`src/edit/`** — the read+write editable model: live-view wrappers over the actual `XmlElement` objects inside a decoded `Package`, so mutations edit the tree in place and untouched content stays byte-faithful on save. This is the novel piece beyond what `ooxml.js` itself provides.
49
- - **`src/pdf/`** — a fully hand-written PDF codec: object model, writer (content-stream generation, standard-14 font metrics, xref table), and reader (tokenizer, cross-reference/object-stream resolution, content-stream interpreter, font/Unicode recovery). No external PDF library.
50
- - **`src/ooxml/`** — resolves a `Package` into a `ContentDocument`: the docx style cascade (`basedOn` chains, theme fonts, toggle properties) and the pptx placeholder→layout→master→theme inheritance cascade.
51
- - **`src/layout/`** — the conversion algorithms: `ContentDocument → LayoutDocument` (docx flow/pagination; pptx direct EMU-to-point placement) and the reverse (`LayoutDocument → ContentDocument`, via line/paragraph/shape clustering).
52
- - **`src/convert/`** — the `DocumentConverter` port/contract and its local adapter, plus the `docxPdfCodec`/`pptxPdfCodec` Zod codecs and ergonomic `docxToPdf`/`pdfToDocx`/`pptxToPdf`/`pdfToPptx` wrappers.
53
-
54
134
  ## Conventions
55
135
 
56
- - **Zod-first schema/type/guard**, matching `ooxml.js`: every model type is inferred from its Zod schema, never hand-written. Recursive types (`ContentBlock`, mirroring `ooxml.js`'s `XmlNode`) use a hand-written structural guard + `z.custom`, not `z.lazy`.
57
- - **No type assertions.** Every third-party or loosely-typed value (from `fast-xml-parser` via `ooxml.js`) is narrowed through a type guard or a Zod parse at the boundary. `src/pdf/`'s own object model narrows natively on its `kind` discriminant, so it needs no such guard.
58
- - **Dependency direction is strictly downward and checkable**: `model`/`bytes` import nothing local; `image` imports `bytes` only; `pdf` imports `model`+`bytes`+`image` only (no OOXML knowledge); `ooxml/*` imports `xml`/`model` only (no PDF knowledge); `layout` imports `model` only (pure, no I/O); `convert` composes everything else. No `PdfObject`/`PdfDict`/`PdfStream` type may appear outside `src/pdf/`.
136
+ - **Zod-first schema/type/guard**, matching `ooxml.js`: every model type is inferred from its Zod schema, never hand-written. `ContentBlock` (recursive, mirroring `ooxml.js`'s own `XmlNode` treatment) uses a hand-written structural guard + `z.custom`, not `z.lazy`, which collapses to `unknown` for recursive element-children in the pinned Zod version.
137
+ - **`z.codec()` for every schema-to-schema round trip**, matching `ooxml.js`'s `packageCodec`/`xmlCodec`: `pdfCodec` (PDF bytes ⇄ `LayoutDocument`) and `docxPdfCodec`/`pptxPdfCodec` (docx/pptx bytes ⇄ PDF bytes) each wrap an already-independently-tested function pair, adding automatic two-way schema validation. These are deliberately the no-options form — `readPdf`/`writePdf`/`docxToPdf`/`pdfToDocx`/`pptxToPdf`/`pdfToPptx` remain the primary entry points wherever a caller needs an `AbortSignal`, a `PdfDiagnosticSink`, or an `onSubstitution` callback, since `z.codec()`'s fixed `decode(input)`/`encode(output)` signature has no room for side-channel options.
138
+ - **`PdfObject` has no Zod schema at all**, deliberately: it never crosses a public boundary or round-trips through JSON, and is constructed exclusively by this package's own parser validating it would just be validating our own output. It narrows natively on its own `kind` discriminant instead, the same reasoning `ooxml.js` applies when it picks a hand-written `isXmlNode` guard over `z.lazy`.
139
+ - **No type assertions anywhere.** Every third-party or loosely-typed value is narrowed through a type guard or a Zod parse at the boundary.
140
+ - **Live views, not flatten-and-regenerate.** `src/edit/*`'s editor classes hold a reference directly into the real `Package`/`XmlElement` objects; saving is `encodePackage(pkg)`, nothing more. This is what makes "everything you didn't touch stays byte-faithful" a structural guarantee rather than a best effort.
141
+ - **A three-tier PDF-read failure policy**, applied consistently across every `src/pdf/*` read module: throw a typed `PdfParseError`/`PdfEncryptedError` for a file that cannot be meaningfully processed at all; recover with a `PdfDiagnostic` (`severity: 'warning'`) for something malformed but salvageable (a bad `startxref`, a wrong stream `/Length`); degrade with a diagnostic for an individual unsupported feature (an unimplemented filter, an unrecognised colour space) while the rest of the document still reads.
59
142
  - **Conventional commits**, enforced via commitlint + husky, matching `ooxml.js`.
60
143
 
61
144
  ## Gotchas and quirks
62
145
 
63
- - **`ooxml.js`'s typed readers (`readDocx`/`readPptx`) are not used as a basis for conversion.** They flatten body content with a recursive-descendant search (destroying document order for paragraphs inside tables) and carry no font/size/color/geometry data. `documents.js` walks `word/document.xml`/`ppt/slides/slideN.xml` directly.
64
- - **The docx⇄pdf and pptx⇄pdf conversion codecs are explicitly not round-trip-lossless** — in deliberate contrast to `ooxml.js`'s own `packageCodec`, which is. A `z.codec()` here means a validated, named pair of format-*converting* transforms, not a lossless round-trip guarantee.
65
- - **PDF output uses standard-14 fonts only (no embedding).** Helvetica/Times-Roman are metric-compatible substitutes for Arial/Times New Roman, but Word's actual default fonts (Calibri, Aptos) are not expect a faithful visual approximation, not a line-identical reproduction of Word/PowerPoint's own rendering.
66
- - **Reading arbitrary real-world PDFs is the hardest part of this package.** The hand-written parser targets cleanly-generated output from mainstream producers (Word, PowerPoint, Chrome, LibreOffice, Acrobat) and fails loudly and specifically on adversarial or badly malformed files, rather than matching a mature library's robustness.
67
- - **Encrypted PDFs are unsupported** (`/Encrypt` present throws), including the common empty-user-password case.
68
- - **JPEG images pass through losslessly** (embedded/extracted via PDF's `DCTDecode` filter with no decode/re-encode); PNG-sourced images go through a real, narrowly-scoped hand-written codec.
146
+ - **`ooxml.js`'s typed readers (`readDocx`/`readPptx`) are not used as a basis for conversion, and are deliberately not re-exported from this package's own public surface.** They flatten body content with a recursive-descendant search (destroying document order for paragraphs inside tables) and carry no font/size/colour/geometry data. `documents.js` walks `word/document.xml`/`ppt/slides/slideN.xml` directly, and exposing both `ContentDocument` and `ooxml.js`'s typed readers in one API would be a trap — two competing, differently-lossy document models.
147
+ - **The docx⇄PDF and pptx⇄PDF conversions are explicitly not round-trip-lossless** — in deliberate contrast to `ooxml.js`'s own `packageCodec`, which is byte/part-faithful by design. See [Fidelity](#fidelity).
148
+ - **PDF output uses the standard 14 fonts only no font embedding.** Helvetica/Times-Roman are genuinely metric-compatible substitutes for Arial/Times New Roman, but Word's actual current defaults (Calibri, Aptos) are not, so line wrapping and pagination will drift slightly from what Word itself would produce. Expect a faithful visual approximation, not a line-identical reproduction.
149
+ - **Reading arbitrary real-world PDFs is the single largest risk surface in this package**, and the parser is honest about its design target: cleanly-generated output from mainstream producers (Word, PowerPoint, Chrome, LibreOffice, Acrobat), recovering from the malformations those producers and their downstream tooling actually create, and failing loudly and specifically on anything else not matching a mature library's robustness against adversarial input.
150
+ - **Encrypted PDFs are unsupported.** `/Encrypt` present in the trailer throws `PdfEncryptedError`, even for the common empty-user-password case.
151
+ - **`CCITTFaxDecode`/`JBIG2Decode`/`JPXDecode` PDF images are unsupported** (scanned-fax and JPEG2000 formats) — the image is skipped with a diagnostic, the rest of the page still reads. JPEG images (`DCTDecode`) pass through completely losslessly in both directions; PNG-sourced images go through a real, narrowly-scoped hand-written codec.
152
+ - **PDF → docx/pptx reconstruction has no table or vector-shape recovery.** A PDF has no semantic table structure to recover — a wide horizontal gap on a line becomes a tab character, not a reconstructed grid. General vector paths, curves, gradients, and shadings are not recovered either.
153
+ - **Table cell `colSpan`/`rowSpan` and pptx shape rotation are read from a `ContentDocument` but not yet written back** by `buildDocxPackage`/`buildPptxPackage` — a merged cell round-trips as an ordinary unmerged one, and a rotated shape round-trips unrotated. Both are bounded, tracked gaps (the cell's own text content and the shape's own position are still correct), not silent ones.
154
+ - **docx headers/footers, live `PAGE`/`NUMPAGES` field substitution, and inline images are not read** by `readDocxContent` — a deliberate, tracked scope narrowing from the original design, not an oversight.
155
+
156
+ ## Fidelity
157
+
158
+ **docx/pptx → PDF** is a genuine layout render: the docx flow/pagination engine and the pptx direct-placement engine both produce real positioned text, images, tables, and (for docx) numbered/bulleted lists, styled through the full cascade (theme fonts/colours, `basedOn` chains, placeholder inheritance). It is a faithful **visual approximation**, not a pixel- or line-identical reproduction of what Word/PowerPoint would themselves render — see the standard-14 font substitution gotcha above.
159
+
160
+ **PDF → docx/pptx** is necessarily a **best-effort reconstruction** from geometry: a PDF page is just positioned glyphs and images, with no semantic paragraph or shape structure to recover. Reading order, bold/italic/colour/font-size, and page/slide count are preserved; paragraph and text-block boundaries are inferred from baseline spacing and left-margin indentation, not recovered exactly.
161
+
162
+ Neither direction is round-trip-lossless, and the two conversions are not inverses of each other — `pdfToDocx(docxToPdf(x))` will not reproduce `x` exactly, and is not intended to. This is a deliberate, permanent contrast with `ooxml.js`'s own `packageCodec`, which genuinely is a lossless round trip. `docxPdfCodec`/`pptxPdfCodec`/`pdfCodec` share `packageCodec`'s *mechanism* (`z.codec()`, schema-validated both ways) but not its *guarantee* — wrapping a lossy conversion in `z.codec()` validates the shape of what comes out, not its fidelity to what went in.
163
+
164
+ **Optional real-world corpus.** `test/corpus/` (gitignored, never committed) holds a `pnpm test:corpus` vitest project for manual conformance checking against real PDFs a hand-built fixture can't fully stand in for — a Word "Save as PDF", a PowerPoint "Save as PDF", a Chrome "Print to PDF", a LibreOffice export. It is not part of `pnpm test` and does not gate CI; drop files in locally before a significant parser change.
165
+
166
+ ## Release and publishing
167
+
168
+ `.github/workflows/ci.yml` runs commitlint, lint, typecheck, the unit suite, and the smoke test on every push and pull request. On a push to `main` where those all pass, `release.config.ts` drives [semantic-release](https://semantic-release.gitbook.io/semantic-release): commit history since the last tag decides the version bump, `CHANGELOG.md` and `package.json` are committed back to `main`, a GitHub Release is cut, and the package publishes to [npmjs.org](https://www.npmjs.com/package/documents.js) — via npm's OIDC trusted publishing, so no `NPM_TOKEN` exists anywhere in the pipeline.
169
+
170
+ Whether that release actually published a new version is detected by diffing `package.json`'s version before and after the release step, not by trusting a third-party action's own detection. Two further jobs gate on that: one republishes the same build under the scoped `@exadev/documents.js` alias to GitHub Packages (which has no OIDC exchange of its own, so it authenticates with `GITHUB_TOKEN` instead), and one packs the release into its own directory, generates an SPDX SBOM (`pnpm sbom`), and signs both an SBOM and a build-provenance attestation against that exact tarball — verifiable independently of the registry, and still present if the package is later unpublished.
171
+
172
+ ## Contributing
173
+
174
+ Commits follow Conventional Commits (`feat:`, `fix:`, `test:`, `chore:`, …), enforced by commitlint (`commitlint.config.ts`) via a husky `commit-msg` hook and a CI `commitlint` job — semantic-release's version bump depends on these being well-formed, not just style. A husky `pre-commit` hook runs `lint-staged` (`eslint --fix` on staged `*.ts` files) and `pre-push` runs the test suite. There is a single `main` branch and no open pull request workflow established so far.
69
175
 
70
176
  ## References
71
177
 
package/dist/index.cjs CHANGED
@@ -270,7 +270,7 @@ const LayoutMetadataSchema = zod.z.object({
270
270
  createdIso: zod.z.string().optional(),
271
271
  modifiedIso: zod.z.string().optional()
272
272
  });
273
- zod.z.object({
273
+ const LayoutDocumentSchema = zod.z.object({
274
274
  formatVersion: zod.z.literal(1),
275
275
  metadata: LayoutMetadataSchema,
276
276
  pages: zod.z.array(LayoutPageSchema),
@@ -386,6 +386,45 @@ const ContentDocumentSchema = zod.z.discriminatedUnion("kind", [zod.z.object({
386
386
  slides: zod.z.array(ContentSlideSchema)
387
387
  })]);
388
388
  //#endregion
389
+ //#region src/model/bytes.ts
390
+ const ZIP_LOCAL_FILE_HEADER = [
391
+ 80,
392
+ 75,
393
+ 3,
394
+ 4
395
+ ];
396
+ const PDF_HEADER = [
397
+ 37,
398
+ 80,
399
+ 68,
400
+ 70,
401
+ 45
402
+ ];
403
+ const PDF_HEADER_SEARCH_WINDOW = 1024;
404
+ function startsWithBytes(bytes, signature) {
405
+ if (bytes.length < signature.length) return false;
406
+ for (let i = 0; i < signature.length; i++) if (bytes[i] !== signature[i]) return false;
407
+ return true;
408
+ }
409
+ function containsBytesWithin(bytes, signature, window) {
410
+ const limit = Math.min(bytes.length - signature.length, window);
411
+ for (let start = 0; start <= limit; start++) {
412
+ let matched = true;
413
+ for (let i = 0; i < signature.length; i++) if (bytes[start + i] !== signature[i]) {
414
+ matched = false;
415
+ break;
416
+ }
417
+ if (matched) return true;
418
+ }
419
+ return false;
420
+ }
421
+ function zipBytesSchema(label) {
422
+ return zod.z.instanceof(Uint8Array).refine((bytes) => startsWithBytes(bytes, ZIP_LOCAL_FILE_HEADER), { message: `not a valid ${label} file: missing the ZIP local-file-header signature` });
423
+ }
424
+ const DocxBytesSchema = zipBytesSchema("docx");
425
+ const PptxBytesSchema = zipBytesSchema("pptx");
426
+ const PdfBytesSchema = zod.z.instanceof(Uint8Array).refine((bytes) => containsBytesWithin(bytes, PDF_HEADER, PDF_HEADER_SEARCH_WINDOW), { message: "not a valid PDF file: missing the %PDF- header" });
427
+ //#endregion
389
428
  //#region src/xml/fragment.ts
390
429
  function el(tag, attrs = {}, children = []) {
391
430
  return {
@@ -6737,6 +6776,12 @@ function writePdf(doc, options = {}) {
6737
6776
  return writer.toBytes();
6738
6777
  }
6739
6778
  //#endregion
6779
+ //#region src/pdf/codec.ts
6780
+ const pdfCodec = zod.z.codec(PdfBytesSchema, LayoutDocumentSchema, {
6781
+ decode: (bytes) => readPdf(bytes),
6782
+ encode: (doc) => writePdf(doc)
6783
+ });
6784
+ //#endregion
6740
6785
  //#region src/ooxml/core-properties.ts
6741
6786
  const CORE_PROPERTIES_PATH = "docProps/core.xml";
6742
6787
  const APP_PROPERTIES_PATH = "docProps/app.xml";
@@ -8782,6 +8827,16 @@ function pdfToPptx(bytes, options) {
8782
8827
  return (0, ooxml_js.encodePackage)(buildPptxPackage(content));
8783
8828
  }
8784
8829
  //#endregion
8830
+ //#region src/convert/codec.ts
8831
+ const docxPdfCodec = zod.z.codec(DocxBytesSchema, PdfBytesSchema, {
8832
+ decode: (docxBytes) => docxToPdf(docxBytes),
8833
+ encode: (pdfBytes) => pdfToDocx(pdfBytes)
8834
+ });
8835
+ const pptxPdfCodec = zod.z.codec(PptxBytesSchema, PdfBytesSchema, {
8836
+ decode: (pptxBytes) => pptxToPdf(pptxBytes),
8837
+ encode: (pdfBytes) => pdfToPptx(pdfBytes)
8838
+ });
8839
+ //#endregion
8785
8840
  //#region src/convert/local.ts
8786
8841
  const SUPPORTED_CONVERSIONS = [
8787
8842
  {
@@ -8944,6 +8999,7 @@ Object.defineProperty(exports, "DefinedNameSchema", {
8944
8999
  return ooxml_js.DefinedNameSchema;
8945
9000
  }
8946
9001
  });
9002
+ exports.DocxBytesSchema = DocxBytesSchema;
8947
9003
  exports.DocxEditor = DocxEditor;
8948
9004
  exports.DocxParagraph = DocxParagraph;
8949
9005
  exports.DocxRun = DocxRun;
@@ -8966,8 +9022,10 @@ Object.defineProperty(exports, "PartSchema", {
8966
9022
  return ooxml_js.PartSchema;
8967
9023
  }
8968
9024
  });
9025
+ exports.PdfBytesSchema = PdfBytesSchema;
8969
9026
  exports.PdfEncryptedError = PdfEncryptedError;
8970
9027
  exports.PdfParseError = PdfParseError;
9028
+ exports.PptxBytesSchema = PptxBytesSchema;
8971
9029
  exports.PptxEditor = PptxEditor;
8972
9030
  exports.PptxShape = PptxShape;
8973
9031
  exports.PptxSlide = PptxSlide;
@@ -9088,6 +9146,7 @@ Object.defineProperty(exports, "decodePackage", {
9088
9146
  return ooxml_js.decodePackage;
9089
9147
  }
9090
9148
  });
9149
+ exports.docxPdfCodec = docxPdfCodec;
9091
9150
  exports.docxToPdf = docxToPdf;
9092
9151
  Object.defineProperty(exports, "elementsWithTag", {
9093
9152
  enumerable: true,
@@ -9148,8 +9207,10 @@ Object.defineProperty(exports, "parseXml", {
9148
9207
  return ooxml_js.parseXml;
9149
9208
  }
9150
9209
  });
9210
+ exports.pdfCodec = pdfCodec;
9151
9211
  exports.pdfToDocx = pdfToDocx;
9152
9212
  exports.pdfToPptx = pdfToPptx;
9213
+ exports.pptxPdfCodec = pptxPdfCodec;
9153
9214
  exports.pptxToPdf = pptxToPdf;
9154
9215
  exports.readDocxContent = readDocxContent;
9155
9216
  exports.readPdf = readPdf;
package/dist/index.d.cts CHANGED
@@ -745,6 +745,11 @@ declare const AlignmentSchema: z.ZodEnum<{
745
745
  }>;
746
746
  type Alignment = z.infer<typeof AlignmentSchema>;
747
747
  //#endregion
748
+ //#region src/model/bytes.d.ts
749
+ declare const DocxBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
750
+ declare const PptxBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
751
+ declare const PdfBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
752
+ //#endregion
748
753
  //#region src/edit/docx/image.d.ts
749
754
  interface ImageInit$1 {
750
755
  readonly format: 'png' | 'jpeg';
@@ -1002,6 +1007,125 @@ interface WritePdfOptions {
1002
1007
  }
1003
1008
  declare function writePdf(doc: LayoutDocument, options?: WritePdfOptions): Uint8Array<ArrayBuffer>;
1004
1009
  //#endregion
1010
+ //#region src/pdf/codec.d.ts
1011
+ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodObject<{
1012
+ formatVersion: z.ZodLiteral<1>;
1013
+ metadata: z.ZodObject<{
1014
+ title: z.ZodOptional<z.ZodString>;
1015
+ author: z.ZodOptional<z.ZodString>;
1016
+ subject: z.ZodOptional<z.ZodString>;
1017
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
1018
+ creator: z.ZodOptional<z.ZodString>;
1019
+ producer: z.ZodOptional<z.ZodString>;
1020
+ createdIso: z.ZodOptional<z.ZodString>;
1021
+ modifiedIso: z.ZodOptional<z.ZodString>;
1022
+ }, z.core.$strip>;
1023
+ pages: z.ZodArray<z.ZodObject<{
1024
+ widthPt: z.ZodNumber;
1025
+ heightPt: z.ZodNumber;
1026
+ items: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
1027
+ kind: z.ZodLiteral<"text">;
1028
+ text: z.ZodString;
1029
+ xPt: z.ZodNumber;
1030
+ yPt: z.ZodNumber;
1031
+ font: z.ZodObject<{
1032
+ family: z.ZodString;
1033
+ weight: z.ZodEnum<{
1034
+ bold: "bold";
1035
+ normal: "normal";
1036
+ }>;
1037
+ style: z.ZodEnum<{
1038
+ italic: "italic";
1039
+ normal: "normal";
1040
+ }>;
1041
+ }, z.core.$strip>;
1042
+ sizePt: z.ZodNumber;
1043
+ color: z.ZodObject<{
1044
+ r: z.ZodNumber;
1045
+ g: z.ZodNumber;
1046
+ b: z.ZodNumber;
1047
+ }, z.core.$strip>;
1048
+ widthPt: z.ZodOptional<z.ZodNumber>;
1049
+ rotationDeg: z.ZodOptional<z.ZodNumber>;
1050
+ underline: z.ZodOptional<z.ZodBoolean>;
1051
+ }, z.core.$strip>, z.ZodObject<{
1052
+ kind: z.ZodLiteral<"image">;
1053
+ imageId: z.ZodString;
1054
+ xPt: z.ZodNumber;
1055
+ yPt: z.ZodNumber;
1056
+ widthPt: z.ZodNumber;
1057
+ heightPt: z.ZodNumber;
1058
+ rotationDeg: z.ZodOptional<z.ZodNumber>;
1059
+ }, z.core.$strip>, z.ZodObject<{
1060
+ kind: z.ZodLiteral<"rect">;
1061
+ xPt: z.ZodNumber;
1062
+ yPt: z.ZodNumber;
1063
+ widthPt: z.ZodNumber;
1064
+ heightPt: z.ZodNumber;
1065
+ fill: z.ZodOptional<z.ZodObject<{
1066
+ r: z.ZodNumber;
1067
+ g: z.ZodNumber;
1068
+ b: z.ZodNumber;
1069
+ }, z.core.$strip>>;
1070
+ stroke: z.ZodOptional<z.ZodObject<{
1071
+ color: z.ZodObject<{
1072
+ r: z.ZodNumber;
1073
+ g: z.ZodNumber;
1074
+ b: z.ZodNumber;
1075
+ }, z.core.$strip>;
1076
+ widthPt: z.ZodNumber;
1077
+ }, z.core.$strip>>;
1078
+ }, z.core.$strip>, z.ZodObject<{
1079
+ kind: z.ZodLiteral<"line">;
1080
+ x1Pt: z.ZodNumber;
1081
+ y1Pt: z.ZodNumber;
1082
+ x2Pt: z.ZodNumber;
1083
+ y2Pt: z.ZodNumber;
1084
+ color: z.ZodObject<{
1085
+ r: z.ZodNumber;
1086
+ g: z.ZodNumber;
1087
+ b: z.ZodNumber;
1088
+ }, z.core.$strip>;
1089
+ widthPt: z.ZodNumber;
1090
+ }, z.core.$strip>, z.ZodObject<{
1091
+ kind: z.ZodLiteral<"ellipse">;
1092
+ xPt: z.ZodNumber;
1093
+ yPt: z.ZodNumber;
1094
+ widthPt: z.ZodNumber;
1095
+ heightPt: z.ZodNumber;
1096
+ fill: z.ZodOptional<z.ZodObject<{
1097
+ r: z.ZodNumber;
1098
+ g: z.ZodNumber;
1099
+ b: z.ZodNumber;
1100
+ }, z.core.$strip>>;
1101
+ stroke: z.ZodOptional<z.ZodObject<{
1102
+ color: z.ZodObject<{
1103
+ r: z.ZodNumber;
1104
+ g: z.ZodNumber;
1105
+ b: z.ZodNumber;
1106
+ }, z.core.$strip>;
1107
+ widthPt: z.ZodNumber;
1108
+ }, z.core.$strip>>;
1109
+ }, z.core.$strip>, z.ZodObject<{
1110
+ kind: z.ZodLiteral<"link">;
1111
+ uri: z.ZodString;
1112
+ xPt: z.ZodNumber;
1113
+ yPt: z.ZodNumber;
1114
+ widthPt: z.ZodNumber;
1115
+ heightPt: z.ZodNumber;
1116
+ }, z.core.$strip>], "kind">>;
1117
+ }, z.core.$strip>>;
1118
+ images: z.ZodRecord<z.ZodString, z.ZodObject<{
1119
+ format: z.ZodEnum<{
1120
+ png: "png";
1121
+ jpeg: "jpeg";
1122
+ }>;
1123
+ base64: z.ZodString;
1124
+ widthPx: z.ZodNumber;
1125
+ heightPx: z.ZodNumber;
1126
+ }, z.core.$strip>>;
1127
+ }, z.core.$strip>>;
1128
+ //#endregion
1005
1129
  //#region src/ooxml/docx/read.d.ts
1006
1130
  declare function readDocxContent(pkg: Package$1): ContentDocument;
1007
1131
  //#endregion
@@ -1063,6 +1187,10 @@ interface PdfToDocumentOptions {
1063
1187
  declare function pdfToDocx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1064
1188
  declare function pdfToPptx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1065
1189
  //#endregion
1190
+ //#region src/convert/codec.d.ts
1191
+ declare const docxPdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>;
1192
+ declare const pptxPdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>;
1193
+ //#endregion
1066
1194
  //#region src/convert/port.d.ts
1067
1195
  type DocumentFormat = 'docx' | 'pptx' | 'pdf';
1068
1196
  interface DocumentPayload {
@@ -1107,4 +1235,4 @@ declare function fixedClock(date: Date): ClockPort;
1107
1235
  //#region src/ports/abort.d.ts
1108
1236
  declare function throwIfAborted(signal: AbortSignal | undefined): void;
1109
1237
  //#endregion
1110
- export { type Alignment, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Box, COLOR_BLACK, CONTENT_FORMAT_VERSION, type ClockPort, type Comment, CommentSchema, type CompactAttrPairs, type CompactPackage, CompactPackageSchema, type CompactPart, CompactPartSchema, type CompactXmlNode, CompactXmlNodeSchema, type ContentBlock, ContentBlockSchema, type ContentDocument, ContentDocumentSchema, type ContentImageBlock, ContentImageBlockSchema, type ContentListMembership, type ContentPageBreak, ContentPageBreakSchema, type ContentParagraph, ContentParagraphSchema, type ContentRun, ContentRunSchema, type ContentSection, ContentSectionSchema, type ContentShape, ContentShapeSchema, type ContentSlide, ContentSlideSchema, type ContentTable, type ContentTableCell, ContentTableCellSchema, type ContentTableRow, ContentTableRowSchema, ContentTableSchema, type ConversionRequest, type ConversionResult, DEFAULT_LAYOUT_FONT, type DefinedName, DefinedNameSchema, type Diagnostic, type DocumentConverter, type DocumentFormat, type DocumentPayload, type DocumentToPdfOptions, type DocxBody, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, type DrawingParagraphInit, type DrawingRunInit, type EngineLayoutOptions, LAYOUT_FORMAT_VERSION, type LayoutColor, type LayoutDocument, type LayoutEllipse, type LayoutFont, type LayoutImage, type LayoutImageAsset, type LayoutItem, type LayoutLine, type LayoutLink, type LayoutMetadata, type LayoutPage, type LayoutRect, type LayoutText, type Margins, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, type Package, PackageSchema, type PageSize, type Part, PartSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfParseError, type PdfToDocumentOptions, PptxEditor, PptxShape, PptxSlide, type ReadPdfOptions, type ReconstructOptions, type Relationship, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, type SlideImageInit, type SlidesLayoutOptions, type TextBoxInit, type WinAnsiSubstitution, type WritePdfOptions, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfToDocx, pdfToPptx, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
1238
+ export { type Alignment, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Box, COLOR_BLACK, CONTENT_FORMAT_VERSION, type ClockPort, type Comment, CommentSchema, type CompactAttrPairs, type CompactPackage, CompactPackageSchema, type CompactPart, CompactPartSchema, type CompactXmlNode, CompactXmlNodeSchema, type ContentBlock, ContentBlockSchema, type ContentDocument, ContentDocumentSchema, type ContentImageBlock, ContentImageBlockSchema, type ContentListMembership, type ContentPageBreak, ContentPageBreakSchema, type ContentParagraph, ContentParagraphSchema, type ContentRun, ContentRunSchema, type ContentSection, ContentSectionSchema, type ContentShape, ContentShapeSchema, type ContentSlide, ContentSlideSchema, type ContentTable, type ContentTableCell, ContentTableCellSchema, type ContentTableRow, ContentTableRowSchema, ContentTableSchema, type ConversionRequest, type ConversionResult, DEFAULT_LAYOUT_FONT, type DefinedName, DefinedNameSchema, type Diagnostic, type DocumentConverter, type DocumentFormat, type DocumentPayload, type DocumentToPdfOptions, type DocxBody, DocxBytesSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, type DrawingParagraphInit, type DrawingRunInit, type EngineLayoutOptions, LAYOUT_FORMAT_VERSION, type LayoutColor, type LayoutDocument, type LayoutEllipse, type LayoutFont, type LayoutImage, type LayoutImageAsset, type LayoutItem, type LayoutLine, type LayoutLink, type LayoutMetadata, type LayoutPage, type LayoutRect, type LayoutText, type Margins, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, type Package, PackageSchema, type PageSize, type Part, PartSchema, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfParseError, type PdfToDocumentOptions, PptxBytesSchema, PptxEditor, PptxShape, PptxSlide, type ReadPdfOptions, type ReconstructOptions, type Relationship, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, type SlideImageInit, type SlidesLayoutOptions, type TextBoxInit, type WinAnsiSubstitution, type WritePdfOptions, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxPdfCodec, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfCodec, pdfToDocx, pdfToPptx, pptxPdfCodec, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
package/dist/index.d.ts CHANGED
@@ -745,6 +745,11 @@ declare const AlignmentSchema: z.ZodEnum<{
745
745
  }>;
746
746
  type Alignment = z.infer<typeof AlignmentSchema>;
747
747
  //#endregion
748
+ //#region src/model/bytes.d.ts
749
+ declare const DocxBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
750
+ declare const PptxBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
751
+ declare const PdfBytesSchema: z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>;
752
+ //#endregion
748
753
  //#region src/edit/docx/image.d.ts
749
754
  interface ImageInit$1 {
750
755
  readonly format: 'png' | 'jpeg';
@@ -1002,6 +1007,125 @@ interface WritePdfOptions {
1002
1007
  }
1003
1008
  declare function writePdf(doc: LayoutDocument, options?: WritePdfOptions): Uint8Array<ArrayBuffer>;
1004
1009
  //#endregion
1010
+ //#region src/pdf/codec.d.ts
1011
+ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodObject<{
1012
+ formatVersion: z.ZodLiteral<1>;
1013
+ metadata: z.ZodObject<{
1014
+ title: z.ZodOptional<z.ZodString>;
1015
+ author: z.ZodOptional<z.ZodString>;
1016
+ subject: z.ZodOptional<z.ZodString>;
1017
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
1018
+ creator: z.ZodOptional<z.ZodString>;
1019
+ producer: z.ZodOptional<z.ZodString>;
1020
+ createdIso: z.ZodOptional<z.ZodString>;
1021
+ modifiedIso: z.ZodOptional<z.ZodString>;
1022
+ }, z.core.$strip>;
1023
+ pages: z.ZodArray<z.ZodObject<{
1024
+ widthPt: z.ZodNumber;
1025
+ heightPt: z.ZodNumber;
1026
+ items: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
1027
+ kind: z.ZodLiteral<"text">;
1028
+ text: z.ZodString;
1029
+ xPt: z.ZodNumber;
1030
+ yPt: z.ZodNumber;
1031
+ font: z.ZodObject<{
1032
+ family: z.ZodString;
1033
+ weight: z.ZodEnum<{
1034
+ bold: "bold";
1035
+ normal: "normal";
1036
+ }>;
1037
+ style: z.ZodEnum<{
1038
+ italic: "italic";
1039
+ normal: "normal";
1040
+ }>;
1041
+ }, z.core.$strip>;
1042
+ sizePt: z.ZodNumber;
1043
+ color: z.ZodObject<{
1044
+ r: z.ZodNumber;
1045
+ g: z.ZodNumber;
1046
+ b: z.ZodNumber;
1047
+ }, z.core.$strip>;
1048
+ widthPt: z.ZodOptional<z.ZodNumber>;
1049
+ rotationDeg: z.ZodOptional<z.ZodNumber>;
1050
+ underline: z.ZodOptional<z.ZodBoolean>;
1051
+ }, z.core.$strip>, z.ZodObject<{
1052
+ kind: z.ZodLiteral<"image">;
1053
+ imageId: z.ZodString;
1054
+ xPt: z.ZodNumber;
1055
+ yPt: z.ZodNumber;
1056
+ widthPt: z.ZodNumber;
1057
+ heightPt: z.ZodNumber;
1058
+ rotationDeg: z.ZodOptional<z.ZodNumber>;
1059
+ }, z.core.$strip>, z.ZodObject<{
1060
+ kind: z.ZodLiteral<"rect">;
1061
+ xPt: z.ZodNumber;
1062
+ yPt: z.ZodNumber;
1063
+ widthPt: z.ZodNumber;
1064
+ heightPt: z.ZodNumber;
1065
+ fill: z.ZodOptional<z.ZodObject<{
1066
+ r: z.ZodNumber;
1067
+ g: z.ZodNumber;
1068
+ b: z.ZodNumber;
1069
+ }, z.core.$strip>>;
1070
+ stroke: z.ZodOptional<z.ZodObject<{
1071
+ color: z.ZodObject<{
1072
+ r: z.ZodNumber;
1073
+ g: z.ZodNumber;
1074
+ b: z.ZodNumber;
1075
+ }, z.core.$strip>;
1076
+ widthPt: z.ZodNumber;
1077
+ }, z.core.$strip>>;
1078
+ }, z.core.$strip>, z.ZodObject<{
1079
+ kind: z.ZodLiteral<"line">;
1080
+ x1Pt: z.ZodNumber;
1081
+ y1Pt: z.ZodNumber;
1082
+ x2Pt: z.ZodNumber;
1083
+ y2Pt: z.ZodNumber;
1084
+ color: z.ZodObject<{
1085
+ r: z.ZodNumber;
1086
+ g: z.ZodNumber;
1087
+ b: z.ZodNumber;
1088
+ }, z.core.$strip>;
1089
+ widthPt: z.ZodNumber;
1090
+ }, z.core.$strip>, z.ZodObject<{
1091
+ kind: z.ZodLiteral<"ellipse">;
1092
+ xPt: z.ZodNumber;
1093
+ yPt: z.ZodNumber;
1094
+ widthPt: z.ZodNumber;
1095
+ heightPt: z.ZodNumber;
1096
+ fill: z.ZodOptional<z.ZodObject<{
1097
+ r: z.ZodNumber;
1098
+ g: z.ZodNumber;
1099
+ b: z.ZodNumber;
1100
+ }, z.core.$strip>>;
1101
+ stroke: z.ZodOptional<z.ZodObject<{
1102
+ color: z.ZodObject<{
1103
+ r: z.ZodNumber;
1104
+ g: z.ZodNumber;
1105
+ b: z.ZodNumber;
1106
+ }, z.core.$strip>;
1107
+ widthPt: z.ZodNumber;
1108
+ }, z.core.$strip>>;
1109
+ }, z.core.$strip>, z.ZodObject<{
1110
+ kind: z.ZodLiteral<"link">;
1111
+ uri: z.ZodString;
1112
+ xPt: z.ZodNumber;
1113
+ yPt: z.ZodNumber;
1114
+ widthPt: z.ZodNumber;
1115
+ heightPt: z.ZodNumber;
1116
+ }, z.core.$strip>], "kind">>;
1117
+ }, z.core.$strip>>;
1118
+ images: z.ZodRecord<z.ZodString, z.ZodObject<{
1119
+ format: z.ZodEnum<{
1120
+ png: "png";
1121
+ jpeg: "jpeg";
1122
+ }>;
1123
+ base64: z.ZodString;
1124
+ widthPx: z.ZodNumber;
1125
+ heightPx: z.ZodNumber;
1126
+ }, z.core.$strip>>;
1127
+ }, z.core.$strip>>;
1128
+ //#endregion
1005
1129
  //#region src/ooxml/docx/read.d.ts
1006
1130
  declare function readDocxContent(pkg: Package$1): ContentDocument;
1007
1131
  //#endregion
@@ -1063,6 +1187,10 @@ interface PdfToDocumentOptions {
1063
1187
  declare function pdfToDocx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1064
1188
  declare function pdfToPptx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1065
1189
  //#endregion
1190
+ //#region src/convert/codec.d.ts
1191
+ declare const docxPdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>;
1192
+ declare const pptxPdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>, z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Array<ArrayBuffer>>>;
1193
+ //#endregion
1066
1194
  //#region src/convert/port.d.ts
1067
1195
  type DocumentFormat = 'docx' | 'pptx' | 'pdf';
1068
1196
  interface DocumentPayload {
@@ -1107,4 +1235,4 @@ declare function fixedClock(date: Date): ClockPort;
1107
1235
  //#region src/ports/abort.d.ts
1108
1236
  declare function throwIfAborted(signal: AbortSignal | undefined): void;
1109
1237
  //#endregion
1110
- export { type Alignment, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Box, COLOR_BLACK, CONTENT_FORMAT_VERSION, type ClockPort, type Comment, CommentSchema, type CompactAttrPairs, type CompactPackage, CompactPackageSchema, type CompactPart, CompactPartSchema, type CompactXmlNode, CompactXmlNodeSchema, type ContentBlock, ContentBlockSchema, type ContentDocument, ContentDocumentSchema, type ContentImageBlock, ContentImageBlockSchema, type ContentListMembership, type ContentPageBreak, ContentPageBreakSchema, type ContentParagraph, ContentParagraphSchema, type ContentRun, ContentRunSchema, type ContentSection, ContentSectionSchema, type ContentShape, ContentShapeSchema, type ContentSlide, ContentSlideSchema, type ContentTable, type ContentTableCell, ContentTableCellSchema, type ContentTableRow, ContentTableRowSchema, ContentTableSchema, type ConversionRequest, type ConversionResult, DEFAULT_LAYOUT_FONT, type DefinedName, DefinedNameSchema, type Diagnostic, type DocumentConverter, type DocumentFormat, type DocumentPayload, type DocumentToPdfOptions, type DocxBody, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, type DrawingParagraphInit, type DrawingRunInit, type EngineLayoutOptions, LAYOUT_FORMAT_VERSION, type LayoutColor, type LayoutDocument, type LayoutEllipse, type LayoutFont, type LayoutImage, type LayoutImageAsset, type LayoutItem, type LayoutLine, type LayoutLink, type LayoutMetadata, type LayoutPage, type LayoutRect, type LayoutText, type Margins, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, type Package, PackageSchema, type PageSize, type Part, PartSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfParseError, type PdfToDocumentOptions, PptxEditor, PptxShape, PptxSlide, type ReadPdfOptions, type ReconstructOptions, type Relationship, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, type SlideImageInit, type SlidesLayoutOptions, type TextBoxInit, type WinAnsiSubstitution, type WritePdfOptions, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfToDocx, pdfToPptx, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
1238
+ export { type Alignment, type Attribute, AttributeSchema, type BinaryPart, BinaryPartSchema, type Box, COLOR_BLACK, CONTENT_FORMAT_VERSION, type ClockPort, type Comment, CommentSchema, type CompactAttrPairs, type CompactPackage, CompactPackageSchema, type CompactPart, CompactPartSchema, type CompactXmlNode, CompactXmlNodeSchema, type ContentBlock, ContentBlockSchema, type ContentDocument, ContentDocumentSchema, type ContentImageBlock, ContentImageBlockSchema, type ContentListMembership, type ContentPageBreak, ContentPageBreakSchema, type ContentParagraph, ContentParagraphSchema, type ContentRun, ContentRunSchema, type ContentSection, ContentSectionSchema, type ContentShape, ContentShapeSchema, type ContentSlide, ContentSlideSchema, type ContentTable, type ContentTableCell, ContentTableCellSchema, type ContentTableRow, ContentTableRowSchema, ContentTableSchema, type ConversionRequest, type ConversionResult, DEFAULT_LAYOUT_FONT, type DefinedName, DefinedNameSchema, type Diagnostic, type DocumentConverter, type DocumentFormat, type DocumentPayload, type DocumentToPdfOptions, type DocxBody, DocxBytesSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, type DrawingParagraphInit, type DrawingRunInit, type EngineLayoutOptions, LAYOUT_FORMAT_VERSION, type LayoutColor, type LayoutDocument, type LayoutEllipse, type LayoutFont, type LayoutImage, type LayoutImageAsset, type LayoutItem, type LayoutLine, type LayoutLink, type LayoutMetadata, type LayoutPage, type LayoutRect, type LayoutText, type Margins, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, type Package, PackageSchema, type PageSize, type Part, PartSchema, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfParseError, type PdfToDocumentOptions, PptxBytesSchema, PptxEditor, PptxShape, PptxSlide, type ReadPdfOptions, type ReconstructOptions, type Relationship, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, type SlideImageInit, type SlidesLayoutOptions, type TextBoxInit, type WinAnsiSubstitution, type WritePdfOptions, type XmlCdata, XmlCdataSchema, type XmlComment, XmlCommentSchema, type XmlDeclaration, XmlDeclarationSchema, type XmlElement, XmlElementSchema, type XmlNode, XmlNodeSchema, type XmlPart, XmlPartSchema, type XmlPi, XmlPiSchema, type XmlText, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxPdfCodec, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfCodec, pdfToDocx, pdfToPptx, pptxPdfCodec, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
package/dist/index.js CHANGED
@@ -269,7 +269,7 @@ const LayoutMetadataSchema = z.object({
269
269
  createdIso: z.string().optional(),
270
270
  modifiedIso: z.string().optional()
271
271
  });
272
- z.object({
272
+ const LayoutDocumentSchema = z.object({
273
273
  formatVersion: z.literal(1),
274
274
  metadata: LayoutMetadataSchema,
275
275
  pages: z.array(LayoutPageSchema),
@@ -385,6 +385,45 @@ const ContentDocumentSchema = z.discriminatedUnion("kind", [z.object({
385
385
  slides: z.array(ContentSlideSchema)
386
386
  })]);
387
387
  //#endregion
388
+ //#region src/model/bytes.ts
389
+ const ZIP_LOCAL_FILE_HEADER = [
390
+ 80,
391
+ 75,
392
+ 3,
393
+ 4
394
+ ];
395
+ const PDF_HEADER = [
396
+ 37,
397
+ 80,
398
+ 68,
399
+ 70,
400
+ 45
401
+ ];
402
+ const PDF_HEADER_SEARCH_WINDOW = 1024;
403
+ function startsWithBytes(bytes, signature) {
404
+ if (bytes.length < signature.length) return false;
405
+ for (let i = 0; i < signature.length; i++) if (bytes[i] !== signature[i]) return false;
406
+ return true;
407
+ }
408
+ function containsBytesWithin(bytes, signature, window) {
409
+ const limit = Math.min(bytes.length - signature.length, window);
410
+ for (let start = 0; start <= limit; start++) {
411
+ let matched = true;
412
+ for (let i = 0; i < signature.length; i++) if (bytes[start + i] !== signature[i]) {
413
+ matched = false;
414
+ break;
415
+ }
416
+ if (matched) return true;
417
+ }
418
+ return false;
419
+ }
420
+ function zipBytesSchema(label) {
421
+ return z.instanceof(Uint8Array).refine((bytes) => startsWithBytes(bytes, ZIP_LOCAL_FILE_HEADER), { message: `not a valid ${label} file: missing the ZIP local-file-header signature` });
422
+ }
423
+ const DocxBytesSchema = zipBytesSchema("docx");
424
+ const PptxBytesSchema = zipBytesSchema("pptx");
425
+ const PdfBytesSchema = z.instanceof(Uint8Array).refine((bytes) => containsBytesWithin(bytes, PDF_HEADER, PDF_HEADER_SEARCH_WINDOW), { message: "not a valid PDF file: missing the %PDF- header" });
426
+ //#endregion
388
427
  //#region src/xml/fragment.ts
389
428
  function el(tag, attrs = {}, children = []) {
390
429
  return {
@@ -6736,6 +6775,12 @@ function writePdf(doc, options = {}) {
6736
6775
  return writer.toBytes();
6737
6776
  }
6738
6777
  //#endregion
6778
+ //#region src/pdf/codec.ts
6779
+ const pdfCodec = z.codec(PdfBytesSchema, LayoutDocumentSchema, {
6780
+ decode: (bytes) => readPdf(bytes),
6781
+ encode: (doc) => writePdf(doc)
6782
+ });
6783
+ //#endregion
6739
6784
  //#region src/ooxml/core-properties.ts
6740
6785
  const CORE_PROPERTIES_PATH = "docProps/core.xml";
6741
6786
  const APP_PROPERTIES_PATH = "docProps/app.xml";
@@ -8781,6 +8826,16 @@ function pdfToPptx(bytes, options) {
8781
8826
  return encodePackage$1(buildPptxPackage(content));
8782
8827
  }
8783
8828
  //#endregion
8829
+ //#region src/convert/codec.ts
8830
+ const docxPdfCodec = z.codec(DocxBytesSchema, PdfBytesSchema, {
8831
+ decode: (docxBytes) => docxToPdf(docxBytes),
8832
+ encode: (pdfBytes) => pdfToDocx(pdfBytes)
8833
+ });
8834
+ const pptxPdfCodec = z.codec(PptxBytesSchema, PdfBytesSchema, {
8835
+ decode: (pptxBytes) => pptxToPdf(pptxBytes),
8836
+ encode: (pdfBytes) => pdfToPptx(pdfBytes)
8837
+ });
8838
+ //#endregion
8784
8839
  //#region src/convert/local.ts
8785
8840
  const SUPPORTED_CONVERSIONS = [
8786
8841
  {
@@ -8886,4 +8941,4 @@ function fixedClock(date) {
8886
8941
  return { now: () => date };
8887
8942
  }
8888
8943
  //#endregion
8889
- export { AttributeSchema, BinaryPartSchema, COLOR_BLACK, CONTENT_FORMAT_VERSION, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, ContentBlockSchema, ContentDocumentSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentShapeSchema, ContentSlideSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, DefinedNameSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, LAYOUT_FORMAT_VERSION, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PackageSchema, PartSchema, PdfEncryptedError, PdfParseError, PptxEditor, PptxShape, PptxSlide, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfToDocx, pdfToPptx, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
8944
+ export { AttributeSchema, BinaryPartSchema, COLOR_BLACK, CONTENT_FORMAT_VERSION, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, ContentBlockSchema, ContentDocumentSchema, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentRunSchema, ContentSectionSchema, ContentShapeSchema, ContentSlideSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, DEFAULT_LAYOUT_FONT, DefinedNameSchema, DocxBytesSchema, DocxEditor, DocxParagraph, DocxRun, DocxTable, DocxTableCell, DocxTableRow, LAYOUT_FORMAT_VERSION, NOOP_DIAGNOSTIC_SINK, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PackageSchema, PartSchema, PdfBytesSchema, PdfEncryptedError, PdfParseError, PptxBytesSchema, PptxEditor, PptxShape, PptxSlide, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, base64ToBytes, buildDocxPackage, buildPptxPackage, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, convertPresentationToLayout, convertWordprocessingToLayout, createDocx, createLocalDocumentConverter, createPptx, decodeCompactPackage, decodeEntities, decodePackage, docxPdfCodec, docxToPdf, elementsWithTag, encodeCompactPackage, encodePackage, fixedClock, flipY, fromCompact, isCompactXmlNode, isContentBlock, isXmlNode, openDocx, openPptx, packageCodec, parsePackage, parseXml, pdfCodec, pdfToDocx, pdfToPptx, pptxPdfCodec, pptxToPdf, readDocxContent, readPdf, readPptxContent, reconstructPresentation, reconstructWordprocessing, resolveRelationships, rgbHexToColor, rootElement, serializePackage, systemClock, textContent, throwIfAborted, toCompact, unzipPackage, walk, writePdf, xmlCodec, zipPackage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "documents.js",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "description": "Bidirectional docx/pptx <-> PDF conversion and a read+write editable OOXML document model, built on ooxml.js and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {