documents.js 4.0.26 → 4.1.1

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.
Files changed (64) hide show
  1. package/README.md +10 -2
  2. package/dist/cell-typing-CEWlywIc.d.cts +22 -0
  3. package/dist/cell-typing-CEWlywIc.d.ts +22 -0
  4. package/dist/convert/codec.cjs +11 -10
  5. package/dist/convert/codec.js +2 -1
  6. package/dist/convert/composition-to-pdf.cjs +133 -0
  7. package/dist/convert/composition-to-pdf.d.cts +7 -0
  8. package/dist/convert/composition-to-pdf.d.ts +7 -0
  9. package/dist/convert/composition-to-pdf.js +131 -0
  10. package/dist/convert/composition.cjs +26 -127
  11. package/dist/convert/composition.d.cts +14 -4
  12. package/dist/convert/composition.d.ts +14 -4
  13. package/dist/convert/composition.js +20 -126
  14. package/dist/convert/convert.cjs +35 -75
  15. package/dist/convert/convert.d.cts +5 -20
  16. package/dist/convert/convert.d.ts +5 -20
  17. package/dist/convert/convert.js +2 -32
  18. package/dist/convert/from-pdf.cjs +44 -0
  19. package/dist/convert/from-pdf.d.cts +21 -0
  20. package/dist/convert/from-pdf.d.ts +21 -0
  21. package/dist/convert/from-pdf.js +34 -0
  22. package/dist/convert/local.cjs +2 -1
  23. package/dist/convert/local.js +2 -1
  24. package/dist/csv/read.d.cts +1 -1
  25. package/dist/csv/read.d.ts +1 -1
  26. package/dist/diagnostics-DVAXKgcf.d.cts +10 -0
  27. package/dist/diagnostics-DVAXKgcf.d.ts +10 -0
  28. package/dist/fonts/registry.d.cts +1 -19
  29. package/dist/fonts/registry.d.ts +1 -19
  30. package/dist/hsqldb/binary-script.d.cts +1 -1
  31. package/dist/hsqldb/binary-script.d.ts +1 -1
  32. package/dist/hsqldb/cache.d.cts +1 -1
  33. package/dist/hsqldb/cache.d.ts +1 -1
  34. package/dist/hsqldb/rowformat.d.cts +1 -24
  35. package/dist/hsqldb/rowformat.d.ts +1 -24
  36. package/dist/index.cjs +13 -11
  37. package/dist/index.d.cts +8 -6
  38. package/dist/index.d.ts +8 -6
  39. package/dist/index.js +4 -2
  40. package/dist/layout/cell-typing.d.cts +1 -21
  41. package/dist/layout/cell-typing.d.ts +1 -21
  42. package/dist/layout/reconstruct.cjs +4 -3
  43. package/dist/layout/reconstruct.d.cts +1 -1
  44. package/dist/layout/reconstruct.d.ts +1 -1
  45. package/dist/layout/reconstruct.js +2 -1
  46. package/dist/layout/shared.cjs +2 -2
  47. package/dist/layout/shared.js +1 -1
  48. package/dist/odb/read.d.cts +1 -1
  49. package/dist/odb/read.d.ts +1 -1
  50. package/dist/odb/report/content.d.cts +1 -1
  51. package/dist/odb/report/content.d.ts +1 -1
  52. package/dist/odb/report/source.d.cts +1 -1
  53. package/dist/odb/report/source.d.ts +1 -1
  54. package/dist/registry-BcBT-bnX.d.cts +20 -0
  55. package/dist/registry-D1Pu5XxB.d.ts +20 -0
  56. package/dist/rowformat-Cl2exlEh.d.cts +25 -0
  57. package/dist/rowformat-Cl2exlEh.d.ts +25 -0
  58. package/dist/svg/diagnostics.d.cts +1 -9
  59. package/dist/svg/diagnostics.d.ts +1 -9
  60. package/dist/svg/read.d.cts +1 -1
  61. package/dist/svg/read.d.ts +1 -1
  62. package/dist/svg/write.d.cts +1 -1
  63. package/dist/svg/write.d.ts +1 -1
  64. package/package.json +21 -6
package/README.md CHANGED
@@ -252,6 +252,14 @@ import { emuToPt } from 'documents.js/model/units';
252
252
  import { buildOdtPackage } from 'documents.js/edit/odt/content';
253
253
  ```
254
254
 
255
+ One subpath is a declared entry point in its own right: **`documents.js/read`** (an explicit `exports` entry onto `src/convert/from-pdf.ts`, where the `pdfTo*` family lives). A consumer that only ever converts FROM pdf and imports the root barrel statically reaches every X-to-PDF renderer — and through pdf-codec's root barrel, ~2.9 MB of vendored font binaries it can never execute, which on Cloudflare Workers' free plan (3 MB gzipped for an entire Worker) is most of the budget. The read entry's module graph provably excludes them, all the way across the workspace boundary into pdf-codec's own source:
256
+
257
+ ```ts
258
+ import { pdfToMarkdown } from 'documents.js/read';
259
+ ```
260
+
261
+ It carries the ten `pdfTo*` conversions and `PdfToDocumentOptions` — identical functions to the root barrel's (the same forwarders, run through the composition engine's read half), never a forked behaviour; `convertDocument` and every X-to-PDF direction stay on the root barrel. `src/read-graph.test.ts` walks the entry's static import graph, follows `pdf-codec` specifiers through that package's real `exports` map into its source, and fails the build if the write path or any font asset becomes reachable.
262
+
255
263
  ### Reading and building xlsx content directly
256
264
 
257
265
  Every other content format has its own standalone `readXContent`-shaped entry point (`readDocxContent`, `readPptxContent`, `readOdtContent`, `readOdpContent`, `readOdsContent`, `readOdgContent`) — xlsx is no longer the exception. `readXlsxContent`/`buildXlsxPackage` are this package's names for `ooxml.js`'s own spreadsheet `ContentDocument` read/build pair — the same one the `ods⇄xlsx` bridge and every xlsx metadata-rebuild path already use internally — re-exported here directly rather than wrapped, since `readXlsxContent` already produces the right shape on its own. (Since `ooxml.js` 4.0.0 the upstream flat builder is named `buildXlsxPackageFromContent` — the bare `buildXlsxPackage` name moved to that package's tree-form `DocumentPackage` builder — so this package re-exports the flat builder under its own long-standing `buildXlsxPackage` name and the `ContentDocument`-in/`Package`-out contract is unchanged.) csv's `readCsvContent`/`buildCsvText` are the same kind of directly-exported stage pair, one level further in: they operate on RFC 4180 text rather than a decoded package (see `src/csv/` under Architecture). svg's `readSvgContent`/`buildSvgText` are the drawing-variant counterpart of csv's pair, operating on SVG text rather than a decoded package (see `src/svg/` under Architecture).
@@ -559,7 +567,7 @@ The package is layered from generic primitives outward to the two conversion dir
559
567
  - **`src/hsqldb/`** — `.odb` decoders, four tiers: `script.ts` (TEXT-script DDL/DML parser), `rowformat.ts`/`cache.ts` (CACHED binary row-store), `binary-script.ts` (BINARY/COMPRESSED whole-script). All import only `document-schema.js` — no odf.js knowledge.
560
568
  - **`src/firebird/`** — Tier 3: gbak logical-backup reader. `reader.ts` (attribute framing + RLE decompression + XDR decoding), `schema.ts`/`data.ts` (table/row walking). No ratified spec — built against Firebird's own engine source.
561
569
  - **`src/odb/`** — decoder-selection and pivot-mapping: `read.ts` routes to the right tier, `spreadsheet.ts`/`csv.ts` map to output formats. `odb/sql/` is the bounded SQL engine, `odb/formula/` is the rpt formula engine, `odb/report/` is the renderer, `odb/values.ts` is shared comparison/aggregation semantics.
562
- - **`src/convert/`** — the composition layer: `convert.ts` (all named functions + `convertDocument` + `resolveCompositionPlan`), `composition.ts` (the pathfinder and primitive registry), `codec.ts` (`z.codec()` pairs), `port.ts`/`local.ts` (the `DocumentConverter` port), `variant-bridges.ts` (cross-variant semantic transforms), and `from-package.ts` (`buildDocumentBytes`, which flattens once at the boundary). The tree ⇄ flat transform those construction sites call — `assemblePackage`, `decompose`, `flattenPackage`, `factorStyles` — is not implemented here: it lives in `document-schema.js`, which owns both encodings. `bijection.test.ts` is this package's own gate on it, re-running the three laws over the real corpus every reader, editor, and conversion here produces.
570
+ - **`src/convert/`** — the composition layer: `convert.ts` (the named conversion functions and their option types), `composition.ts` (the pathfinder, the primitive registry, the bridge/fromPdf executors, and `convertDocumentFromPdf` — the read half of the engine), `composition-to-pdf.ts` (`executeToPdf`, the layout-engine registry, and the full `convertDocument` binding — the write half, split out so a read-only consumer never statically imports a renderer), `from-pdf.ts` (the `pdfTo*` family and the `documents.js/read` entry), `codec.ts` (`z.codec()` pairs), `port.ts`/`local.ts` (the `DocumentConverter` port), `variant-bridges.ts` (cross-variant semantic transforms), and `from-package.ts` (`buildDocumentBytes`, which flattens once at the boundary). The tree ⇄ flat transform those construction sites call — `assemblePackage`, `decompose`, `flattenPackage`, `factorStyles` — is not implemented here: it lives in `document-schema.js`, which owns both encodings. `bijection.test.ts` is this package's own gate on it, re-running the three laws over the real corpus every reader, editor, and conversion here produces.
563
571
  - **`src/codecs/`** — `DOCUMENT_FORMAT_CODECS`: every format's read/build capability as data, so `readDocumentMetadata`/`setDocumentMetadata`/`buildDocumentBytes` dispatch through one registry.
564
572
  - **`src/metadata/`** — cross-format metadata read/write via `DOCUMENT_FORMAT_CODECS`.
565
573
  - **`src/package-codec.ts`** — `decodeDocumentPackage`/`encodeDocumentPackage`/`decodeOdbPackage`.
@@ -589,7 +597,7 @@ To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
589
597
  - **Live views, not flatten-and-regenerate.** Editor classes hold a reference into the real `Package`/`XmlElement` objects; saving is `encodePackage(pkg)`.
590
598
  - **Three-tier PDF-read failure policy** — throw for unprocessable files, recover-with-diagnostic for malformed-but-salvageable, degrade-with-diagnostic for unsupported features. See pdf-codec's README.
591
599
  - **Conventional commits**, enforced via commitlint + husky.
592
- - **Worker-isomorphic runtime.** `src/` is typechecked against a web-only environment (`lib: ["ES2024", "WebWorker"]`, no `@types/node`); `eslint` bans Node-only imports/globals; `test:workers` proves PDF-bypassing paths run in `workerd`.
600
+ - **Worker-isomorphic runtime.** `src/` is typechecked against a web-only environment (`lib: ["ES2024", "WebWorker"]`, no `@types/node`); `eslint` bans Node-only imports/globals; `test:workers` proves both the PDF-bypassing paths and the PDF pivot itself (`pdfToMarkdown` through the read-only entry module, `markdownToPdf` through the full write path) run in `workerd`.
593
601
 
594
602
  ## Gotchas and quirks
595
603
 
@@ -0,0 +1,22 @@
1
+ import { ContentCellValue } from "document-schema.js";
2
+ //#region src/layout/cell-typing.d.ts
3
+ type CellTypeRule = 'boolean-literal' | 'iso-date' | 'named-month-date' | 'plain-number' | 'grouped-number' | 'percentage' | 'currency';
4
+ type CellTypeDeclineReason = 'ambiguous-boolean-word' | 'ambiguous-date-order' | 'ambiguous-grouping-separator' | 'leading-zero-digits' | 'precision-loss';
5
+ type CellTypeInferenceResult = {
6
+ readonly outcome: 'retyped';
7
+ readonly value: ContentCellValue;
8
+ readonly rule: CellTypeRule;
9
+ } | {
10
+ readonly outcome: 'declined';
11
+ readonly reason: CellTypeDeclineReason;
12
+ };
13
+ type CellTypeInference = {
14
+ readonly sheetIndex: number;
15
+ readonly row: number;
16
+ readonly column: number;
17
+ readonly displayText: string;
18
+ } & CellTypeInferenceResult;
19
+ type CellTypeInferenceSink = (inference: CellTypeInference) => void;
20
+ declare function inferCellValue(displayText: string): CellTypeInferenceResult | undefined;
21
+ //#endregion
22
+ export { CellTypeRule as a, CellTypeInferenceSink as i, CellTypeInference as n, inferCellValue as o, CellTypeInferenceResult as r, CellTypeDeclineReason as t };
@@ -0,0 +1,22 @@
1
+ import { ContentCellValue } from "document-schema.js";
2
+ //#region src/layout/cell-typing.d.ts
3
+ type CellTypeRule = 'boolean-literal' | 'iso-date' | 'named-month-date' | 'plain-number' | 'grouped-number' | 'percentage' | 'currency';
4
+ type CellTypeDeclineReason = 'ambiguous-boolean-word' | 'ambiguous-date-order' | 'ambiguous-grouping-separator' | 'leading-zero-digits' | 'precision-loss';
5
+ type CellTypeInferenceResult = {
6
+ readonly outcome: 'retyped';
7
+ readonly value: ContentCellValue;
8
+ readonly rule: CellTypeRule;
9
+ } | {
10
+ readonly outcome: 'declined';
11
+ readonly reason: CellTypeDeclineReason;
12
+ };
13
+ type CellTypeInference = {
14
+ readonly sheetIndex: number;
15
+ readonly row: number;
16
+ readonly column: number;
17
+ readonly displayText: string;
18
+ } & CellTypeInferenceResult;
19
+ type CellTypeInferenceSink = (inference: CellTypeInference) => void;
20
+ declare function inferCellValue(displayText: string): CellTypeInferenceResult | undefined;
21
+ //#endregion
22
+ export { CellTypeRule as a, CellTypeInferenceSink as i, CellTypeInference as n, inferCellValue as o, CellTypeInferenceResult as r, CellTypeDeclineReason as t };
@@ -1,43 +1,44 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_model_bytes = require("../model/bytes.cjs");
3
3
  const require_convert_convert = require("./convert.cjs");
4
+ const require_convert_from_pdf = require("./from-pdf.cjs");
4
5
  let zod = require("zod");
5
6
  //#region src/convert/codec.ts
6
7
  const docxPdfCodec = zod.z.codec(require_model_bytes.DocxBytesSchema, require_model_bytes.PdfBytesSchema, {
7
8
  decode: (docxBytes) => require_convert_convert.docxToPdf(docxBytes),
8
- encode: (pdfBytes) => require_convert_convert.pdfToDocx(pdfBytes)
9
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToDocx(pdfBytes)
9
10
  });
10
11
  const pptxPdfCodec = zod.z.codec(require_model_bytes.PptxBytesSchema, require_model_bytes.PdfBytesSchema, {
11
12
  decode: (pptxBytes) => require_convert_convert.pptxToPdf(pptxBytes),
12
- encode: (pdfBytes) => require_convert_convert.pdfToPptx(pdfBytes)
13
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToPptx(pdfBytes)
13
14
  });
14
15
  const odtPdfCodec = zod.z.codec(require_model_bytes.OdtBytesSchema, require_model_bytes.PdfBytesSchema, {
15
16
  decode: (odtBytes) => require_convert_convert.odtToPdf(odtBytes),
16
- encode: (pdfBytes) => require_convert_convert.pdfToOdt(pdfBytes)
17
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToOdt(pdfBytes)
17
18
  });
18
19
  const odpPdfCodec = zod.z.codec(require_model_bytes.OdpBytesSchema, require_model_bytes.PdfBytesSchema, {
19
20
  decode: (odpBytes) => require_convert_convert.odpToPdf(odpBytes),
20
- encode: (pdfBytes) => require_convert_convert.pdfToOdp(pdfBytes)
21
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToOdp(pdfBytes)
21
22
  });
22
23
  const odsPdfCodec = zod.z.codec(require_model_bytes.OdsBytesSchema, require_model_bytes.PdfBytesSchema, {
23
24
  decode: (odsBytes) => require_convert_convert.odsToPdf(odsBytes),
24
- encode: (pdfBytes) => require_convert_convert.pdfToOds(pdfBytes)
25
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToOds(pdfBytes)
25
26
  });
26
27
  const odgPdfCodec = zod.z.codec(require_model_bytes.OdgBytesSchema, require_model_bytes.PdfBytesSchema, {
27
28
  decode: (odgBytes) => require_convert_convert.odgToPdf(odgBytes),
28
- encode: (pdfBytes) => require_convert_convert.pdfToOdg(pdfBytes)
29
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToOdg(pdfBytes)
29
30
  });
30
31
  const xlsxPdfCodec = zod.z.codec(require_model_bytes.XlsxBytesSchema, require_model_bytes.PdfBytesSchema, {
31
32
  decode: (xlsxBytes) => require_convert_convert.xlsxToPdf(xlsxBytes),
32
- encode: (pdfBytes) => require_convert_convert.pdfToXlsx(pdfBytes)
33
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToXlsx(pdfBytes)
33
34
  });
34
35
  const markdownPdfCodec = zod.z.codec(require_model_bytes.MarkdownBytesSchema, require_model_bytes.PdfBytesSchema, {
35
36
  decode: (markdownBytes) => require_convert_convert.markdownToPdf(markdownBytes),
36
- encode: (pdfBytes) => require_convert_convert.pdfToMarkdown(pdfBytes)
37
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToMarkdown(pdfBytes)
37
38
  });
38
39
  const svgPdfCodec = zod.z.codec(require_model_bytes.SvgBytesSchema, require_model_bytes.PdfBytesSchema, {
39
40
  decode: (svgBytes) => require_convert_convert.svgToPdf(svgBytes),
40
- encode: (pdfBytes) => require_convert_convert.pdfToSvg(pdfBytes)
41
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToSvg(pdfBytes)
41
42
  });
42
43
  const odtDocxCodec = zod.z.codec(require_model_bytes.OdtBytesSchema, require_model_bytes.DocxBytesSchema, {
43
44
  decode: (odtBytes) => require_convert_convert.odtToDocx(odtBytes),
@@ -65,7 +66,7 @@ const xlsxMarkdownCodec = zod.z.codec(require_model_bytes.XlsxBytesSchema, requi
65
66
  });
66
67
  const csvPdfCodec = zod.z.codec(require_model_bytes.CsvBytesSchema, require_model_bytes.PdfBytesSchema, {
67
68
  decode: (csvBytes) => require_convert_convert.csvToPdf(csvBytes),
68
- encode: (pdfBytes) => require_convert_convert.pdfToCsv(pdfBytes)
69
+ encode: (pdfBytes) => require_convert_from_pdf.pdfToCsv(pdfBytes)
69
70
  });
70
71
  const odsCsvCodec = zod.z.codec(require_model_bytes.OdsBytesSchema, require_model_bytes.CsvBytesSchema, {
71
72
  decode: (odsBytes) => require_convert_convert.odsToCsv(odsBytes),
@@ -1,5 +1,6 @@
1
1
  import { CsvBytesSchema, DocxBytesSchema, MarkdownBytesSchema, OdgBytesSchema, OdpBytesSchema, OdsBytesSchema, OdtBytesSchema, PdfBytesSchema, PptxBytesSchema, SvgBytesSchema, XlsxBytesSchema } from "../model/bytes.js";
2
- import { csvToMarkdown, csvToOds, csvToPdf, csvToXlsx, docxToMarkdown, docxToOdt, docxToPdf, markdownToCsv, markdownToDocx, markdownToOdt, markdownToPdf, markdownToXlsx, odgToPdf, odgToSvg, odpToPdf, odpToPptx, odsToCsv, odsToPdf, odsToXlsx, odtToDocx, odtToMarkdown, odtToPdf, pdfToCsv, pdfToDocx, pdfToMarkdown, pdfToOdg, pdfToOdp, pdfToOds, pdfToOdt, pdfToPptx, pdfToSvg, pdfToXlsx, pptxToOdp, pptxToPdf, svgToOdg, svgToPdf, xlsxToCsv, xlsxToMarkdown, xlsxToOds, xlsxToPdf } from "./convert.js";
2
+ import { csvToMarkdown, csvToOds, csvToPdf, csvToXlsx, docxToMarkdown, docxToOdt, docxToPdf, markdownToCsv, markdownToDocx, markdownToOdt, markdownToPdf, markdownToXlsx, odgToPdf, odgToSvg, odpToPdf, odpToPptx, odsToCsv, odsToPdf, odsToXlsx, odtToDocx, odtToMarkdown, odtToPdf, pptxToOdp, pptxToPdf, svgToOdg, svgToPdf, xlsxToCsv, xlsxToMarkdown, xlsxToOds, xlsxToPdf } from "./convert.js";
3
+ import { pdfToCsv, pdfToDocx, pdfToMarkdown, pdfToOdg, pdfToOdp, pdfToOds, pdfToOdt, pdfToPptx, pdfToSvg, pdfToXlsx } from "./from-pdf.js";
3
4
  import { z } from "zod";
4
5
  //#region src/convert/codec.ts
5
6
  const docxPdfCodec = z.codec(DocxBytesSchema, PdfBytesSchema, {
@@ -0,0 +1,133 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_model_metadata = require("../model/metadata.cjs");
3
+ const require_fonts_registry = require("../fonts/registry.cjs");
4
+ const require_layout_engine = require("../layout/engine.cjs");
5
+ const require_layout_slides = require("../layout/slides.cjs");
6
+ const require_ports_abort = require("../ports/abort.cjs");
7
+ const require_layout_sheets = require("../layout/sheets.cjs");
8
+ const require_layout_drawing = require("../layout/drawing.cjs");
9
+ const require_convert_capability = require("./capability.cjs");
10
+ const require_convert_composition = require("./composition.cjs");
11
+ let document_schema_js = require("document-schema.js");
12
+ let pdf_codec = require("pdf-codec");
13
+ //#region src/convert/composition-to-pdf.ts
14
+ const mathMetricsAt = (sizePt) => (0, pdf_codec.loadMathFont)().metricsAt(sizePt);
15
+ const LAYOUT_ENGINES = {
16
+ wordprocessing: require_layout_engine.convertWordprocessingToLayout,
17
+ presentation: require_layout_slides.convertPresentationToLayout,
18
+ spreadsheet: require_layout_sheets.convertSpreadsheetToLayout,
19
+ drawing: require_layout_drawing.convertDrawingToLayout
20
+ };
21
+ function executeToPdf(format, bytes, options) {
22
+ if (!require_convert_composition.LAYOUT_CAPABLE.has(format)) throw new Error(`executeToPdf: '${format}' has no layout engine of its own`);
23
+ const node = require_convert_composition.FORMAT_NODES[format];
24
+ let content;
25
+ let fonts;
26
+ if (require_convert_composition.isTextFormatNode(node)) {
27
+ require_ports_abort.throwIfAborted(options?.signal);
28
+ const text = node.decode(bytes);
29
+ const read = node.read(text, options);
30
+ content = {
31
+ ...read,
32
+ metadata: require_model_metadata.resolveMetadataTimestamps(read.metadata, options?.clock)
33
+ };
34
+ fonts = (0, pdf_codec.createFontRegistry)({
35
+ fonts: options?.fonts,
36
+ onSubstitution: options?.onFontSubstitution
37
+ });
38
+ } else {
39
+ const pkg = node.decode(bytes);
40
+ const read = node.read(pkg, options);
41
+ content = {
42
+ ...read,
43
+ metadata: require_model_metadata.resolveMetadataTimestamps(read.metadata, options?.clock)
44
+ };
45
+ const fontSource = node.family === "odf" ? {
46
+ kind: "odf",
47
+ package: pkg
48
+ } : format === "pptx" ? {
49
+ kind: "pptx",
50
+ package: pkg
51
+ } : {
52
+ kind: "docx",
53
+ package: pkg
54
+ };
55
+ fonts = require_fonts_registry.createDocumentFontRegistry(fontSource, {
56
+ fonts: options?.fonts,
57
+ onFontSubstitution: options?.onFontSubstitution
58
+ });
59
+ }
60
+ const measurer = (0, pdf_codec.createFontMeasurer)(fonts);
61
+ let layout;
62
+ let pages;
63
+ let formulas;
64
+ switch (content.kind) {
65
+ case "wordprocessing": {
66
+ const result = LAYOUT_ENGINES.wordprocessing(content, {
67
+ measurer,
68
+ mathMetricsAt
69
+ });
70
+ layout = result.document;
71
+ pages = result.pages;
72
+ formulas = result.formulas;
73
+ break;
74
+ }
75
+ case "presentation": {
76
+ const result = LAYOUT_ENGINES.presentation(content, {
77
+ measurer,
78
+ mathMetricsAt
79
+ });
80
+ layout = result.document;
81
+ pages = result.pages;
82
+ formulas = result.formulas;
83
+ break;
84
+ }
85
+ case "spreadsheet": {
86
+ const result = LAYOUT_ENGINES.spreadsheet(content, {
87
+ measurer,
88
+ mathMetricsAt,
89
+ signal: options?.signal
90
+ });
91
+ layout = result.document;
92
+ pages = result.pages;
93
+ formulas = result.formulas;
94
+ break;
95
+ }
96
+ case "drawing": {
97
+ const result = LAYOUT_ENGINES.drawing(content, { measurer });
98
+ layout = result.document;
99
+ pages = result.pages;
100
+ break;
101
+ }
102
+ default: throw new Error(`executeToPdf: cannot lay out a '${content.kind}' document`);
103
+ }
104
+ if (formulas === void 0) {
105
+ const out = (0, pdf_codec.writePdf)(layout, {
106
+ signal: options?.signal,
107
+ onSubstitution: options?.onSubstitution,
108
+ fonts
109
+ });
110
+ options?.onDocument?.((0, document_schema_js.assemblePackage)(content, pages));
111
+ return out;
112
+ }
113
+ const out = (0, pdf_codec.writePdf)(layout, {
114
+ signal: options?.signal,
115
+ onSubstitution: options?.onSubstitution,
116
+ formulas,
117
+ fonts
118
+ });
119
+ options?.onDocument?.((0, document_schema_js.assemblePackage)(content, pages));
120
+ return out;
121
+ }
122
+ function convertDocument(source, target, bytes, options) {
123
+ const plan = require_convert_composition.resolveCompositionPlan(source, target);
124
+ if (plan === void 0) throw new require_convert_capability.UnsupportedConversionError(source, target);
125
+ return require_convert_composition.runCompositionPlan(plan, bytes, options, {
126
+ bridge: require_convert_composition.executeBridge,
127
+ fromPdf: require_convert_composition.executeFromPdf,
128
+ toPdf: executeToPdf
129
+ });
130
+ }
131
+ //#endregion
132
+ exports.convertDocument = convertDocument;
133
+ exports.executeToPdf = executeToPdf;
@@ -0,0 +1,7 @@
1
+ import { DocumentFormat } from "./port.cjs";
2
+ import { ContentFormat, UnifiedConversionOptions } from "./composition.cjs";
3
+ //#region src/convert/composition-to-pdf.d.ts
4
+ declare function executeToPdf(format: ContentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
5
+ declare function convertDocument(source: DocumentFormat, target: DocumentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
6
+ //#endregion
7
+ export { convertDocument, executeToPdf };
@@ -0,0 +1,7 @@
1
+ import { DocumentFormat } from "./port.js";
2
+ import { ContentFormat, UnifiedConversionOptions } from "./composition.js";
3
+ //#region src/convert/composition-to-pdf.d.ts
4
+ declare function executeToPdf(format: ContentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
5
+ declare function convertDocument(source: DocumentFormat, target: DocumentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
6
+ //#endregion
7
+ export { convertDocument, executeToPdf };
@@ -0,0 +1,131 @@
1
+ import { resolveMetadataTimestamps } from "../model/metadata.js";
2
+ import { createDocumentFontRegistry } from "../fonts/registry.js";
3
+ import { convertWordprocessingToLayout } from "../layout/engine.js";
4
+ import { convertPresentationToLayout } from "../layout/slides.js";
5
+ import { throwIfAborted } from "../ports/abort.js";
6
+ import { convertSpreadsheetToLayout } from "../layout/sheets.js";
7
+ import { convertDrawingToLayout } from "../layout/drawing.js";
8
+ import { UnsupportedConversionError } from "./capability.js";
9
+ import { FORMAT_NODES, LAYOUT_CAPABLE, executeBridge, executeFromPdf, isTextFormatNode, resolveCompositionPlan, runCompositionPlan } from "./composition.js";
10
+ import { assemblePackage } from "document-schema.js";
11
+ import { createFontMeasurer, createFontRegistry, loadMathFont, writePdf } from "pdf-codec";
12
+ //#region src/convert/composition-to-pdf.ts
13
+ const mathMetricsAt = (sizePt) => loadMathFont().metricsAt(sizePt);
14
+ const LAYOUT_ENGINES = {
15
+ wordprocessing: convertWordprocessingToLayout,
16
+ presentation: convertPresentationToLayout,
17
+ spreadsheet: convertSpreadsheetToLayout,
18
+ drawing: convertDrawingToLayout
19
+ };
20
+ function executeToPdf(format, bytes, options) {
21
+ if (!LAYOUT_CAPABLE.has(format)) throw new Error(`executeToPdf: '${format}' has no layout engine of its own`);
22
+ const node = FORMAT_NODES[format];
23
+ let content;
24
+ let fonts;
25
+ if (isTextFormatNode(node)) {
26
+ throwIfAborted(options?.signal);
27
+ const text = node.decode(bytes);
28
+ const read = node.read(text, options);
29
+ content = {
30
+ ...read,
31
+ metadata: resolveMetadataTimestamps(read.metadata, options?.clock)
32
+ };
33
+ fonts = createFontRegistry({
34
+ fonts: options?.fonts,
35
+ onSubstitution: options?.onFontSubstitution
36
+ });
37
+ } else {
38
+ const pkg = node.decode(bytes);
39
+ const read = node.read(pkg, options);
40
+ content = {
41
+ ...read,
42
+ metadata: resolveMetadataTimestamps(read.metadata, options?.clock)
43
+ };
44
+ const fontSource = node.family === "odf" ? {
45
+ kind: "odf",
46
+ package: pkg
47
+ } : format === "pptx" ? {
48
+ kind: "pptx",
49
+ package: pkg
50
+ } : {
51
+ kind: "docx",
52
+ package: pkg
53
+ };
54
+ fonts = createDocumentFontRegistry(fontSource, {
55
+ fonts: options?.fonts,
56
+ onFontSubstitution: options?.onFontSubstitution
57
+ });
58
+ }
59
+ const measurer = createFontMeasurer(fonts);
60
+ let layout;
61
+ let pages;
62
+ let formulas;
63
+ switch (content.kind) {
64
+ case "wordprocessing": {
65
+ const result = LAYOUT_ENGINES.wordprocessing(content, {
66
+ measurer,
67
+ mathMetricsAt
68
+ });
69
+ layout = result.document;
70
+ pages = result.pages;
71
+ formulas = result.formulas;
72
+ break;
73
+ }
74
+ case "presentation": {
75
+ const result = LAYOUT_ENGINES.presentation(content, {
76
+ measurer,
77
+ mathMetricsAt
78
+ });
79
+ layout = result.document;
80
+ pages = result.pages;
81
+ formulas = result.formulas;
82
+ break;
83
+ }
84
+ case "spreadsheet": {
85
+ const result = LAYOUT_ENGINES.spreadsheet(content, {
86
+ measurer,
87
+ mathMetricsAt,
88
+ signal: options?.signal
89
+ });
90
+ layout = result.document;
91
+ pages = result.pages;
92
+ formulas = result.formulas;
93
+ break;
94
+ }
95
+ case "drawing": {
96
+ const result = LAYOUT_ENGINES.drawing(content, { measurer });
97
+ layout = result.document;
98
+ pages = result.pages;
99
+ break;
100
+ }
101
+ default: throw new Error(`executeToPdf: cannot lay out a '${content.kind}' document`);
102
+ }
103
+ if (formulas === void 0) {
104
+ const out = writePdf(layout, {
105
+ signal: options?.signal,
106
+ onSubstitution: options?.onSubstitution,
107
+ fonts
108
+ });
109
+ options?.onDocument?.(assemblePackage(content, pages));
110
+ return out;
111
+ }
112
+ const out = writePdf(layout, {
113
+ signal: options?.signal,
114
+ onSubstitution: options?.onSubstitution,
115
+ formulas,
116
+ fonts
117
+ });
118
+ options?.onDocument?.(assemblePackage(content, pages));
119
+ return out;
120
+ }
121
+ function convertDocument(source, target, bytes, options) {
122
+ const plan = resolveCompositionPlan(source, target);
123
+ if (plan === void 0) throw new UnsupportedConversionError(source, target);
124
+ return runCompositionPlan(plan, bytes, options, {
125
+ bridge: executeBridge,
126
+ fromPdf: executeFromPdf,
127
+ toPdf: executeToPdf
128
+ });
129
+ }
130
+ //#endregion
131
+ export { convertDocument, executeToPdf };
@@ -1,5 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_model_metadata = require("../model/metadata.cjs");
3
2
  const require_edit_docx_content = require("../edit/docx/content.cjs");
4
3
  const require_edit_pptx_content = require("../edit/pptx/content.cjs");
5
4
  const require_edit_odt_content = require("../edit/odt/content.cjs");
@@ -8,7 +7,6 @@ const require_edit_ods_content = require("../edit/ods/content.cjs");
8
7
  const require_edit_odg_content = require("../edit/odg/content.cjs");
9
8
  const require_markdown_read = require("../markdown/read.cjs");
10
9
  const require_markdown_write = require("../markdown/write.cjs");
11
- const require_fonts_registry = require("../fonts/registry.cjs");
12
10
  const require_ooxml_docx_read = require("../ooxml/docx/read.cjs");
13
11
  const require_ooxml_pptx_read = require("../ooxml/pptx/read.cjs");
14
12
  const require_odf_odt_read = require("../odf/odt/read.cjs");
@@ -22,21 +20,16 @@ const require_csv_write = require("../csv/write.cjs");
22
20
  const require_svg_text = require("../svg/text.cjs");
23
21
  const require_svg_read = require("../svg/read.cjs");
24
22
  const require_svg_write = require("../svg/write.cjs");
25
- const require_layout_engine = require("../layout/engine.cjs");
26
- const require_layout_slides = require("../layout/slides.cjs");
27
23
  const require_ports_abort = require("../ports/abort.cjs");
28
- const require_layout_sheets = require("../layout/sheets.cjs");
29
- const require_layout_drawing = require("../layout/drawing.cjs");
30
24
  const require_layout_reconstruct = require("../layout/reconstruct.cjs");
31
25
  const require_convert_variant_bridges = require("./variant-bridges.cjs");
32
26
  const require_convert_capability = require("./capability.cjs");
33
27
  let ooxml_js = require("ooxml.js");
34
28
  let document_schema_js = require("document-schema.js");
35
- let pdf_codec = require("pdf-codec");
36
29
  let odf_js = require("odf.js");
37
30
  require("markdown-codec");
31
+ let pdf_codec_read = require("pdf-codec/read");
38
32
  //#region src/convert/composition.ts
39
- const mathMetricsAt = (sizePt) => (0, pdf_codec.loadMathFont)().metricsAt(sizePt);
40
33
  const CONTENT_FORMATS = [
41
34
  "docx",
42
35
  "pptx",
@@ -184,12 +177,6 @@ const TRANSFORMS = {
184
177
  return require_convert_variant_bridges.presentationToDrawing(doc);
185
178
  }
186
179
  };
187
- const LAYOUT_ENGINES = {
188
- wordprocessing: require_layout_engine.convertWordprocessingToLayout,
189
- presentation: require_layout_slides.convertPresentationToLayout,
190
- spreadsheet: require_layout_sheets.convertSpreadsheetToLayout,
191
- drawing: require_layout_drawing.convertDrawingToLayout
192
- };
193
180
  const RECONSTRUCTORS = {
194
181
  wordprocessing: require_layout_reconstruct.reconstructWordprocessing,
195
182
  presentation: require_layout_reconstruct.reconstructPresentation,
@@ -228,110 +215,9 @@ function executeBridge(source, target, bytes, options) {
228
215
  options?.onDocument?.((0, document_schema_js.assemblePackage)(buildContent));
229
216
  return out;
230
217
  }
231
- function executeToPdf(format, bytes, options) {
232
- if (!LAYOUT_CAPABLE.has(format)) throw new Error(`executeToPdf: '${format}' has no layout engine of its own`);
233
- const node = FORMAT_NODES[format];
234
- let content;
235
- let fonts;
236
- if (isTextFormatNode(node)) {
237
- require_ports_abort.throwIfAborted(options?.signal);
238
- const text = node.decode(bytes);
239
- const read = node.read(text, options);
240
- content = {
241
- ...read,
242
- metadata: require_model_metadata.resolveMetadataTimestamps(read.metadata, options?.clock)
243
- };
244
- fonts = (0, pdf_codec.createFontRegistry)({
245
- fonts: options?.fonts,
246
- onSubstitution: options?.onFontSubstitution
247
- });
248
- } else {
249
- const pkg = node.decode(bytes);
250
- const read = node.read(pkg, options);
251
- content = {
252
- ...read,
253
- metadata: require_model_metadata.resolveMetadataTimestamps(read.metadata, options?.clock)
254
- };
255
- const fontSource = node.family === "odf" ? {
256
- kind: "odf",
257
- package: pkg
258
- } : format === "pptx" ? {
259
- kind: "pptx",
260
- package: pkg
261
- } : {
262
- kind: "docx",
263
- package: pkg
264
- };
265
- fonts = require_fonts_registry.createDocumentFontRegistry(fontSource, {
266
- fonts: options?.fonts,
267
- onFontSubstitution: options?.onFontSubstitution
268
- });
269
- }
270
- const measurer = (0, pdf_codec.createFontMeasurer)(fonts);
271
- let layout;
272
- let pages;
273
- let formulas;
274
- switch (content.kind) {
275
- case "wordprocessing": {
276
- const result = LAYOUT_ENGINES.wordprocessing(content, {
277
- measurer,
278
- mathMetricsAt
279
- });
280
- layout = result.document;
281
- pages = result.pages;
282
- formulas = result.formulas;
283
- break;
284
- }
285
- case "presentation": {
286
- const result = LAYOUT_ENGINES.presentation(content, {
287
- measurer,
288
- mathMetricsAt
289
- });
290
- layout = result.document;
291
- pages = result.pages;
292
- formulas = result.formulas;
293
- break;
294
- }
295
- case "spreadsheet": {
296
- const result = LAYOUT_ENGINES.spreadsheet(content, {
297
- measurer,
298
- mathMetricsAt,
299
- signal: options?.signal
300
- });
301
- layout = result.document;
302
- pages = result.pages;
303
- formulas = result.formulas;
304
- break;
305
- }
306
- case "drawing": {
307
- const result = LAYOUT_ENGINES.drawing(content, { measurer });
308
- layout = result.document;
309
- pages = result.pages;
310
- break;
311
- }
312
- default: throw new Error(`executeToPdf: cannot lay out a '${content.kind}' document`);
313
- }
314
- if (formulas === void 0) {
315
- const out = (0, pdf_codec.writePdf)(layout, {
316
- signal: options?.signal,
317
- onSubstitution: options?.onSubstitution,
318
- fonts
319
- });
320
- options?.onDocument?.((0, document_schema_js.assemblePackage)(content, pages));
321
- return out;
322
- }
323
- const out = (0, pdf_codec.writePdf)(layout, {
324
- signal: options?.signal,
325
- onSubstitution: options?.onSubstitution,
326
- formulas,
327
- fonts
328
- });
329
- options?.onDocument?.((0, document_schema_js.assemblePackage)(content, pages));
330
- return out;
331
- }
332
218
  function executeFromPdf(target, bytes, options) {
333
219
  const node = FORMAT_NODES[target];
334
- const layout = (0, pdf_codec.readPdf)(bytes, {
220
+ const layout = (0, pdf_codec_read.readPdf)(bytes, {
335
221
  signal: options?.signal,
336
222
  sink: options?.sink
337
223
  });
@@ -446,31 +332,44 @@ function resolveCompositionPlan(source, target) {
446
332
  function isContentFormat(format) {
447
333
  return format !== "pdf" && format !== "odf";
448
334
  }
449
- function convertDocument(source, target, bytes, options) {
450
- const plan = resolveCompositionPlan(source, target);
451
- if (plan === void 0) throw new require_convert_capability.UnsupportedConversionError(source, target);
335
+ function runCompositionPlan(plan, bytes, options, executors) {
452
336
  let current = bytes;
453
337
  for (let i = 0; i < plan.hops.length; i++) {
454
338
  const hop = plan.hops[i];
455
- if (hop === void 0) throw new Error("convertDocument: resolveCompositionPlan returned a malformed hop");
339
+ if (hop === void 0) throw new Error("runCompositionPlan: resolveCompositionPlan returned a malformed hop");
456
340
  const hopOptions = i === plan.hops.length - 1 ? options : options === void 0 ? void 0 : {
457
341
  ...options,
458
342
  onDocument: void 0
459
343
  };
460
344
  if (hop.executor === "toPdf") {
461
- if (!isContentFormat(hop.from)) throw new Error(`convertDocument: toPdf source '${hop.from}' is not a content format`);
462
- current = executeToPdf(hop.from, current, hopOptions);
345
+ if (!isContentFormat(hop.from)) throw new Error(`runCompositionPlan: toPdf source '${hop.from}' is not a content format`);
346
+ const toPdf = executors.toPdf;
347
+ if (toPdf === void 0) throw new Error(`runCompositionPlan: the plan's ${hop.from} -> ${hop.to} hop needs a toPdf executor, but this binding carries none (the read-only entry cannot render PDFs)`);
348
+ current = toPdf(hop.from, current, hopOptions);
463
349
  } else if (hop.executor === "fromPdf") {
464
- if (!isContentFormat(hop.to)) throw new Error(`convertDocument: fromPdf target '${hop.to}' is not a content format`);
465
- current = executeFromPdf(hop.to, current, hopOptions);
350
+ if (!isContentFormat(hop.to)) throw new Error(`runCompositionPlan: fromPdf target '${hop.to}' is not a content format`);
351
+ current = executors.fromPdf(hop.to, current, hopOptions);
466
352
  } else {
467
- if (!isContentFormat(hop.from) || !isContentFormat(hop.to)) throw new Error(`convertDocument: bridge endpoints '${hop.from}' -> '${hop.to}' are not both content formats`);
468
- current = executeBridge(hop.from, hop.to, current, hopOptions);
353
+ if (!isContentFormat(hop.from) || !isContentFormat(hop.to)) throw new Error(`runCompositionPlan: bridge endpoints '${hop.from}' -> '${hop.to}' are not both content formats`);
354
+ current = executors.bridge(hop.from, hop.to, current, hopOptions);
469
355
  }
470
356
  }
471
357
  return current;
472
358
  }
359
+ function convertDocumentFromPdf(target, bytes, options) {
360
+ const plan = resolveCompositionPlan("pdf", target);
361
+ if (plan === void 0) throw new require_convert_capability.UnsupportedConversionError("pdf", target);
362
+ return runCompositionPlan(plan, bytes, options, {
363
+ bridge: executeBridge,
364
+ fromPdf: executeFromPdf
365
+ });
366
+ }
473
367
  //#endregion
474
368
  exports.FORMAT_NODES = FORMAT_NODES;
475
- exports.convertDocument = convertDocument;
369
+ exports.LAYOUT_CAPABLE = LAYOUT_CAPABLE;
370
+ exports.convertDocumentFromPdf = convertDocumentFromPdf;
371
+ exports.executeBridge = executeBridge;
372
+ exports.executeFromPdf = executeFromPdf;
373
+ exports.isTextFormatNode = isTextFormatNode;
476
374
  exports.resolveCompositionPlan = resolveCompositionPlan;
375
+ exports.runCompositionPlan = runCompositionPlan;