documents.js 1.51.0 → 1.52.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
@@ -81,6 +81,27 @@ const { document, diagnostics } = await converter.convert(
81
81
 
82
82
  `DocumentFormat` includes `xlsx` alongside `docx`/`pptx`/`odt`/`odp`/`ods`/`odg`/`pdf` — not because xlsx has a PDF conversion of its own, but because `createLocalDocumentConverter`'s `{ source, targetFormat }` contract already generalises past "targetFormat always means pdf": `odt`→`docx`, `docx`→`odt`, `odp`→`pptx`, `pptx`→`odp`, `ods`→`xlsx`, and `xlsx`→`ods` are six further entries in the same `conversions` list, routed to the six bridge functions above with an empty `diagnostics` array.
83
83
 
84
+ Getting back the intermediate `DocumentPackage` (content + layout, from `document-content-model`) a conversion built internally, instead of only the target bytes — every ergonomic conversion function above accepts an `onDocument` callback for this, and the port surfaces the same value as `package` on its `ConversionResult`:
85
+
86
+ ```ts
87
+ import { docxToPdf } from 'documents.js';
88
+
89
+ const pdfBytes = docxToPdf(docxBytes, {
90
+ onDocument: (pkg) => {
91
+ console.log(pkg.content.kind); // 'wordprocessing'
92
+ console.log(pkg.layout?.pages.length); // populated for every X-to-PDF/PDF-to-X conversion
93
+ },
94
+ });
95
+
96
+ // or via the port:
97
+ const { document, package: pkg } = await converter.convert(
98
+ { source: { format: 'docx', bytes: docxBytes }, targetFormat: 'pdf' },
99
+ { signal: new AbortController().signal },
100
+ );
101
+ ```
102
+
103
+ For the six PDF-bypassing bridges, `pkg.layout` is always `undefined` — a bridge never runs a layout engine, so there is nothing to populate it with; running one purely to fill this field would be wasted work no caller asked for.
104
+
84
105
  Reading and editing docx/pptx content directly, without going through PDF at all:
85
106
 
86
107
  ```ts
@@ -274,7 +295,7 @@ The package is layered from generic primitives outward to the two conversion dir
274
295
  - **`src/layout/`** — the pure conversion algorithms, importing `model` and (for formula placement) `mathml`: `engine.ts` (`ContentDocument` wordprocessing → `LayoutDocument`: flow, line-breaking, pagination — fed identically by docx- and odt-sourced content; also returns `WordprocessingLayoutResult.formulas`, every embedded formula block it laid out via `src/mathml`'s `layoutFormula`, positioned in PDF page space — see the Gotchas entry below on why a formula can't become an ordinary `LayoutItem`), `slides.ts` (`ContentDocument` presentation → `LayoutDocument`: direct EMU-to-point placement, no pagination needed — fed identically by pptx- and odp-sourced content; also exports `convertShape`, the single-`ContentShape`-to-`LayoutItem[]` conversion `drawing.ts` below reuses verbatim, now optionally formula-aware via its own trailing `formulaContext` parameter so `drawing.ts`'s existing call site keeps compiling unchanged), `sheets.ts` (`ContentDocument` spreadsheet → `LayoutDocument`: resolve the print range, build cumulative column/row offsets skipping hidden ones, reserve header/repeat-row-column space, resolve an explicit or non-iterative fit-to-page scale, partition into column/row bands honouring manual breaks with the same "an oversized item gets its own band and overflows rather than looping" guarantee `engine.ts`'s `ensureRoom` documents, emit pages in `downThenOver`/`overThenDown` order, then per page paint backgrounds/gridlines/headers/cell text with default alignment by value kind and `###`/spill-then-truncate overflow handling — the first layout algorithm in this package that accepts an `AbortSignal`, since a 50k-cell sheet needs cancellation where a docx/pptx page count never did), `drawing.ts` (`ContentDocument` drawing → `LayoutDocument`: one `ContentDrawPage` per PDF page, direct placement like `slides.ts`, with one new emission path — a `ContentVector` `rect`/`ellipse`/`line` maps onto the pre-existing `LayoutRect`/`LayoutEllipse`/`LayoutLine` kinds, and a `path` vector's local, viewBox-relative subpath points are resolved through the vector's own frame offset then a single page-space flip into a `LayoutPath` value; vectors paint before shapes, a documented, bounded choice — see this module's own top-of-file note — since `ContentDrawPageSchema` keeps `shapes` and `vectors` as two independently paint-ordered arrays with no field recording their relative order when the two genuinely overlap), `reconstruct.ts` (`LayoutDocument` → `ContentDocument`: `reconstructWordprocessing`/`reconstructPresentation` do baseline-proximity line clustering, then paragraph/text-block clustering from geometry — PDF has no semantic paragraph or shape structure to recover, only positioned glyphs; `reconstructDrawing` does no clustering at all, since a drawing has no such structure to infer in the first place — every `LayoutItem` maps close to 1:1 back onto a `ContentVector` `rect`/`ellipse`/`line`/`path` or a `ContentShape`, in the exact z-order it was painted, bucketed into `ContentDrawPageSchema`'s own two independently-ordered `shapes`/`vectors` arrays the same way `drawing.ts` produced them; `reconstructSpreadsheet` tries a real gridline lattice first — scanning the page's `LayoutLine`/stroked-single-segment-`LayoutPath` items for enough parallel horizontal and vertical lines at consistent positions to call it a printed grid, using those line positions directly as cell boundaries when found — and falls back to text-position clustering otherwise, reusing this same module's `clusterIntoLines` for rows and a parallel recurring-x-position generalisation of `clusterIntoParagraphs`'s own `dominantLeftX` for columns; every recovered cell is a bare string, column widths/row heights are genuinely measured from whichever geometry was used, and no print range/scale/repeat-rows/repeat-columns/manual-breaks are ever inferred).
275
296
  - **`src/hsqldb/`** — `script.ts`, the Tier 1 `.odb` decoder: a small, bounded HSQLDB TEXT-script-format (`hsqldb.script_format=0`) DDL/DML text parser, not a database engine — `parseHsqldbScript(bytes)` extracts `CREATE TABLE`'s own column names/types and `INSERT INTO`'s own row values into `HsqldbTable[]`, tolerating (skipping) every other statement kind real HSQLDB output emits that this package has no use for (users, grants, sequences, indexes, views), and throwing `HsqldbScriptParseError` for anything matching neither list. Mirrors `src/pdf/`'s own isolation discipline: it imports only `document-content-model`'s `ContentCellValue` type, no odf.js `Package`/`XmlElement` knowledge at all — the caller is responsible for handing it raw bytes already extracted from a real `.odb` package.
276
297
  - **`src/odb/`** — the decoder-selection and pivot-mapping layer sitting between odf.js's `.odb` support and `src/hsqldb/`: `read.ts`'s `readOdbTables(pkg)` calls odf.js's own `readOdbInventory` to classify the package's connection (throwing `OdbNoEmbeddedDataSourceError` for an external-only datasource) and its embedded engine (throwing `OdbUnsupportedFormatError`, naming Firebird or HSQLDB's own binary/compressed script formats explicitly, for anything Tier 1 doesn't cover), then routes a genuine HSQLDB TEXT script to `parseHsqldbScript`. `spreadsheet.ts`'s `odbTablesToSpreadsheetDocument` maps `HsqldbTable[]` onto the same `ContentSheet`-based `ContentDocument` spreadsheet variant `readOdsContent`/`buildOdsPackage` already produce and consume, feeding `odbToXlsx`'s call into `buildXlsxPackage` directly. `csv.ts`'s `buildOdbTableCsv` writes exactly one named table as CSV bytes, with no `ContentSheet`/xlsx machinery involved at all, throwing `OdbTableNotSpecifiedError`/`OdbTableNotFoundError` (naming every available table) when the caller's own `table` option doesn't resolve to exactly one table.
277
- - **`src/convert/`** — `convert.ts` (the twelve PDF-pivot round-trip ergonomic wrappers, a dedicated "Six cross-format bridges" section: `odtToDocx`/`docxToOdt`, `odpToPptx`/`pptxToOdp`, `odsToXlsx`/`xlsxToOds`, each a direct `readXContent` → `buildYPackage` composition bypassing PDF entirely — see [Fidelity](#fidelity) — `odmToPdf`, the one further conversion shaped around a caller-supplied `resolveSubDocument` callback rather than being purely bytes-in/bytes-out, since a `.odm` master document's own chapters are external references odf.js's `readOdm` never inlines — see Gotchas — `odbToXlsx`/`odbToCsv`, thin compositions over `readOdbTables` and `src/odb/`'s own pivot/CSV mapping, and `odfToPdf`, a standalone `.odf` formula document → PDF via `readOdfFormulaContent` → `src/mathml`'s `layoutFormula` → `writePdf`'s own formula-aware option, with no reverse `pdfToOdf` at all), `codec.ts` (`docxPdfCodec`/`pptxPdfCodec`/`odtPdfCodec`/`odpPdfCodec`/`odsPdfCodec`/`odgPdfCodec` plus `odtDocxCodec`/`odpPptxCodec`/`odsXlsxCodec`, a `z.codec()` pair over each — `odmToPdf`/`odbToXlsx`/`odbToCsv`/`odfToPdf` have no codec of their own, for the same fixed-signature/one-directional reasons each has no port entry, or a one-way port entry, below), `port.ts`/`local.ts` (the swappable `DocumentConverter` contract and its synchronous local implementation, covering `docx`/`pptx`/`odt`/`odp`/`ods`/`odg`/`odf` → `pdf`, `pdf` → `docx`/`pptx`/`odt`/`odp`/`ods`/`odg`, and the six bridge pairs — `DocumentFormat` includes `xlsx` for exactly this reason, even though xlsx has no PDF conversion of its own; `odm` and `odb` are deliberately not `DocumentFormat` members, since neither `odmToPdf` nor `odbToXlsx`/`odbToCsv` is wired into this port at all; `odf` IS a member, but with only the one `odf → pdf` entry — no `pdf → odf`).
298
+ - **`src/convert/`** — `convert.ts` (the twelve PDF-pivot round-trip ergonomic wrappers, a dedicated "Six cross-format bridges" section: `odtToDocx`/`docxToOdt`, `odpToPptx`/`pptxToOdp`, `odsToXlsx`/`xlsxToOds`, each a direct `readXContent` → `buildYPackage` composition bypassing PDF entirely — see [Fidelity](#fidelity) — `odmToPdf`, the one further conversion shaped around a caller-supplied `resolveSubDocument` callback rather than being purely bytes-in/bytes-out, since a `.odm` master document's own chapters are external references odf.js's `readOdm` never inlines — see Gotchas — `odbToXlsx`/`odbToCsv`, thin compositions over `readOdbTables` and `src/odb/`'s own pivot/CSV mapping, and `odfToPdf`, a standalone `.odf` formula document → PDF via `readOdfFormulaContent` → `src/mathml`'s `layoutFormula` → `writePdf`'s own formula-aware option, with no reverse `pdfToOdf` at all), `codec.ts` (`docxPdfCodec`/`pptxPdfCodec`/`odtPdfCodec`/`odpPdfCodec`/`odsPdfCodec`/`odgPdfCodec` plus `odtDocxCodec`/`odpPptxCodec`/`odsXlsxCodec`, a `z.codec()` pair over each — `odmToPdf`/`odbToXlsx`/`odbToCsv`/`odfToPdf` have no codec of their own, for the same fixed-signature/one-directional reasons each has no port entry, or a one-way port entry, below), `port.ts`/`local.ts` (the swappable `DocumentConverter` contract and its synchronous local implementation, covering `docx`/`pptx`/`odt`/`odp`/`ods`/`odg`/`odf` → `pdf`, `pdf` → `docx`/`pptx`/`odt`/`odp`/`ods`/`odg`, and the six bridge pairs — `DocumentFormat` includes `xlsx` for exactly this reason, even though xlsx has no PDF conversion of its own; `odm` and `odb` are deliberately not `DocumentFormat` members, since neither `odmToPdf` nor `odbToXlsx`/`odbToCsv` is wired into this port at all; `odf` IS a member, but with only the one `odf → pdf` entry — no `pdf → odf`). Every conversion function that builds a `ContentDocument`/`LayoutDocument` internally (the twelve PDF-pivot conversions and the six bridges; `odfToPdf` accepts but never invokes it) also accepts an `onDocument` callback, and `ConversionResult` carries the same value through the port as an optional `package` field — the full `DocumentPackage` (content + layout, from `document-content-model`) that conversion built, not just its target bytes.
278
299
 
279
300
  Dependency direction is strictly downward and checkable: `model`/`bytes`/`mathml` import nothing local (`mathml` is fully self-contained — no dependency on `model`, `document-content-model`, or any ODF/PDF package, since it consumes only its own locally-mirrored `MathMlNode` input and its own injected `MathFontMetrics` port); `image` imports `bytes` only; `pdf` imports `model`+`bytes`+`image`+`mathml`; `ooxml/*` imports `xml`/`model` only (no PDF knowledge); `odf/*` imports `model` only (no PDF knowledge, no `xml/*` — `odf.js` already owns its own XML query helpers); `hsqldb` imports `document-content-model` only (no odf.js knowledge); `layout` imports `model`+`mathml`; `odb` imports `hsqldb`+`model`+odf.js only; `convert` composes everything else. No `PdfObject`/`PdfDict`/`PdfStream` type appears outside `src/pdf/`.
280
301
 
@@ -306,6 +327,7 @@ To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
306
327
 
307
328
  - **`ooxml.js`'s typed readers (`readDocx`/`readPptx`) are now the actual basis for conversion** — `readDocxContent`/`readPptxContent` are thin wrappers around them, not an independent walk of `word/document.xml`/`ppt/slides/slideN.xml`. They are still deliberately not re-exported from this package's own public surface: `readDocx`/`readPptx` also carry `comments`/`footnotes`/`headers`/`footers` (docx) that `ContentDocument` doesn't model, so exposing both the wrapper and the thing it wraps would invite a caller to reach for the wrong one rather than genuinely offering two competing models.
308
329
  - **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). The six cross-format bridges below (`odtToDocx`/`docxToOdt`, `odpToPptx`/`pptxToOdp`, `odsToXlsx`/`xlsxToOds`) are a genuinely different case — see the [Fidelity](#fidelity) section's own paragraph on them.
330
+ - **A `DocumentPackage` returned via `onDocument`/`ConversionResult.package` is a snapshot from that one conversion pass, not a live view** — its `layout` correlates with its `content` only as of the exact read+layout that produced it (`document-content-model`'s own `DocumentPackageSchema` doc comment), so if a caller mutates the returned `content` afterwards, the `layout` sitting alongside it silently goes stale; nothing in this package (or `document-content-model`) detects or rejects that.
309
331
  - **Building the six cross-format bridges surfaced two real, previously-undiscovered gaps in existing `populateParagraph` write paths, both now fixed.** `buildDocxPackage`'s `populateParagraph` (`src/edit/docx/content.ts`) never wrote a paragraph's own `list` membership back (`ContentParagraph.list`, docx's flat `numId`/`level` model) — only read, never written, since no existing caller had ever round-tripped a list-bearing paragraph through it. `buildOdtPackage`'s `populateParagraph` (`src/edit/odt/content.ts`) never wrote a paragraph's own `styleId` back at all (`readOdtContent`/`readOdfParagraph` in `odf.js` reads it unconditionally from `text:style-name`, but nothing on the write side ever set that attribute). Both are now fixed: `DocxParagraph.list` is set unconditionally alongside `styleId`/`alignment`, matching that function's own existing pattern; `OdtParagraph.styleId` is set conditionally alongside `alignment`, matching odt's own local convention. `buildOdtPackage` additionally gained `appendBlocks`/`appendListRun` (`src/edit/odt/content.ts`) — ODF has no flat per-paragraph list property to set the way docx does, so a run of consecutive `ContentParagraph`s sharing `list.numId` is grouped and written as a real, potentially multi-level `text:list`/`text:list-item` tree via `OdtList`/`OdtListItem`, the structural inverse of `odf.js`'s own list-reading (a fresh `text:list` per `numId` change, one level of nesting per `list.level` step, descending only one level at a time since ODF can only open a nested list from inside an existing item). Both gaps were invisible before this task specifically because nothing had previously round-tripped a list-bearing paragraph or a styled paragraph through `docx ⇄ odt` at all — the PDF-pivot conversions never exercised `buildDocxPackage`/`buildOdtPackage` on content read back from the OTHER format.
310
332
  - **A table shape inside an odp slide does not survive `odpToPptx`.** `buildPptxPackage`'s `appendShape` (`src/edit/pptx/content.ts`) silently drops any non-paragraph block found inside a shape's own text-box loop — a scope choice whose own comment ("PDF-reconstructed shapes never mix kinds") assumed its only caller was the PDF-reconstruction path, where that is true. `odpToPptx` is a second, non-PDF-reconstructed caller for which it is not: a real odp `draw:frame` containing a `table:table` directly (not inside a text box) reads as a `ContentShape` with a `'table'` block, and that block is silently dropped, leaving an empty pptx text box where the table was. Everything else on the same slide — a rotated shape, grouped shapes, an image, speaker notes — survives correctly (see `src/convert/bridges.test.ts`'s own dedicated fidelity-gap test, which proves both halves against the existing `minimalOdpBytes()` fixture). A real, tracked, bounded gap, not a silent one: closing it means teaching `buildPptxPackage`/`buildOdpPackage` to write a real table into a slide shape, a materially larger feature than this bridge's own scope.
311
333
  - **The `ods ⇄ xlsx` bridge inherits several real, format-boundary fidelity limits from `ooxml.js`'s brand-new `readXlsxContent`/`buildXlsxPackage`, on top of its own pivot-copy design.** xlsx has no `percentage`/`currency` cell type of its own (both are a plain numeric cell plus a number-format style neither this reader nor this writer interprets) — an ods `percentage`/`currency` cell survives the `odsToXlsx` hop with its numeric *value* intact but downgrades to a plain `number` *kind*, permanently (currency's own currency code is dropped outright). xlsx also has only one rare `t="d"` cell type covering BOTH date and time — an ods `time` cell survives as a `date`-kind cell carrying its original value string verbatim, but mislabelled; an ods `date` cell is unaffected (it was already the kind xlsx's own `t="d"` maps onto). A formula (`table:formula`/`<f>`) is carried completely verbatim in both directions — never parsed, translated, or evaluated by either this package's own reader or writer — but a REAL spreadsheet application does evaluate a workbook's own `<f>`/`table:formula` on open: confirmed against genuine LibreOffice 26.2, an ods formula authored in OpenFormula syntax (`of:=[.B2]*2`) becomes a formula ERROR (`Err:510`) when the bridged xlsx is opened in real Calc, even though the formula's own cached value is still present and correctly readable via `readXlsxContent` — going the other way is less fragile in practice only because a genuine xlsx formula (bare Excel A1 syntax, e.g. `B2*2`) happens to still parse under LibreOffice's own more lenient, backward-compatible ODF formula grammar, not because of anything this bridge does differently in either direction. Column widths survive the `odsToXlsx` hop within roughly a pixel of rounding tolerance (see `src/convert/bridges.test.ts`'s own `COLUMN_WIDTH_TOLERANCE_PT`) but are then dropped entirely on the return `xlsxToOds` hop — not a character-width-unit rounding loss, but `buildOdsPackage` not writing `ContentSheetColumn.widthPt` at all, a pre-existing, already-documented gap in that file's own module comment, unrelated to and unfixed by this bridge. A boolean cell written by `buildXlsxPackage` renders as a raw `1`/`0` rather than `TRUE`/`FALSE` when opened in real Excel/Calc, since that writer's own genuinely-minimal `xl/styles.xml` (one default cell format, no boolean-specific number format) has nothing else to apply — the underlying `{ kind: 'boolean', value: true }` is still read back correctly by `readXlsxContent` regardless; this is a real-application *display* gap, not a data-fidelity one. `readXlsxContent`'s own cell.value.kind never produces `'error'` from an odf.js-sourced document at all, for a structural reason rather than a bug: ODF's `office:value-type` enumeration has no `error` member, so `OdsCell.value`'s own write-side choice for a `kind: 'error'` cell is to write it as a genuine, non-empty `office:string-value` carrying the error's own text — an `xlsxToOds` → `odsToXlsx` round trip of a genuine xlsx `t="e"` error cell therefore turns it into a plain `string` cell carrying the identical text; the message survives, the `error` semantic does not.
package/dist/index.cjs CHANGED
@@ -14691,6 +14691,11 @@ function docxToPdf(bytes, options) {
14691
14691
  const content = readDocxContent(openDocx(bytes).toPackage());
14692
14692
  if (content.kind !== "wordprocessing") throw new Error("readDocxContent returned a non-wordprocessing ContentDocument");
14693
14693
  const { document: layout, formulas } = convertWordprocessingToLayout(content, { measurer: createStandardFontMeasurer() });
14694
+ options?.onDocument?.({
14695
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14696
+ content,
14697
+ layout
14698
+ });
14694
14699
  return writePdf(layout, {
14695
14700
  signal: options?.signal,
14696
14701
  onSubstitution: options?.onSubstitution,
@@ -14704,6 +14709,11 @@ function odtToPdf(bytes, options) {
14704
14709
  measurer: createStandardFontMeasurer(),
14705
14710
  formulas: content.formulas
14706
14711
  });
14712
+ options?.onDocument?.({
14713
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14714
+ content: content.document,
14715
+ layout
14716
+ });
14707
14717
  return writePdf(layout, {
14708
14718
  signal: options?.signal,
14709
14719
  onSubstitution: options?.onSubstitution,
@@ -14714,6 +14724,11 @@ function pptxToPdf(bytes, options) {
14714
14724
  const content = readPptxContent(openPptx(bytes).toPackage());
14715
14725
  if (content.kind !== "presentation") throw new Error("readPptxContent returned a non-presentation ContentDocument");
14716
14726
  const { document: layout } = convertPresentationToLayout(content, { measurer: createStandardFontMeasurer() });
14727
+ options?.onDocument?.({
14728
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14729
+ content,
14730
+ layout
14731
+ });
14717
14732
  return writePdf(layout, {
14718
14733
  signal: options?.signal,
14719
14734
  onSubstitution: options?.onSubstitution
@@ -14726,6 +14741,11 @@ function odpToPdf(bytes, options) {
14726
14741
  measurer: createStandardFontMeasurer(),
14727
14742
  formulas: content.formulas
14728
14743
  });
14744
+ options?.onDocument?.({
14745
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14746
+ content: content.document,
14747
+ layout
14748
+ });
14729
14749
  return writePdf(layout, {
14730
14750
  signal: options?.signal,
14731
14751
  onSubstitution: options?.onSubstitution,
@@ -14735,10 +14755,16 @@ function odpToPdf(bytes, options) {
14735
14755
  function odsToPdf(bytes, options) {
14736
14756
  const content = readOdsContent((0, odf_js.decodePackage)(bytes));
14737
14757
  if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
14738
- return writePdf(convertSpreadsheetToLayout(content, {
14758
+ const layout = convertSpreadsheetToLayout(content, {
14739
14759
  measurer: createStandardFontMeasurer(),
14740
14760
  signal: options?.signal
14741
- }), {
14761
+ });
14762
+ options?.onDocument?.({
14763
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14764
+ content,
14765
+ layout
14766
+ });
14767
+ return writePdf(layout, {
14742
14768
  signal: options?.signal,
14743
14769
  onSubstitution: options?.onSubstitution
14744
14770
  });
@@ -14746,7 +14772,13 @@ function odsToPdf(bytes, options) {
14746
14772
  function odgToPdf(bytes, options) {
14747
14773
  const content = readOdgContent((0, odf_js.decodePackage)(bytes));
14748
14774
  if (content.kind !== "drawing") throw new Error("readOdgContent returned a non-drawing ContentDocument");
14749
- return writePdf(convertDrawingToLayout(content, { measurer: createStandardFontMeasurer() }), {
14775
+ const layout = convertDrawingToLayout(content, { measurer: createStandardFontMeasurer() });
14776
+ options?.onDocument?.({
14777
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14778
+ content,
14779
+ layout
14780
+ });
14781
+ return writePdf(layout, {
14750
14782
  signal: options?.signal,
14751
14783
  onSubstitution: options?.onSubstitution
14752
14784
  });
@@ -14790,45 +14822,81 @@ function odfToPdf(bytes, options) {
14790
14822
  });
14791
14823
  }
14792
14824
  function pdfToDocx(bytes, options) {
14793
- const content = reconstructWordprocessing(readPdf(bytes, {
14825
+ const layout = readPdf(bytes, {
14794
14826
  signal: options?.signal,
14795
14827
  sink: options?.sink
14796
- }), { signal: options?.signal });
14828
+ });
14829
+ const content = reconstructWordprocessing(layout, { signal: options?.signal });
14830
+ options?.onDocument?.({
14831
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14832
+ content,
14833
+ layout
14834
+ });
14797
14835
  return (0, ooxml_js.encodePackage)(buildDocxPackage(content));
14798
14836
  }
14799
14837
  function pdfToPptx(bytes, options) {
14800
- const content = reconstructPresentation(readPdf(bytes, {
14838
+ const layout = readPdf(bytes, {
14801
14839
  signal: options?.signal,
14802
14840
  sink: options?.sink
14803
- }), { signal: options?.signal });
14841
+ });
14842
+ const content = reconstructPresentation(layout, { signal: options?.signal });
14843
+ options?.onDocument?.({
14844
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14845
+ content,
14846
+ layout
14847
+ });
14804
14848
  return (0, ooxml_js.encodePackage)(buildPptxPackage(content));
14805
14849
  }
14806
14850
  function pdfToOdt(bytes, options) {
14807
- const content = reconstructWordprocessing(readPdf(bytes, {
14851
+ const layout = readPdf(bytes, {
14808
14852
  signal: options?.signal,
14809
14853
  sink: options?.sink
14810
- }), { signal: options?.signal });
14854
+ });
14855
+ const content = reconstructWordprocessing(layout, { signal: options?.signal });
14856
+ options?.onDocument?.({
14857
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14858
+ content,
14859
+ layout
14860
+ });
14811
14861
  return (0, odf_js.encodePackage)(buildOdtPackage(content));
14812
14862
  }
14813
14863
  function pdfToOdp(bytes, options) {
14814
- const content = reconstructPresentation(readPdf(bytes, {
14864
+ const layout = readPdf(bytes, {
14815
14865
  signal: options?.signal,
14816
14866
  sink: options?.sink
14817
- }), { signal: options?.signal });
14867
+ });
14868
+ const content = reconstructPresentation(layout, { signal: options?.signal });
14869
+ options?.onDocument?.({
14870
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14871
+ content,
14872
+ layout
14873
+ });
14818
14874
  return (0, odf_js.encodePackage)(buildOdpPackage(content));
14819
14875
  }
14820
14876
  function pdfToOdg(bytes, options) {
14821
- const content = reconstructDrawing(readPdf(bytes, {
14877
+ const layout = readPdf(bytes, {
14822
14878
  signal: options?.signal,
14823
14879
  sink: options?.sink
14824
- }), { signal: options?.signal });
14880
+ });
14881
+ const content = reconstructDrawing(layout, { signal: options?.signal });
14882
+ options?.onDocument?.({
14883
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14884
+ content,
14885
+ layout
14886
+ });
14825
14887
  return (0, odf_js.encodePackage)(buildOdgPackage(content));
14826
14888
  }
14827
14889
  function pdfToOds(bytes, options) {
14828
- const content = reconstructSpreadsheet(readPdf(bytes, {
14890
+ const layout = readPdf(bytes, {
14829
14891
  signal: options?.signal,
14830
14892
  sink: options?.sink
14831
- }), { signal: options?.signal });
14893
+ });
14894
+ const content = reconstructSpreadsheet(layout, { signal: options?.signal });
14895
+ options?.onDocument?.({
14896
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14897
+ content,
14898
+ layout
14899
+ });
14832
14900
  return (0, odf_js.encodePackage)(buildOdsPackage(content));
14833
14901
  }
14834
14902
  function odtToDocx(bytes, options) {
@@ -14836,6 +14904,10 @@ function odtToDocx(bytes, options) {
14836
14904
  const content = readOdtContent((0, odf_js.decodePackage)(bytes)).document;
14837
14905
  if (content.kind !== "wordprocessing") throw new Error("readOdtContent returned a non-wordprocessing ContentDocument");
14838
14906
  throwIfAborted(options?.signal);
14907
+ options?.onDocument?.({
14908
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14909
+ content
14910
+ });
14839
14911
  return (0, ooxml_js.encodePackage)(buildDocxPackage(content));
14840
14912
  }
14841
14913
  function docxToOdt(bytes, options) {
@@ -14843,6 +14915,10 @@ function docxToOdt(bytes, options) {
14843
14915
  const content = readDocxContent((0, ooxml_js.decodePackage)(bytes));
14844
14916
  if (content.kind !== "wordprocessing") throw new Error("readDocxContent returned a non-wordprocessing ContentDocument");
14845
14917
  throwIfAborted(options?.signal);
14918
+ options?.onDocument?.({
14919
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14920
+ content
14921
+ });
14846
14922
  return (0, odf_js.encodePackage)(buildOdtPackage(content));
14847
14923
  }
14848
14924
  function odpToPptx(bytes, options) {
@@ -14850,6 +14926,10 @@ function odpToPptx(bytes, options) {
14850
14926
  const content = readOdpContent((0, odf_js.decodePackage)(bytes)).document;
14851
14927
  if (content.kind !== "presentation") throw new Error("readOdpContent returned a non-presentation ContentDocument");
14852
14928
  throwIfAborted(options?.signal);
14929
+ options?.onDocument?.({
14930
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14931
+ content
14932
+ });
14853
14933
  return (0, ooxml_js.encodePackage)(buildPptxPackage(content));
14854
14934
  }
14855
14935
  function pptxToOdp(bytes, options) {
@@ -14857,6 +14937,10 @@ function pptxToOdp(bytes, options) {
14857
14937
  const content = readPptxContent((0, ooxml_js.decodePackage)(bytes));
14858
14938
  if (content.kind !== "presentation") throw new Error("readPptxContent returned a non-presentation ContentDocument");
14859
14939
  throwIfAborted(options?.signal);
14940
+ options?.onDocument?.({
14941
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14942
+ content
14943
+ });
14860
14944
  return (0, odf_js.encodePackage)(buildOdpPackage(content));
14861
14945
  }
14862
14946
  function odsToXlsx(bytes, options) {
@@ -14864,6 +14948,10 @@ function odsToXlsx(bytes, options) {
14864
14948
  const content = readOdsContent((0, odf_js.decodePackage)(bytes));
14865
14949
  if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
14866
14950
  throwIfAborted(options?.signal);
14951
+ options?.onDocument?.({
14952
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14953
+ content
14954
+ });
14867
14955
  return (0, ooxml_js.encodePackage)((0, ooxml_js.buildXlsxPackage)(content));
14868
14956
  }
14869
14957
  function xlsxToOds(bytes, options) {
@@ -14872,6 +14960,10 @@ function xlsxToOds(bytes, options) {
14872
14960
  const content = (0, ooxml_js.readXlsxContent)(pkg);
14873
14961
  if (content.kind !== "spreadsheet") throw new Error("readXlsxContent returned a non-spreadsheet ContentDocument");
14874
14962
  throwIfAborted(options?.signal);
14963
+ options?.onDocument?.({
14964
+ formatVersion: document_content_model.DOCUMENT_PACKAGE_FORMAT_VERSION,
14965
+ content
14966
+ });
14875
14967
  return (0, odf_js.encodePackage)(buildOdsPackage(content));
14876
14968
  }
14877
14969
  var OdmUnresolvedSectionError = class extends Error {
@@ -15100,238 +15192,292 @@ function fromPdfDiagnostic(diagnostic) {
15100
15192
  }
15101
15193
  function createLocalDocumentConverter() {
15102
15194
  return {
15103
- contractVersion: 1,
15195
+ contractVersion: 2,
15104
15196
  conversions: SUPPORTED_CONVERSIONS,
15105
15197
  convert(request, options) {
15106
15198
  const { source, targetFormat } = request;
15107
15199
  const diagnostics = [];
15200
+ let documentPackage;
15201
+ const onDocument = (pkg) => {
15202
+ documentPackage = pkg;
15203
+ };
15108
15204
  if (source.format === "docx" && targetFormat === "pdf") {
15109
15205
  const bytes = docxToPdf(source.bytes, {
15110
15206
  signal: options.signal,
15111
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15207
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15208
+ onDocument
15112
15209
  });
15113
15210
  return Promise.resolve({
15114
15211
  document: {
15115
15212
  format: "pdf",
15116
15213
  bytes
15117
15214
  },
15118
- diagnostics
15215
+ diagnostics,
15216
+ package: documentPackage
15119
15217
  });
15120
15218
  }
15121
15219
  if (source.format === "pptx" && targetFormat === "pdf") {
15122
15220
  const bytes = pptxToPdf(source.bytes, {
15123
15221
  signal: options.signal,
15124
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15222
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15223
+ onDocument
15125
15224
  });
15126
15225
  return Promise.resolve({
15127
15226
  document: {
15128
15227
  format: "pdf",
15129
15228
  bytes
15130
15229
  },
15131
- diagnostics
15230
+ diagnostics,
15231
+ package: documentPackage
15132
15232
  });
15133
15233
  }
15134
15234
  if (source.format === "odt" && targetFormat === "pdf") {
15135
15235
  const bytes = odtToPdf(source.bytes, {
15136
15236
  signal: options.signal,
15137
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15237
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15238
+ onDocument
15138
15239
  });
15139
15240
  return Promise.resolve({
15140
15241
  document: {
15141
15242
  format: "pdf",
15142
15243
  bytes
15143
15244
  },
15144
- diagnostics
15245
+ diagnostics,
15246
+ package: documentPackage
15145
15247
  });
15146
15248
  }
15147
15249
  if (source.format === "odp" && targetFormat === "pdf") {
15148
15250
  const bytes = odpToPdf(source.bytes, {
15149
15251
  signal: options.signal,
15150
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15252
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15253
+ onDocument
15151
15254
  });
15152
15255
  return Promise.resolve({
15153
15256
  document: {
15154
15257
  format: "pdf",
15155
15258
  bytes
15156
15259
  },
15157
- diagnostics
15260
+ diagnostics,
15261
+ package: documentPackage
15158
15262
  });
15159
15263
  }
15160
15264
  if (source.format === "ods" && targetFormat === "pdf") {
15161
15265
  const bytes = odsToPdf(source.bytes, {
15162
15266
  signal: options.signal,
15163
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15267
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15268
+ onDocument
15164
15269
  });
15165
15270
  return Promise.resolve({
15166
15271
  document: {
15167
15272
  format: "pdf",
15168
15273
  bytes
15169
15274
  },
15170
- diagnostics
15275
+ diagnostics,
15276
+ package: documentPackage
15171
15277
  });
15172
15278
  }
15173
15279
  if (source.format === "odg" && targetFormat === "pdf") {
15174
15280
  const bytes = odgToPdf(source.bytes, {
15175
15281
  signal: options.signal,
15176
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15282
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15283
+ onDocument
15177
15284
  });
15178
15285
  return Promise.resolve({
15179
15286
  document: {
15180
15287
  format: "pdf",
15181
15288
  bytes
15182
15289
  },
15183
- diagnostics
15290
+ diagnostics,
15291
+ package: documentPackage
15184
15292
  });
15185
15293
  }
15186
15294
  if (source.format === "odf" && targetFormat === "pdf") {
15187
15295
  const bytes = odfToPdf(source.bytes, {
15188
15296
  signal: options.signal,
15189
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15297
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15298
+ onDocument
15190
15299
  });
15191
15300
  return Promise.resolve({
15192
15301
  document: {
15193
15302
  format: "pdf",
15194
15303
  bytes
15195
15304
  },
15196
- diagnostics
15305
+ diagnostics,
15306
+ package: documentPackage
15197
15307
  });
15198
15308
  }
15199
15309
  if (source.format === "pdf" && targetFormat === "docx") {
15200
15310
  const bytes = pdfToDocx(source.bytes, {
15201
15311
  signal: options.signal,
15202
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15312
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15313
+ onDocument
15203
15314
  });
15204
15315
  return Promise.resolve({
15205
15316
  document: {
15206
15317
  format: "docx",
15207
15318
  bytes
15208
15319
  },
15209
- diagnostics
15320
+ diagnostics,
15321
+ package: documentPackage
15210
15322
  });
15211
15323
  }
15212
15324
  if (source.format === "pdf" && targetFormat === "pptx") {
15213
15325
  const bytes = pdfToPptx(source.bytes, {
15214
15326
  signal: options.signal,
15215
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15327
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15328
+ onDocument
15216
15329
  });
15217
15330
  return Promise.resolve({
15218
15331
  document: {
15219
15332
  format: "pptx",
15220
15333
  bytes
15221
15334
  },
15222
- diagnostics
15335
+ diagnostics,
15336
+ package: documentPackage
15223
15337
  });
15224
15338
  }
15225
15339
  if (source.format === "pdf" && targetFormat === "odt") {
15226
15340
  const bytes = pdfToOdt(source.bytes, {
15227
15341
  signal: options.signal,
15228
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15342
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15343
+ onDocument
15229
15344
  });
15230
15345
  return Promise.resolve({
15231
15346
  document: {
15232
15347
  format: "odt",
15233
15348
  bytes
15234
15349
  },
15235
- diagnostics
15350
+ diagnostics,
15351
+ package: documentPackage
15236
15352
  });
15237
15353
  }
15238
15354
  if (source.format === "pdf" && targetFormat === "odp") {
15239
15355
  const bytes = pdfToOdp(source.bytes, {
15240
15356
  signal: options.signal,
15241
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15357
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15358
+ onDocument
15242
15359
  });
15243
15360
  return Promise.resolve({
15244
15361
  document: {
15245
15362
  format: "odp",
15246
15363
  bytes
15247
15364
  },
15248
- diagnostics
15365
+ diagnostics,
15366
+ package: documentPackage
15249
15367
  });
15250
15368
  }
15251
15369
  if (source.format === "pdf" && targetFormat === "ods") {
15252
15370
  const bytes = pdfToOds(source.bytes, {
15253
15371
  signal: options.signal,
15254
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15372
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15373
+ onDocument
15255
15374
  });
15256
15375
  return Promise.resolve({
15257
15376
  document: {
15258
15377
  format: "ods",
15259
15378
  bytes
15260
15379
  },
15261
- diagnostics
15380
+ diagnostics,
15381
+ package: documentPackage
15262
15382
  });
15263
15383
  }
15264
15384
  if (source.format === "pdf" && targetFormat === "odg") {
15265
15385
  const bytes = pdfToOdg(source.bytes, {
15266
15386
  signal: options.signal,
15267
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15387
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15388
+ onDocument
15268
15389
  });
15269
15390
  return Promise.resolve({
15270
15391
  document: {
15271
15392
  format: "odg",
15272
15393
  bytes
15273
15394
  },
15274
- diagnostics
15395
+ diagnostics,
15396
+ package: documentPackage
15275
15397
  });
15276
15398
  }
15277
15399
  if (source.format === "odt" && targetFormat === "docx") {
15278
- const bytes = odtToDocx(source.bytes, { signal: options.signal });
15400
+ const bytes = odtToDocx(source.bytes, {
15401
+ signal: options.signal,
15402
+ onDocument
15403
+ });
15279
15404
  return Promise.resolve({
15280
15405
  document: {
15281
15406
  format: "docx",
15282
15407
  bytes
15283
15408
  },
15284
- diagnostics
15409
+ diagnostics,
15410
+ package: documentPackage
15285
15411
  });
15286
15412
  }
15287
15413
  if (source.format === "docx" && targetFormat === "odt") {
15288
- const bytes = docxToOdt(source.bytes, { signal: options.signal });
15414
+ const bytes = docxToOdt(source.bytes, {
15415
+ signal: options.signal,
15416
+ onDocument
15417
+ });
15289
15418
  return Promise.resolve({
15290
15419
  document: {
15291
15420
  format: "odt",
15292
15421
  bytes
15293
15422
  },
15294
- diagnostics
15423
+ diagnostics,
15424
+ package: documentPackage
15295
15425
  });
15296
15426
  }
15297
15427
  if (source.format === "odp" && targetFormat === "pptx") {
15298
- const bytes = odpToPptx(source.bytes, { signal: options.signal });
15428
+ const bytes = odpToPptx(source.bytes, {
15429
+ signal: options.signal,
15430
+ onDocument
15431
+ });
15299
15432
  return Promise.resolve({
15300
15433
  document: {
15301
15434
  format: "pptx",
15302
15435
  bytes
15303
15436
  },
15304
- diagnostics
15437
+ diagnostics,
15438
+ package: documentPackage
15305
15439
  });
15306
15440
  }
15307
15441
  if (source.format === "pptx" && targetFormat === "odp") {
15308
- const bytes = pptxToOdp(source.bytes, { signal: options.signal });
15442
+ const bytes = pptxToOdp(source.bytes, {
15443
+ signal: options.signal,
15444
+ onDocument
15445
+ });
15309
15446
  return Promise.resolve({
15310
15447
  document: {
15311
15448
  format: "odp",
15312
15449
  bytes
15313
15450
  },
15314
- diagnostics
15451
+ diagnostics,
15452
+ package: documentPackage
15315
15453
  });
15316
15454
  }
15317
15455
  if (source.format === "ods" && targetFormat === "xlsx") {
15318
- const bytes = odsToXlsx(source.bytes, { signal: options.signal });
15456
+ const bytes = odsToXlsx(source.bytes, {
15457
+ signal: options.signal,
15458
+ onDocument
15459
+ });
15319
15460
  return Promise.resolve({
15320
15461
  document: {
15321
15462
  format: "xlsx",
15322
15463
  bytes
15323
15464
  },
15324
- diagnostics
15465
+ diagnostics,
15466
+ package: documentPackage
15325
15467
  });
15326
15468
  }
15327
15469
  if (source.format === "xlsx" && targetFormat === "ods") {
15328
- const bytes = xlsxToOds(source.bytes, { signal: options.signal });
15470
+ const bytes = xlsxToOds(source.bytes, {
15471
+ signal: options.signal,
15472
+ onDocument
15473
+ });
15329
15474
  return Promise.resolve({
15330
15475
  document: {
15331
15476
  format: "ods",
15332
15477
  bytes
15333
15478
  },
15334
- diagnostics
15479
+ diagnostics,
15480
+ package: documentPackage
15335
15481
  });
15336
15482
  }
15337
15483
  return Promise.reject(/* @__PURE__ */ new Error(`unsupported conversion: ${source.format} -> ${targetFormat}`));
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Attribute, AttributeSchema, BinaryPart, BinaryPartSchema, Comment, CommentSchema, CompactAttrPairs, CompactPackage, CompactPackageSchema, CompactPart, CompactPartSchema, CompactXmlNode, CompactXmlNodeSchema, DefinedName, DefinedNameSchema, Package, Package as Package$1, PackageSchema, Part, PartSchema, Relationship, XmlCdata, XmlCdataSchema, XmlComment, XmlCommentSchema, XmlDeclaration, XmlDeclarationSchema, XmlElement, XmlElement as XmlElement$1, XmlElementSchema, XmlNode, XmlNode as XmlNode$1, XmlNodeSchema, XmlPart, XmlPartSchema, XmlPi, XmlPiSchema, XmlText, XmlTextSchema, attr, base64ToBytes, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, decodeCompactPackage, decodeEntities, decodePackage, elementsWithTag, encodeCompactPackage, encodePackage, fromCompact, isCompactXmlNode, isXmlNode, packageCodec, parsePackage, parseXml, resolveRelationships, rootElement, serializePackage, textContent as textContent$1, toCompact, unzipPackage, walk, xmlCodec, zipPackage } from "ooxml.js";
2
- import { Alignment, Box, Box as Box$1, COLOR_BLACK, Color, Color as LayoutColor, ContentBlock, ContentBlockSchema, ContentCellValue, ContentCellValue as ContentCellValue$1, ContentCellValueSchema, ContentDrawPage, ContentDrawPageSchema, ContentImageBlock, ContentImageBlockSchema, ContentListMembership, ContentListMembership as ContentListMembership$1, ContentPageBreak, ContentPageBreakSchema, ContentParagraph, ContentParagraphSchema, ContentPathPoint, ContentPathPoint as ContentPathPoint$1, ContentPathPointSchema, ContentPathSegment, ContentPathSegmentSchema, ContentRun, ContentRun as ContentRun$1, ContentRunSchema, ContentSection, ContentSectionSchema, ContentShape, ContentShapeSchema, ContentSheet, ContentSheetCell, ContentSheetCellSchema, ContentSheetColumn, ContentSheetColumnSchema, ContentSheetImage, ContentSheetPrintRange, ContentSheetPrintRangeSchema, ContentSheetPrintSettings, ContentSheetPrintSettings as ContentSheetPrintSettings$1, ContentSheetPrintSettingsSchema, ContentSheetRepeatRange, ContentSheetRepeatRangeSchema, ContentSheetRow, ContentSheetRowSchema, ContentSheetSchema, ContentSlide, ContentSlideSchema, ContentStroke, ContentStroke as ContentStroke$1, ContentStrokeSchema, ContentSubpath, ContentSubpath as ContentSubpath$1, ContentSubpathSchema, ContentTable, ContentTableCell, ContentTableCellSchema, ContentTableRow, ContentTableRowSchema, ContentTableSchema, ContentVector, ContentVectorSchema, DEFAULT_LAYOUT_FONT, LAYOUT_FORMAT_VERSION, LayoutDocument, LayoutDocument as LayoutDocument$1, LayoutEllipse, LayoutFont, LayoutImage, LayoutImageAsset, LayoutItem, LayoutLine, LayoutLink, LayoutMetadata, LayoutMetadata as LayoutMetadata$1, LayoutPage, LayoutPath, LayoutPathSegment, LayoutRect, LayoutSubpath, LayoutText, Margins, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PageSize, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, isContentBlock, rgbHexToColor } from "document-content-model";
2
+ import { Alignment, Box, Box as Box$1, COLOR_BLACK, Color, Color as LayoutColor, ContentBlock, ContentBlockSchema, ContentCellValue, ContentCellValue as ContentCellValue$1, ContentCellValueSchema, ContentDrawPage, ContentDrawPageSchema, ContentImageBlock, ContentImageBlockSchema, ContentListMembership, ContentListMembership as ContentListMembership$1, ContentPageBreak, ContentPageBreakSchema, ContentParagraph, ContentParagraphSchema, ContentPathPoint, ContentPathPoint as ContentPathPoint$1, ContentPathPointSchema, ContentPathSegment, ContentPathSegmentSchema, ContentRun, ContentRun as ContentRun$1, ContentRunSchema, ContentSection, ContentSectionSchema, ContentShape, ContentShapeSchema, ContentSheet, ContentSheetCell, ContentSheetCellSchema, ContentSheetColumn, ContentSheetColumnSchema, ContentSheetImage, ContentSheetPrintRange, ContentSheetPrintRangeSchema, ContentSheetPrintSettings, ContentSheetPrintSettings as ContentSheetPrintSettings$1, ContentSheetPrintSettingsSchema, ContentSheetRepeatRange, ContentSheetRepeatRangeSchema, ContentSheetRow, ContentSheetRowSchema, ContentSheetSchema, ContentSlide, ContentSlideSchema, ContentStroke, ContentStroke as ContentStroke$1, ContentStrokeSchema, ContentSubpath, ContentSubpath as ContentSubpath$1, ContentSubpathSchema, ContentTable, ContentTableCell, ContentTableCellSchema, ContentTableRow, ContentTableRowSchema, ContentTableSchema, ContentVector, ContentVectorSchema, DEFAULT_LAYOUT_FONT, DocumentPackage, LAYOUT_FORMAT_VERSION, LayoutDocument, LayoutDocument as LayoutDocument$1, LayoutEllipse, LayoutFont, LayoutImage, LayoutImageAsset, LayoutItem, LayoutLine, LayoutLink, LayoutMetadata, LayoutMetadata as LayoutMetadata$1, LayoutPage, LayoutPath, LayoutPathSegment, LayoutRect, LayoutSubpath, LayoutText, Margins, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PageSize, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, isContentBlock, rgbHexToColor } from "document-content-model";
3
3
  import { z } from "zod";
4
4
  import { Package as Package$2, XmlElement as XmlElement$2, XmlNode as XmlNode$2 } from "odf.js";
5
5
  //#region src/model/content.d.ts
@@ -1458,6 +1458,7 @@ interface DocumentToPdfOptions {
1458
1458
  readonly onSubstitution?: (substitution: WinAnsiSubstitution, context: {
1459
1459
  readonly pageIndex: number;
1460
1460
  }) => void;
1461
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1461
1462
  }
1462
1463
  declare function docxToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPdfOptions): Uint8Array<ArrayBuffer>;
1463
1464
  declare function odtToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPdfOptions): Uint8Array<ArrayBuffer>;
@@ -1469,6 +1470,7 @@ declare function odfToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPd
1469
1470
  interface PdfToDocumentOptions {
1470
1471
  readonly signal?: AbortSignal;
1471
1472
  readonly sink?: PdfDiagnosticSink;
1473
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1472
1474
  }
1473
1475
  declare function pdfToDocx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1474
1476
  declare function pdfToPptx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
@@ -1478,6 +1480,7 @@ declare function pdfToOdg(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumen
1478
1480
  declare function pdfToOds(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1479
1481
  interface DocumentBridgeOptions {
1480
1482
  readonly signal?: AbortSignal;
1483
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1481
1484
  }
1482
1485
  declare function odtToDocx(bytes: Uint8Array<ArrayBuffer>, options?: DocumentBridgeOptions): Uint8Array<ArrayBuffer>;
1483
1486
  declare function docxToOdt(bytes: Uint8Array<ArrayBuffer>, options?: DocumentBridgeOptions): Uint8Array<ArrayBuffer>;
@@ -1572,6 +1575,7 @@ interface ConversionRequest {
1572
1575
  interface ConversionResult {
1573
1576
  readonly document: DocumentPayload;
1574
1577
  readonly diagnostics: readonly Diagnostic[];
1578
+ readonly package?: DocumentPackage;
1575
1579
  }
1576
1580
  interface DocumentConverter {
1577
1581
  readonly contractVersion: number;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Attribute, AttributeSchema, BinaryPart, BinaryPartSchema, Comment, CommentSchema, CompactAttrPairs, CompactPackage, CompactPackageSchema, CompactPart, CompactPartSchema, CompactXmlNode, CompactXmlNodeSchema, DefinedName, DefinedNameSchema, Package, Package as Package$1, PackageSchema, Part, PartSchema, Relationship, XmlCdata, XmlCdataSchema, XmlComment, XmlCommentSchema, XmlDeclaration, XmlDeclarationSchema, XmlElement, XmlElement as XmlElement$1, XmlElementSchema, XmlNode, XmlNode as XmlNode$1, XmlNodeSchema, XmlPart, XmlPartSchema, XmlPi, XmlPiSchema, XmlText, XmlTextSchema, attr, base64ToBytes, buildXml, bytesToBase64, childrenWithTag, compactCodec, compactPackageCodec, decodeCompactPackage, decodeEntities, decodePackage, elementsWithTag, encodeCompactPackage, encodePackage, fromCompact, isCompactXmlNode, isXmlNode, packageCodec, parsePackage, parseXml, resolveRelationships, rootElement, serializePackage, textContent as textContent$1, toCompact, unzipPackage, walk, xmlCodec, zipPackage } from "ooxml.js";
2
- import { Alignment, Box, Box as Box$1, COLOR_BLACK, Color, Color as LayoutColor, ContentBlock, ContentBlockSchema, ContentCellValue, ContentCellValue as ContentCellValue$1, ContentCellValueSchema, ContentDrawPage, ContentDrawPageSchema, ContentImageBlock, ContentImageBlockSchema, ContentListMembership, ContentListMembership as ContentListMembership$1, ContentPageBreak, ContentPageBreakSchema, ContentParagraph, ContentParagraphSchema, ContentPathPoint, ContentPathPoint as ContentPathPoint$1, ContentPathPointSchema, ContentPathSegment, ContentPathSegmentSchema, ContentRun, ContentRun as ContentRun$1, ContentRunSchema, ContentSection, ContentSectionSchema, ContentShape, ContentShapeSchema, ContentSheet, ContentSheetCell, ContentSheetCellSchema, ContentSheetColumn, ContentSheetColumnSchema, ContentSheetImage, ContentSheetPrintRange, ContentSheetPrintRangeSchema, ContentSheetPrintSettings, ContentSheetPrintSettings as ContentSheetPrintSettings$1, ContentSheetPrintSettingsSchema, ContentSheetRepeatRange, ContentSheetRepeatRangeSchema, ContentSheetRow, ContentSheetRowSchema, ContentSheetSchema, ContentSlide, ContentSlideSchema, ContentStroke, ContentStroke as ContentStroke$1, ContentStrokeSchema, ContentSubpath, ContentSubpath as ContentSubpath$1, ContentSubpathSchema, ContentTable, ContentTableCell, ContentTableCellSchema, ContentTableRow, ContentTableRowSchema, ContentTableSchema, ContentVector, ContentVectorSchema, DEFAULT_LAYOUT_FONT, LAYOUT_FORMAT_VERSION, LayoutDocument, LayoutDocument as LayoutDocument$1, LayoutEllipse, LayoutFont, LayoutImage, LayoutImageAsset, LayoutItem, LayoutLine, LayoutLink, LayoutMetadata, LayoutMetadata as LayoutMetadata$1, LayoutPage, LayoutPath, LayoutPathSegment, LayoutRect, LayoutSubpath, LayoutText, Margins, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PageSize, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, isContentBlock, rgbHexToColor } from "document-content-model";
2
+ import { Alignment, Box, Box as Box$1, COLOR_BLACK, Color, Color as LayoutColor, ContentBlock, ContentBlockSchema, ContentCellValue, ContentCellValue as ContentCellValue$1, ContentCellValueSchema, ContentDrawPage, ContentDrawPageSchema, ContentImageBlock, ContentImageBlockSchema, ContentListMembership, ContentListMembership as ContentListMembership$1, ContentPageBreak, ContentPageBreakSchema, ContentParagraph, ContentParagraphSchema, ContentPathPoint, ContentPathPoint as ContentPathPoint$1, ContentPathPointSchema, ContentPathSegment, ContentPathSegmentSchema, ContentRun, ContentRun as ContentRun$1, ContentRunSchema, ContentSection, ContentSectionSchema, ContentShape, ContentShapeSchema, ContentSheet, ContentSheetCell, ContentSheetCellSchema, ContentSheetColumn, ContentSheetColumnSchema, ContentSheetImage, ContentSheetPrintRange, ContentSheetPrintRangeSchema, ContentSheetPrintSettings, ContentSheetPrintSettings as ContentSheetPrintSettings$1, ContentSheetPrintSettingsSchema, ContentSheetRepeatRange, ContentSheetRepeatRangeSchema, ContentSheetRow, ContentSheetRowSchema, ContentSheetSchema, ContentSlide, ContentSlideSchema, ContentStroke, ContentStroke as ContentStroke$1, ContentStrokeSchema, ContentSubpath, ContentSubpath as ContentSubpath$1, ContentSubpathSchema, ContentTable, ContentTableCell, ContentTableCellSchema, ContentTableRow, ContentTableRowSchema, ContentTableSchema, ContentVector, ContentVectorSchema, DEFAULT_LAYOUT_FONT, DocumentPackage, LAYOUT_FORMAT_VERSION, LayoutDocument, LayoutDocument as LayoutDocument$1, LayoutEllipse, LayoutFont, LayoutImage, LayoutImageAsset, LayoutItem, LayoutLine, LayoutLink, LayoutMetadata, LayoutMetadata as LayoutMetadata$1, LayoutPage, LayoutPath, LayoutPathSegment, LayoutRect, LayoutSubpath, LayoutText, Margins, PAGE_SIZE_A4, PAGE_SIZE_LETTER, PageSize, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, isContentBlock, rgbHexToColor } from "document-content-model";
3
3
  import { z } from "zod";
4
4
  import { Package as Package$2, XmlElement as XmlElement$2, XmlNode as XmlNode$2 } from "odf.js";
5
5
  //#region src/model/content.d.ts
@@ -1458,6 +1458,7 @@ interface DocumentToPdfOptions {
1458
1458
  readonly onSubstitution?: (substitution: WinAnsiSubstitution, context: {
1459
1459
  readonly pageIndex: number;
1460
1460
  }) => void;
1461
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1461
1462
  }
1462
1463
  declare function docxToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPdfOptions): Uint8Array<ArrayBuffer>;
1463
1464
  declare function odtToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPdfOptions): Uint8Array<ArrayBuffer>;
@@ -1469,6 +1470,7 @@ declare function odfToPdf(bytes: Uint8Array<ArrayBuffer>, options?: DocumentToPd
1469
1470
  interface PdfToDocumentOptions {
1470
1471
  readonly signal?: AbortSignal;
1471
1472
  readonly sink?: PdfDiagnosticSink;
1473
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1472
1474
  }
1473
1475
  declare function pdfToDocx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1474
1476
  declare function pdfToPptx(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
@@ -1478,6 +1480,7 @@ declare function pdfToOdg(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumen
1478
1480
  declare function pdfToOds(bytes: Uint8Array<ArrayBuffer>, options?: PdfToDocumentOptions): Uint8Array<ArrayBuffer>;
1479
1481
  interface DocumentBridgeOptions {
1480
1482
  readonly signal?: AbortSignal;
1483
+ readonly onDocument?: (pkg: DocumentPackage) => void;
1481
1484
  }
1482
1485
  declare function odtToDocx(bytes: Uint8Array<ArrayBuffer>, options?: DocumentBridgeOptions): Uint8Array<ArrayBuffer>;
1483
1486
  declare function docxToOdt(bytes: Uint8Array<ArrayBuffer>, options?: DocumentBridgeOptions): Uint8Array<ArrayBuffer>;
@@ -1572,6 +1575,7 @@ interface ConversionRequest {
1572
1575
  interface ConversionResult {
1573
1576
  readonly document: DocumentPayload;
1574
1577
  readonly diagnostics: readonly Diagnostic[];
1578
+ readonly package?: DocumentPackage;
1575
1579
  }
1576
1580
  interface DocumentConverter {
1577
1581
  readonly contractVersion: number;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AttributeSchema, BinaryPartSchema, CommentSchema, CompactPackageSchema, CompactPartSchema, CompactXmlNodeSchema, DefinedNameSchema, PackageSchema, PartSchema, XmlCdataSchema, XmlCommentSchema, XmlDeclarationSchema, XmlElementSchema, XmlNodeSchema, XmlPartSchema, XmlPiSchema, XmlTextSchema, attr, attr as attr$1, base64ToBytes, base64ToBytes as base64ToBytes$1, buildXlsxPackage, buildXml, bytesToBase64, bytesToBase64 as bytesToBase64$1, childrenWithTag, compactCodec, compactPackageCodec, decodeCompactPackage, decodeEntities, decodePackage, decodePackage as decodePackage$1, elementsWithTag, elementsWithTag as elementsWithTag$1, encodeCompactPackage, encodePackage, encodePackage as encodePackage$1, fromCompact, isCompactXmlNode, isXmlNode, packageCodec, parsePackage, parseXml, readDocx, readPptx, readXlsxContent, resolveRelationships, resolveRelationships as resolveRelationships$1, rootElement, rootElement as rootElement$1, serializePackage, textContent as textContent$1, textContent as textContent$2, toCompact, unzipPackage, walk, xmlCodec, zipPackage } from "ooxml.js";
2
- import { COLOR_BLACK, COLOR_BLACK as COLOR_BLACK$1, ContentBlockSchema, ContentCellValueSchema, ContentDrawPageSchema, ContentDrawPageSchema as ContentDrawPageSchema$1, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentPathPointSchema, ContentPathSegmentSchema, ContentRunSchema, ContentSectionSchema, ContentSectionSchema as ContentSectionSchema$1, ContentShapeSchema, ContentSheetCellSchema, ContentSheetColumnSchema, ContentSheetPrintRangeSchema, ContentSheetPrintSettingsSchema, ContentSheetRepeatRangeSchema, ContentSheetRowSchema, ContentSheetSchema, ContentSheetSchema as ContentSheetSchema$1, ContentSlideSchema, ContentSlideSchema as ContentSlideSchema$1, ContentStrokeSchema, ContentSubpathSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, ContentVectorSchema, DEFAULT_LAYOUT_FONT, LAYOUT_FORMAT_VERSION, LAYOUT_FORMAT_VERSION as LAYOUT_FORMAT_VERSION$1, LayoutDocumentSchema, LayoutMetadataSchema, PAGE_SIZE_A4, PAGE_SIZE_LETTER, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, colorToRgbHex, isContentBlock, rgbHexToColor } from "document-content-model";
2
+ import { COLOR_BLACK, COLOR_BLACK as COLOR_BLACK$1, ContentBlockSchema, ContentCellValueSchema, ContentDrawPageSchema, ContentDrawPageSchema as ContentDrawPageSchema$1, ContentImageBlockSchema, ContentPageBreakSchema, ContentParagraphSchema, ContentPathPointSchema, ContentPathSegmentSchema, ContentRunSchema, ContentSectionSchema, ContentSectionSchema as ContentSectionSchema$1, ContentShapeSchema, ContentSheetCellSchema, ContentSheetColumnSchema, ContentSheetPrintRangeSchema, ContentSheetPrintSettingsSchema, ContentSheetRepeatRangeSchema, ContentSheetRowSchema, ContentSheetSchema, ContentSheetSchema as ContentSheetSchema$1, ContentSlideSchema, ContentSlideSchema as ContentSlideSchema$1, ContentStrokeSchema, ContentSubpathSchema, ContentTableCellSchema, ContentTableRowSchema, ContentTableSchema, ContentVectorSchema, DEFAULT_LAYOUT_FONT, DOCUMENT_PACKAGE_FORMAT_VERSION, LAYOUT_FORMAT_VERSION, LAYOUT_FORMAT_VERSION as LAYOUT_FORMAT_VERSION$1, LayoutDocumentSchema, LayoutMetadataSchema, PAGE_SIZE_A4, PAGE_SIZE_LETTER, SLIDE_SIZE_STANDARD, SLIDE_SIZE_WIDESCREEN, colorToRgbHex, isContentBlock, rgbHexToColor } from "document-content-model";
3
3
  import { z } from "zod";
4
4
  import { ODF_MEDIA_TYPES, StyleRegistry, applyOdfTransform, attrValue, base64ToBytes as base64ToBytes$2, buildOdfSubpaths, bytesToBase64 as bytesToBase64$2, childrenWithTag as childrenWithTag$1, decodeOdfText, decodePackage as decodePackage$2, encodePackage as encodePackage$2, findChildElement, findStyleElement, formatOdfColor, formatOdfLength, parseBox, parseCellReference, parseLinePoints, parseMargins, parseOdfColor, parseOdfLength, parseOdfPathData, parseOdfViewBox, parsePageSize, readDrawFrame, readManifest, readOdbInventory, readOdfFormula, readOdfMetadata, readOdfParagraph, readOdfTable, readOdg, readOdm, readOdp, readOds, readOdt, resolveOdfShapeGeometry, resolvePageLayoutProperties, resolveStyle, rootElement as rootElement$2, setDocumentMediaType, syncManifest, syncManifest as syncManifest$1, xmlnsAttributes } from "odf.js";
5
5
  import { Unzlib, inflateSync, unzlibSync, zlibSync } from "fflate";
@@ -14690,6 +14690,11 @@ function docxToPdf(bytes, options) {
14690
14690
  const content = readDocxContent(openDocx(bytes).toPackage());
14691
14691
  if (content.kind !== "wordprocessing") throw new Error("readDocxContent returned a non-wordprocessing ContentDocument");
14692
14692
  const { document: layout, formulas } = convertWordprocessingToLayout(content, { measurer: createStandardFontMeasurer() });
14693
+ options?.onDocument?.({
14694
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14695
+ content,
14696
+ layout
14697
+ });
14693
14698
  return writePdf(layout, {
14694
14699
  signal: options?.signal,
14695
14700
  onSubstitution: options?.onSubstitution,
@@ -14703,6 +14708,11 @@ function odtToPdf(bytes, options) {
14703
14708
  measurer: createStandardFontMeasurer(),
14704
14709
  formulas: content.formulas
14705
14710
  });
14711
+ options?.onDocument?.({
14712
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14713
+ content: content.document,
14714
+ layout
14715
+ });
14706
14716
  return writePdf(layout, {
14707
14717
  signal: options?.signal,
14708
14718
  onSubstitution: options?.onSubstitution,
@@ -14713,6 +14723,11 @@ function pptxToPdf(bytes, options) {
14713
14723
  const content = readPptxContent(openPptx(bytes).toPackage());
14714
14724
  if (content.kind !== "presentation") throw new Error("readPptxContent returned a non-presentation ContentDocument");
14715
14725
  const { document: layout } = convertPresentationToLayout(content, { measurer: createStandardFontMeasurer() });
14726
+ options?.onDocument?.({
14727
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14728
+ content,
14729
+ layout
14730
+ });
14716
14731
  return writePdf(layout, {
14717
14732
  signal: options?.signal,
14718
14733
  onSubstitution: options?.onSubstitution
@@ -14725,6 +14740,11 @@ function odpToPdf(bytes, options) {
14725
14740
  measurer: createStandardFontMeasurer(),
14726
14741
  formulas: content.formulas
14727
14742
  });
14743
+ options?.onDocument?.({
14744
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14745
+ content: content.document,
14746
+ layout
14747
+ });
14728
14748
  return writePdf(layout, {
14729
14749
  signal: options?.signal,
14730
14750
  onSubstitution: options?.onSubstitution,
@@ -14734,10 +14754,16 @@ function odpToPdf(bytes, options) {
14734
14754
  function odsToPdf(bytes, options) {
14735
14755
  const content = readOdsContent(decodePackage$2(bytes));
14736
14756
  if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
14737
- return writePdf(convertSpreadsheetToLayout(content, {
14757
+ const layout = convertSpreadsheetToLayout(content, {
14738
14758
  measurer: createStandardFontMeasurer(),
14739
14759
  signal: options?.signal
14740
- }), {
14760
+ });
14761
+ options?.onDocument?.({
14762
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14763
+ content,
14764
+ layout
14765
+ });
14766
+ return writePdf(layout, {
14741
14767
  signal: options?.signal,
14742
14768
  onSubstitution: options?.onSubstitution
14743
14769
  });
@@ -14745,7 +14771,13 @@ function odsToPdf(bytes, options) {
14745
14771
  function odgToPdf(bytes, options) {
14746
14772
  const content = readOdgContent(decodePackage$2(bytes));
14747
14773
  if (content.kind !== "drawing") throw new Error("readOdgContent returned a non-drawing ContentDocument");
14748
- return writePdf(convertDrawingToLayout(content, { measurer: createStandardFontMeasurer() }), {
14774
+ const layout = convertDrawingToLayout(content, { measurer: createStandardFontMeasurer() });
14775
+ options?.onDocument?.({
14776
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14777
+ content,
14778
+ layout
14779
+ });
14780
+ return writePdf(layout, {
14749
14781
  signal: options?.signal,
14750
14782
  onSubstitution: options?.onSubstitution
14751
14783
  });
@@ -14789,45 +14821,81 @@ function odfToPdf(bytes, options) {
14789
14821
  });
14790
14822
  }
14791
14823
  function pdfToDocx(bytes, options) {
14792
- const content = reconstructWordprocessing(readPdf(bytes, {
14824
+ const layout = readPdf(bytes, {
14793
14825
  signal: options?.signal,
14794
14826
  sink: options?.sink
14795
- }), { signal: options?.signal });
14827
+ });
14828
+ const content = reconstructWordprocessing(layout, { signal: options?.signal });
14829
+ options?.onDocument?.({
14830
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14831
+ content,
14832
+ layout
14833
+ });
14796
14834
  return encodePackage$1(buildDocxPackage(content));
14797
14835
  }
14798
14836
  function pdfToPptx(bytes, options) {
14799
- const content = reconstructPresentation(readPdf(bytes, {
14837
+ const layout = readPdf(bytes, {
14800
14838
  signal: options?.signal,
14801
14839
  sink: options?.sink
14802
- }), { signal: options?.signal });
14840
+ });
14841
+ const content = reconstructPresentation(layout, { signal: options?.signal });
14842
+ options?.onDocument?.({
14843
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14844
+ content,
14845
+ layout
14846
+ });
14803
14847
  return encodePackage$1(buildPptxPackage(content));
14804
14848
  }
14805
14849
  function pdfToOdt(bytes, options) {
14806
- const content = reconstructWordprocessing(readPdf(bytes, {
14850
+ const layout = readPdf(bytes, {
14807
14851
  signal: options?.signal,
14808
14852
  sink: options?.sink
14809
- }), { signal: options?.signal });
14853
+ });
14854
+ const content = reconstructWordprocessing(layout, { signal: options?.signal });
14855
+ options?.onDocument?.({
14856
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14857
+ content,
14858
+ layout
14859
+ });
14810
14860
  return encodePackage$2(buildOdtPackage(content));
14811
14861
  }
14812
14862
  function pdfToOdp(bytes, options) {
14813
- const content = reconstructPresentation(readPdf(bytes, {
14863
+ const layout = readPdf(bytes, {
14814
14864
  signal: options?.signal,
14815
14865
  sink: options?.sink
14816
- }), { signal: options?.signal });
14866
+ });
14867
+ const content = reconstructPresentation(layout, { signal: options?.signal });
14868
+ options?.onDocument?.({
14869
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14870
+ content,
14871
+ layout
14872
+ });
14817
14873
  return encodePackage$2(buildOdpPackage(content));
14818
14874
  }
14819
14875
  function pdfToOdg(bytes, options) {
14820
- const content = reconstructDrawing(readPdf(bytes, {
14876
+ const layout = readPdf(bytes, {
14821
14877
  signal: options?.signal,
14822
14878
  sink: options?.sink
14823
- }), { signal: options?.signal });
14879
+ });
14880
+ const content = reconstructDrawing(layout, { signal: options?.signal });
14881
+ options?.onDocument?.({
14882
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14883
+ content,
14884
+ layout
14885
+ });
14824
14886
  return encodePackage$2(buildOdgPackage(content));
14825
14887
  }
14826
14888
  function pdfToOds(bytes, options) {
14827
- const content = reconstructSpreadsheet(readPdf(bytes, {
14889
+ const layout = readPdf(bytes, {
14828
14890
  signal: options?.signal,
14829
14891
  sink: options?.sink
14830
- }), { signal: options?.signal });
14892
+ });
14893
+ const content = reconstructSpreadsheet(layout, { signal: options?.signal });
14894
+ options?.onDocument?.({
14895
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14896
+ content,
14897
+ layout
14898
+ });
14831
14899
  return encodePackage$2(buildOdsPackage(content));
14832
14900
  }
14833
14901
  function odtToDocx(bytes, options) {
@@ -14835,6 +14903,10 @@ function odtToDocx(bytes, options) {
14835
14903
  const content = readOdtContent(decodePackage$2(bytes)).document;
14836
14904
  if (content.kind !== "wordprocessing") throw new Error("readOdtContent returned a non-wordprocessing ContentDocument");
14837
14905
  throwIfAborted(options?.signal);
14906
+ options?.onDocument?.({
14907
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14908
+ content
14909
+ });
14838
14910
  return encodePackage$1(buildDocxPackage(content));
14839
14911
  }
14840
14912
  function docxToOdt(bytes, options) {
@@ -14842,6 +14914,10 @@ function docxToOdt(bytes, options) {
14842
14914
  const content = readDocxContent(decodePackage$1(bytes));
14843
14915
  if (content.kind !== "wordprocessing") throw new Error("readDocxContent returned a non-wordprocessing ContentDocument");
14844
14916
  throwIfAborted(options?.signal);
14917
+ options?.onDocument?.({
14918
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14919
+ content
14920
+ });
14845
14921
  return encodePackage$2(buildOdtPackage(content));
14846
14922
  }
14847
14923
  function odpToPptx(bytes, options) {
@@ -14849,6 +14925,10 @@ function odpToPptx(bytes, options) {
14849
14925
  const content = readOdpContent(decodePackage$2(bytes)).document;
14850
14926
  if (content.kind !== "presentation") throw new Error("readOdpContent returned a non-presentation ContentDocument");
14851
14927
  throwIfAborted(options?.signal);
14928
+ options?.onDocument?.({
14929
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14930
+ content
14931
+ });
14852
14932
  return encodePackage$1(buildPptxPackage(content));
14853
14933
  }
14854
14934
  function pptxToOdp(bytes, options) {
@@ -14856,6 +14936,10 @@ function pptxToOdp(bytes, options) {
14856
14936
  const content = readPptxContent(decodePackage$1(bytes));
14857
14937
  if (content.kind !== "presentation") throw new Error("readPptxContent returned a non-presentation ContentDocument");
14858
14938
  throwIfAborted(options?.signal);
14939
+ options?.onDocument?.({
14940
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14941
+ content
14942
+ });
14859
14943
  return encodePackage$2(buildOdpPackage(content));
14860
14944
  }
14861
14945
  function odsToXlsx(bytes, options) {
@@ -14863,6 +14947,10 @@ function odsToXlsx(bytes, options) {
14863
14947
  const content = readOdsContent(decodePackage$2(bytes));
14864
14948
  if (content.kind !== "spreadsheet") throw new Error("readOdsContent returned a non-spreadsheet ContentDocument");
14865
14949
  throwIfAborted(options?.signal);
14950
+ options?.onDocument?.({
14951
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14952
+ content
14953
+ });
14866
14954
  return encodePackage$1(buildXlsxPackage(content));
14867
14955
  }
14868
14956
  function xlsxToOds(bytes, options) {
@@ -14871,6 +14959,10 @@ function xlsxToOds(bytes, options) {
14871
14959
  const content = readXlsxContent(pkg);
14872
14960
  if (content.kind !== "spreadsheet") throw new Error("readXlsxContent returned a non-spreadsheet ContentDocument");
14873
14961
  throwIfAborted(options?.signal);
14962
+ options?.onDocument?.({
14963
+ formatVersion: DOCUMENT_PACKAGE_FORMAT_VERSION,
14964
+ content
14965
+ });
14874
14966
  return encodePackage$2(buildOdsPackage(content));
14875
14967
  }
14876
14968
  var OdmUnresolvedSectionError = class extends Error {
@@ -15099,238 +15191,292 @@ function fromPdfDiagnostic(diagnostic) {
15099
15191
  }
15100
15192
  function createLocalDocumentConverter() {
15101
15193
  return {
15102
- contractVersion: 1,
15194
+ contractVersion: 2,
15103
15195
  conversions: SUPPORTED_CONVERSIONS,
15104
15196
  convert(request, options) {
15105
15197
  const { source, targetFormat } = request;
15106
15198
  const diagnostics = [];
15199
+ let documentPackage;
15200
+ const onDocument = (pkg) => {
15201
+ documentPackage = pkg;
15202
+ };
15107
15203
  if (source.format === "docx" && targetFormat === "pdf") {
15108
15204
  const bytes = docxToPdf(source.bytes, {
15109
15205
  signal: options.signal,
15110
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15206
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15207
+ onDocument
15111
15208
  });
15112
15209
  return Promise.resolve({
15113
15210
  document: {
15114
15211
  format: "pdf",
15115
15212
  bytes
15116
15213
  },
15117
- diagnostics
15214
+ diagnostics,
15215
+ package: documentPackage
15118
15216
  });
15119
15217
  }
15120
15218
  if (source.format === "pptx" && targetFormat === "pdf") {
15121
15219
  const bytes = pptxToPdf(source.bytes, {
15122
15220
  signal: options.signal,
15123
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15221
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15222
+ onDocument
15124
15223
  });
15125
15224
  return Promise.resolve({
15126
15225
  document: {
15127
15226
  format: "pdf",
15128
15227
  bytes
15129
15228
  },
15130
- diagnostics
15229
+ diagnostics,
15230
+ package: documentPackage
15131
15231
  });
15132
15232
  }
15133
15233
  if (source.format === "odt" && targetFormat === "pdf") {
15134
15234
  const bytes = odtToPdf(source.bytes, {
15135
15235
  signal: options.signal,
15136
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15236
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15237
+ onDocument
15137
15238
  });
15138
15239
  return Promise.resolve({
15139
15240
  document: {
15140
15241
  format: "pdf",
15141
15242
  bytes
15142
15243
  },
15143
- diagnostics
15244
+ diagnostics,
15245
+ package: documentPackage
15144
15246
  });
15145
15247
  }
15146
15248
  if (source.format === "odp" && targetFormat === "pdf") {
15147
15249
  const bytes = odpToPdf(source.bytes, {
15148
15250
  signal: options.signal,
15149
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15251
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15252
+ onDocument
15150
15253
  });
15151
15254
  return Promise.resolve({
15152
15255
  document: {
15153
15256
  format: "pdf",
15154
15257
  bytes
15155
15258
  },
15156
- diagnostics
15259
+ diagnostics,
15260
+ package: documentPackage
15157
15261
  });
15158
15262
  }
15159
15263
  if (source.format === "ods" && targetFormat === "pdf") {
15160
15264
  const bytes = odsToPdf(source.bytes, {
15161
15265
  signal: options.signal,
15162
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15266
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15267
+ onDocument
15163
15268
  });
15164
15269
  return Promise.resolve({
15165
15270
  document: {
15166
15271
  format: "pdf",
15167
15272
  bytes
15168
15273
  },
15169
- diagnostics
15274
+ diagnostics,
15275
+ package: documentPackage
15170
15276
  });
15171
15277
  }
15172
15278
  if (source.format === "odg" && targetFormat === "pdf") {
15173
15279
  const bytes = odgToPdf(source.bytes, {
15174
15280
  signal: options.signal,
15175
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15281
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15282
+ onDocument
15176
15283
  });
15177
15284
  return Promise.resolve({
15178
15285
  document: {
15179
15286
  format: "pdf",
15180
15287
  bytes
15181
15288
  },
15182
- diagnostics
15289
+ diagnostics,
15290
+ package: documentPackage
15183
15291
  });
15184
15292
  }
15185
15293
  if (source.format === "odf" && targetFormat === "pdf") {
15186
15294
  const bytes = odfToPdf(source.bytes, {
15187
15295
  signal: options.signal,
15188
- onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c))
15296
+ onSubstitution: (s, c) => diagnostics.push(substitutionDiagnostic(s, c)),
15297
+ onDocument
15189
15298
  });
15190
15299
  return Promise.resolve({
15191
15300
  document: {
15192
15301
  format: "pdf",
15193
15302
  bytes
15194
15303
  },
15195
- diagnostics
15304
+ diagnostics,
15305
+ package: documentPackage
15196
15306
  });
15197
15307
  }
15198
15308
  if (source.format === "pdf" && targetFormat === "docx") {
15199
15309
  const bytes = pdfToDocx(source.bytes, {
15200
15310
  signal: options.signal,
15201
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15311
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15312
+ onDocument
15202
15313
  });
15203
15314
  return Promise.resolve({
15204
15315
  document: {
15205
15316
  format: "docx",
15206
15317
  bytes
15207
15318
  },
15208
- diagnostics
15319
+ diagnostics,
15320
+ package: documentPackage
15209
15321
  });
15210
15322
  }
15211
15323
  if (source.format === "pdf" && targetFormat === "pptx") {
15212
15324
  const bytes = pdfToPptx(source.bytes, {
15213
15325
  signal: options.signal,
15214
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15326
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15327
+ onDocument
15215
15328
  });
15216
15329
  return Promise.resolve({
15217
15330
  document: {
15218
15331
  format: "pptx",
15219
15332
  bytes
15220
15333
  },
15221
- diagnostics
15334
+ diagnostics,
15335
+ package: documentPackage
15222
15336
  });
15223
15337
  }
15224
15338
  if (source.format === "pdf" && targetFormat === "odt") {
15225
15339
  const bytes = pdfToOdt(source.bytes, {
15226
15340
  signal: options.signal,
15227
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15341
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15342
+ onDocument
15228
15343
  });
15229
15344
  return Promise.resolve({
15230
15345
  document: {
15231
15346
  format: "odt",
15232
15347
  bytes
15233
15348
  },
15234
- diagnostics
15349
+ diagnostics,
15350
+ package: documentPackage
15235
15351
  });
15236
15352
  }
15237
15353
  if (source.format === "pdf" && targetFormat === "odp") {
15238
15354
  const bytes = pdfToOdp(source.bytes, {
15239
15355
  signal: options.signal,
15240
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15356
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15357
+ onDocument
15241
15358
  });
15242
15359
  return Promise.resolve({
15243
15360
  document: {
15244
15361
  format: "odp",
15245
15362
  bytes
15246
15363
  },
15247
- diagnostics
15364
+ diagnostics,
15365
+ package: documentPackage
15248
15366
  });
15249
15367
  }
15250
15368
  if (source.format === "pdf" && targetFormat === "ods") {
15251
15369
  const bytes = pdfToOds(source.bytes, {
15252
15370
  signal: options.signal,
15253
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15371
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15372
+ onDocument
15254
15373
  });
15255
15374
  return Promise.resolve({
15256
15375
  document: {
15257
15376
  format: "ods",
15258
15377
  bytes
15259
15378
  },
15260
- diagnostics
15379
+ diagnostics,
15380
+ package: documentPackage
15261
15381
  });
15262
15382
  }
15263
15383
  if (source.format === "pdf" && targetFormat === "odg") {
15264
15384
  const bytes = pdfToOdg(source.bytes, {
15265
15385
  signal: options.signal,
15266
- sink: (d) => diagnostics.push(fromPdfDiagnostic(d))
15386
+ sink: (d) => diagnostics.push(fromPdfDiagnostic(d)),
15387
+ onDocument
15267
15388
  });
15268
15389
  return Promise.resolve({
15269
15390
  document: {
15270
15391
  format: "odg",
15271
15392
  bytes
15272
15393
  },
15273
- diagnostics
15394
+ diagnostics,
15395
+ package: documentPackage
15274
15396
  });
15275
15397
  }
15276
15398
  if (source.format === "odt" && targetFormat === "docx") {
15277
- const bytes = odtToDocx(source.bytes, { signal: options.signal });
15399
+ const bytes = odtToDocx(source.bytes, {
15400
+ signal: options.signal,
15401
+ onDocument
15402
+ });
15278
15403
  return Promise.resolve({
15279
15404
  document: {
15280
15405
  format: "docx",
15281
15406
  bytes
15282
15407
  },
15283
- diagnostics
15408
+ diagnostics,
15409
+ package: documentPackage
15284
15410
  });
15285
15411
  }
15286
15412
  if (source.format === "docx" && targetFormat === "odt") {
15287
- const bytes = docxToOdt(source.bytes, { signal: options.signal });
15413
+ const bytes = docxToOdt(source.bytes, {
15414
+ signal: options.signal,
15415
+ onDocument
15416
+ });
15288
15417
  return Promise.resolve({
15289
15418
  document: {
15290
15419
  format: "odt",
15291
15420
  bytes
15292
15421
  },
15293
- diagnostics
15422
+ diagnostics,
15423
+ package: documentPackage
15294
15424
  });
15295
15425
  }
15296
15426
  if (source.format === "odp" && targetFormat === "pptx") {
15297
- const bytes = odpToPptx(source.bytes, { signal: options.signal });
15427
+ const bytes = odpToPptx(source.bytes, {
15428
+ signal: options.signal,
15429
+ onDocument
15430
+ });
15298
15431
  return Promise.resolve({
15299
15432
  document: {
15300
15433
  format: "pptx",
15301
15434
  bytes
15302
15435
  },
15303
- diagnostics
15436
+ diagnostics,
15437
+ package: documentPackage
15304
15438
  });
15305
15439
  }
15306
15440
  if (source.format === "pptx" && targetFormat === "odp") {
15307
- const bytes = pptxToOdp(source.bytes, { signal: options.signal });
15441
+ const bytes = pptxToOdp(source.bytes, {
15442
+ signal: options.signal,
15443
+ onDocument
15444
+ });
15308
15445
  return Promise.resolve({
15309
15446
  document: {
15310
15447
  format: "odp",
15311
15448
  bytes
15312
15449
  },
15313
- diagnostics
15450
+ diagnostics,
15451
+ package: documentPackage
15314
15452
  });
15315
15453
  }
15316
15454
  if (source.format === "ods" && targetFormat === "xlsx") {
15317
- const bytes = odsToXlsx(source.bytes, { signal: options.signal });
15455
+ const bytes = odsToXlsx(source.bytes, {
15456
+ signal: options.signal,
15457
+ onDocument
15458
+ });
15318
15459
  return Promise.resolve({
15319
15460
  document: {
15320
15461
  format: "xlsx",
15321
15462
  bytes
15322
15463
  },
15323
- diagnostics
15464
+ diagnostics,
15465
+ package: documentPackage
15324
15466
  });
15325
15467
  }
15326
15468
  if (source.format === "xlsx" && targetFormat === "ods") {
15327
- const bytes = xlsxToOds(source.bytes, { signal: options.signal });
15469
+ const bytes = xlsxToOds(source.bytes, {
15470
+ signal: options.signal,
15471
+ onDocument
15472
+ });
15328
15473
  return Promise.resolve({
15329
15474
  document: {
15330
15475
  format: "ods",
15331
15476
  bytes
15332
15477
  },
15333
- diagnostics
15478
+ diagnostics,
15479
+ package: documentPackage
15334
15480
  });
15335
15481
  }
15336
15482
  return Promise.reject(/* @__PURE__ */ new Error(`unsupported conversion: ${source.format} -> ${targetFormat}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "documents.js",
3
- "version": "1.51.0",
3
+ "version": "1.52.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": {
@@ -64,7 +64,7 @@
64
64
  "license": "MIT",
65
65
  "packageManager": "pnpm@11.6.0",
66
66
  "dependencies": {
67
- "document-content-model": "^1.3.0",
67
+ "document-content-model": "^1.4.0",
68
68
  "fflate": "^0.8.3",
69
69
  "odf.js": "^1.10.0",
70
70
  "ooxml.js": "^2.2.0",