js.documents 6.3.5 → 6.4.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 +31 -24
- package/dist/{capability-D-a4okp0.d.ts → capability-BmRwrPL9.d.ts} +3 -1
- package/dist/{capability-BZ3iNsWh.d.cts → capability-WJWAE-5Z.d.cts} +3 -1
- package/dist/codecs/read.cjs +5 -0
- package/dist/codecs/read.js +5 -0
- package/dist/codecs/registry.cjs +2 -1
- package/dist/codecs/registry.js +2 -1
- package/dist/convert/capability.cjs +34 -13
- package/dist/convert/capability.d.cts +2 -2
- package/dist/convert/capability.d.ts +2 -2
- package/dist/convert/capability.js +34 -14
- package/dist/convert/composition-to-pdf.cjs +17 -1
- package/dist/convert/composition-to-pdf.d.cts +2 -2
- package/dist/convert/composition-to-pdf.d.ts +2 -2
- package/dist/convert/composition-to-pdf.js +18 -2
- package/dist/convert/composition.cjs +54 -16
- package/dist/convert/composition.d.cts +14 -6
- package/dist/convert/composition.d.ts +14 -6
- package/dist/convert/composition.js +53 -17
- package/dist/convert/from-package.cjs +3 -2
- package/dist/convert/from-package.js +3 -2
- package/dist/convert/port.cjs +1 -0
- package/dist/convert/port.d.cts +1 -0
- package/dist/convert/port.d.ts +1 -0
- package/dist/convert/port.js +1 -0
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/layout/reconstruct.cjs +5 -2
- package/dist/layout/reconstruct.js +5 -2
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/ExaDev/documents.js/tree/main/packages/documents.js) [](https://www.npmjs.com/package/documents.js) [](https://www.npmjs.com/package/documents.js) [](https://github.com/ExaDev/documents.js/actions)
|
|
4
4
|
|
|
5
|
-
> Converts between any two compatible document formats through a shared content/layout pivot. docx, pptx, odt, odp, ods, odg, xlsx, csv (TSV is the same format with a tab delimiter), svg, markdown, and rtf all read into and build from the same shared `ContentDocument` model (reported to callers as the tree-form `DocumentTree`), with PDF — reached through pdf-codec's own `LayoutDocument` view — as the one format every variant can reach. A composition engine (`convertDocument`) routes
|
|
5
|
+
> Converts between any two compatible document formats through a shared content/layout pivot. docx, pptx, odt, odp, ods, odg, xlsx, csv (TSV is the same format with a tab delimiter), svg, markdown, and rtf all read into and build from the same shared `ContentDocument` model (reported to callers as the tree-form `DocumentTree`), with PDF — reached through pdf-codec's own `LayoutDocument` view — as the one format every variant can reach; wpd (WordPerfect 6.x-X6) reads into the same wordprocessing variant as a read-only source, routable everywhere the others are but never buildable as a target, since wpd-codec ships no writer. A composition engine (`convertDocument`) routes 141 (source, target) pairs across the twelve content formats and PDF, including twenty-two PDF-pivot round trips (the eight layout-engine formats, plus xlsx and csv composing through ods, and rtf composing through docx/odt/markdown), twenty-four cross-format bridge functions (same-variant direct copies, cross-variant semantic transforms, and PDF-composed), twelve one-way wpd-sourced routes, plus special-case conversions for `.odm` master documents, `.odb` database front-ends (HSQLDB and Firebird, four storage tiers), standalone `.odf` formula documents, and a bounded SQL/rpt-formula engine for `.odb` reports. Also includes: read-and-write live-view editors for all six editable formats, docx comment/footnote/header-footer exposure via `readDocxExtras`, real font resolution (source-embedded faces ahead of caller-supplied, vendored substitutes, and the standard 14), a hand-written MathML typesetting engine with embedded-font PDF rendering and a matching MathML ⇄ OMML translator, LaTeX lowering into the schema's two-layer semantic math core (pinned temml parser, symbol tables from prose, a coherence lint), and a fully hand-written PDF codec. Built on [ooxml.js](../ooxml.js/README.md), [odf.js](../odf.js/README.md), [pdf-codec](../pdf-codec/README.md), [markdown-codec](../markdown-codec/README.md), [rtf-codec](../rtf-codec/README.md), [wpd-codec](../wpd-codec/README.md), and [document-schema.js](../document-schema.js/README.md).
|
|
6
6
|
|
|
7
7
|
`documents.js` extends `ooxml.js` in two directions `ooxml.js` deliberately does not cover: full PDF support (parsing and generating, via `pdf-codec`), and a read-**and-write** manipulation API for docx/pptx content — `ooxml.js`'s own typed readers are one-way. The PDF codec is hand-written against ISO 32000-1, with no external PDF library as a dependency — see [Fidelity](#fidelity) and pdf-codec's own README for the honest trade-off (not as robust against adversarial PDFs as a 15+-year-hardened library; fully auditable and dependency-free instead). `src/mathml/` (the MathML typesetting engine) stays in this package and is hand-written too, for the same supply-chain reason. The one deliberate exception on the math side is the LaTeX parser: `src/latex/` lowers LaTeX into the schema's semantic core over a pinned exact-version [temml](https://temml.org) dependency — see [LaTeX lowering into the semantic core](#latex-lowering-into-the-semantic-core) for why a LaTeX grammar is the one component not worth hand-writing and what the pin guarantees.
|
|
8
8
|
|
|
@@ -14,6 +14,7 @@ graph TD
|
|
|
14
14
|
pdfcodec("pdf-codec")
|
|
15
15
|
mdcodec("markdown-codec")
|
|
16
16
|
rtfcodec("rtf-codec")
|
|
17
|
+
wpdcodec("wpd-codec")
|
|
17
18
|
bytecodec("byte-codec")
|
|
18
19
|
documents("documents.js")
|
|
19
20
|
mcp("document-mcp")
|
|
@@ -24,12 +25,14 @@ graph TD
|
|
|
24
25
|
schema --> pdfcodec
|
|
25
26
|
schema --> mdcodec
|
|
26
27
|
schema --> rtfcodec
|
|
28
|
+
schema --> wpdcodec
|
|
27
29
|
schema --> documents
|
|
28
30
|
ooxml --> documents
|
|
29
31
|
odf --> documents
|
|
30
32
|
pdfcodec --> documents
|
|
31
33
|
mdcodec --> documents
|
|
32
34
|
rtfcodec --> documents
|
|
35
|
+
wpdcodec --> documents
|
|
33
36
|
bytecodec --> pdfcodec
|
|
34
37
|
bytecodec --> documents
|
|
35
38
|
documents --> mcp
|
|
@@ -44,6 +47,7 @@ graph TD
|
|
|
44
47
|
click pdfcodec "https://github.com/ExaDev/documents.js/tree/main/packages/pdf-codec" "pdf-codec"
|
|
45
48
|
click mdcodec "https://github.com/ExaDev/documents.js/tree/main/packages/markdown-codec" "markdown-codec"
|
|
46
49
|
click rtfcodec "https://github.com/ExaDev/documents.js/tree/main/packages/rtf-codec" "rtf-codec"
|
|
50
|
+
click wpdcodec "https://github.com/ExaDev/documents.js/tree/main/packages/wpd-codec" "wpd-codec"
|
|
47
51
|
click bytecodec "https://github.com/ExaDev/documents.js/tree/main/packages/byte-codec" "byte-codec"
|
|
48
52
|
click documents "https://github.com/ExaDev/documents.js" "documents.js"
|
|
49
53
|
click mcp "https://github.com/ExaDev/documents.js/tree/main/packages/document-mcp" "document-mcp"
|
|
@@ -76,7 +80,7 @@ npm install documents.js document-schema.js
|
|
|
76
80
|
|
|
77
81
|
### The generic entry point: `convertDocument`
|
|
78
82
|
|
|
79
|
-
A single function, `convertDocument`, sits behind every named conversion and reaches every pair the composition engine can route — all
|
|
83
|
+
A single function, `convertDocument`, sits behind every named conversion and reaches every pair the composition engine can route — all 141 supported (source, target) combinations. The named functions below are thin one-line forwarders to it; they remain the ergonomic layer for a caller who wants a fixed pair and autocomplete discovery, while `convertDocument` is the first-class entry point for a caller working from a runtime format pair (CLI, MCP tool, matrix enumeration).
|
|
80
84
|
|
|
81
85
|
```ts
|
|
82
86
|
import { convertDocument } from "documents.js";
|
|
@@ -196,14 +200,14 @@ const { document, diagnostics } = await converter.convert(
|
|
|
196
200
|
);
|
|
197
201
|
```
|
|
198
202
|
|
|
199
|
-
`DocumentFormat` includes `docx`/`pptx`/`xlsx`/`odt`/`odp`/`ods`/`odg`/`svg`/`odf`/`csv`/`markdown`/`rtf`/`pdf` —
|
|
203
|
+
`DocumentFormat` includes `docx`/`pptx`/`xlsx`/`odt`/`odp`/`ods`/`odg`/`svg`/`odf`/`csv`/`markdown`/`rtf`/`wpd`/`pdf` — fourteen members, `wpd` the one read-only member: it appears as a source in `conversions` but never as a target, since wpd-codec ships no writer. The port's `conversions` list is derived from `resolveCompositionPlan` plus the `odf`→`pdf` special case — 141 pairs total. `DocumentFormat` is inferred from `DocumentFormatSchema` (a real Zod schema); `DOCUMENT_FORMATS` is exported as a plain array derived from the same schema:
|
|
200
204
|
|
|
201
205
|
The port also exposes `contractVersion: number`, bumped only when `DocumentConverter`'s own contract shape changes — a new field on `ConversionResult` a caller might need to branch on, or a new `ConversionOptions` field an implementation is now expected to honour — never when the `conversions` table simply grows with more supported source/target pairs (that's discoverable at runtime via `conversions` itself). It is currently `7`: the bump from `6` reflects `ConversionResult.package` changing type to the tree-form `DocumentTree` described below, which a caller reading that field must now flatten rather than read directly.
|
|
202
206
|
|
|
203
207
|
```ts
|
|
204
208
|
import { DOCUMENT_FORMATS, DocumentFormatSchema } from "documents.js";
|
|
205
209
|
|
|
206
|
-
console.log(DOCUMENT_FORMATS); // ['docx', 'pptx', 'xlsx', 'odt', 'odp', 'ods', 'odg', 'svg', 'odf', 'csv', 'markdown', 'rtf', 'pdf']
|
|
210
|
+
console.log(DOCUMENT_FORMATS); // ['docx', 'pptx', 'xlsx', 'odt', 'odp', 'ods', 'odg', 'svg', 'odf', 'csv', 'markdown', 'rtf', 'wpd', 'pdf']
|
|
207
211
|
DocumentFormatSchema.parse(userSuppliedFormat); // throws a ZodError for anything outside that list
|
|
208
212
|
```
|
|
209
213
|
|
|
@@ -770,7 +774,7 @@ The package is layered from generic primitives outward to the two conversion dir
|
|
|
770
774
|
- **`src/metadata/`** — cross-format metadata read/write via `DOCUMENT_FORMAT_CODECS`.
|
|
771
775
|
- **`src/package-codec.ts`** — `decodeDocumentPackage`/`encodeDocumentPackage`/`decodeOdbPackage`.
|
|
772
776
|
|
|
773
|
-
Dependency direction is downward and checkable.
|
|
777
|
+
Dependency direction is downward and checkable. Eight external dependencies each own a distinct concern: `ooxml.js` (docx/pptx/xlsx), `odf.js` (odt/ods/odp/odg), `document-schema.js` (shared schemas + port contracts), `pdf-codec` (PDF codec + text-layout/font primitives), `byte-codec` (byte/image utilities), `markdown-codec` (markdown), `rtf-codec` (rtf), `wpd-codec` (wpd, read-only). No `PdfObject`/`PdfDict`/`PdfStream` type appears anywhere in this package.
|
|
774
778
|
|
|
775
779
|
## Build, test, and lint
|
|
776
780
|
|
|
@@ -883,25 +887,26 @@ To run a single test file: `pnpm vitest run src/path/to/file.test.ts`.
|
|
|
883
887
|
|
|
884
888
|
## Fidelity
|
|
885
889
|
|
|
886
|
-
Read as **row → column**. `✓` lossless, `~` bounded, `✗` lossy, `✗✗` severe, `→` one-way, `–` no conversion. `.odm`/`.odb` sit outside this table. `rtf` is wired into the composition engine and bidirectionally routable to every other format here except `csv`/`xlsx` (one hop past the pathfinder's own 3-hop cap) and `odf` (excluded from routing entirely — see below). Every cell below is derived from `resolveCompositionPlan`'s actual resolved route for that pair (hop count and hop kind — same-variant bridge, cross-variant transform, or PDF pivot), not hand-reasoned: the pathfinder generates the full cross-product of same-variant and cross-variant-transform edges, so a pair can be routable even with no named convenience function for it (e.g. `odp → docx`, `odt → pptx`).
|
|
887
|
-
|
|
888
|
-
| ↓ from \ to → | docx | pptx | xlsx | odt | odp | ods | odg | svg | odf | markdown | csv | rtf | pdf |
|
|
889
|
-
| ------------- | ---- | ---- | ---- | --- | --- | --- | --- | --- | --- | -------- | --- | --- | --- |
|
|
890
|
-
| **docx** | — | ~ | ✗ | ✓ | ~ | ✗ | ✗ | ✗ | – | ✗ | ✗ | ✗ | ~ |
|
|
891
|
-
| **pptx** | ~ | — | ✗ | ~ | ✓ | ✗ | ~ | ~ | – | ~ | ✗ | ~ | ~ |
|
|
892
|
-
| **xlsx** | ✗ | ✗ | — | ✗ | ✗ | ~ | ✗ | ✗ | – | ✗✗ | ~ | – | ~ |
|
|
893
|
-
| **odt** | ✓ | ~ | ✗ | — | ~ | ✗ | ✗ | ✗ | – | ✗ | ✗ | ✗ | ~ |
|
|
894
|
-
| **odp** | ~ | ✓ | ✗ | ~ | — | ✗ | ~ | ~ | – | ~ | ✗ | ~ | ~ |
|
|
895
|
-
| **ods** | ✗ | ✗ | ~ | ✗ | ✗ | — | ✗ | ✗ | – | ✗✗ | ~ | ✗ | ~ |
|
|
896
|
-
| **odg** | ✗ | ~ | ✗ | ✗ | ~ | ✗ | — | ✓ | – | ✗ | ✗ | ✗ | ~ |
|
|
897
|
-
| **svg** | ✗ | ~ | ✗ | ✗ | ~ | ✗ | ✓ | — | – | ✗✗ | ✗✗ | ✗ | ~ |
|
|
898
|
-
| **odf** | – | – | – | – | – | – | – | – | — | – | – | – | → |
|
|
899
|
-
| **markdown** | ~ | ~ | ✗✗ | ~ | ~ | ✗ | ✗ | ✗✗ | – | — | ✗✗ | ~ | ~ |
|
|
900
|
-
| **csv** | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | – | ✗✗ | — | – | ~ |
|
|
901
|
-
| **rtf** | ~ | ~ | – | ~ | ~ | ✗ | ✗ | ✗ | – | ✗ | – | — | ~ |
|
|
902
|
-
| **
|
|
903
|
-
|
|
904
|
-
|
|
890
|
+
Read as **row → column**. `✓` lossless, `~` bounded, `✗` lossy, `✗✗` severe, `→` one-way, `–` no conversion. `.odm`/`.odb` sit outside this table. `rtf` is wired into the composition engine and bidirectionally routable to every other format here except `csv`/`xlsx` (one hop past the pathfinder's own 3-hop cap) and `odf` (excluded from routing entirely — see below). `wpd` is wired in as a read-only source (see composition.ts's own `ReadOnlyContentFormat`): routable to every other format here except `odf`, exactly like `rtf`'s reach, but every one of its cells is `→` rather than a fidelity grade, since a read-only format has no reverse direction to compare against and no column of its own — nothing ever routes to `wpd`, wpd-codec having no writer at all. Every cell below is derived from `resolveCompositionPlan`'s actual resolved route for that pair (hop count and hop kind — same-variant bridge, cross-variant transform, or PDF pivot), not hand-reasoned: the pathfinder generates the full cross-product of same-variant and cross-variant-transform edges, so a pair can be routable even with no named convenience function for it (e.g. `odp → docx`, `odt → pptx`).
|
|
891
|
+
|
|
892
|
+
| ↓ from \ to → | docx | pptx | xlsx | odt | odp | ods | odg | svg | odf | markdown | csv | rtf | wpd | pdf |
|
|
893
|
+
| ------------- | ---- | ---- | ---- | --- | --- | --- | --- | --- | --- | -------- | --- | --- | --- | --- |
|
|
894
|
+
| **docx** | — | ~ | ✗ | ✓ | ~ | ✗ | ✗ | ✗ | – | ✗ | ✗ | ✗ | – | ~ |
|
|
895
|
+
| **pptx** | ~ | — | ✗ | ~ | ✓ | ✗ | ~ | ~ | – | ~ | ✗ | ~ | – | ~ |
|
|
896
|
+
| **xlsx** | ✗ | ✗ | — | ✗ | ✗ | ~ | ✗ | ✗ | – | ✗✗ | ~ | – | – | ~ |
|
|
897
|
+
| **odt** | ✓ | ~ | ✗ | — | ~ | ✗ | ✗ | ✗ | – | ✗ | ✗ | ✗ | – | ~ |
|
|
898
|
+
| **odp** | ~ | ✓ | ✗ | ~ | — | ✗ | ~ | ~ | – | ~ | ✗ | ~ | – | ~ |
|
|
899
|
+
| **ods** | ✗ | ✗ | ~ | ✗ | ✗ | — | ✗ | ✗ | – | ✗✗ | ~ | ✗ | – | ~ |
|
|
900
|
+
| **odg** | ✗ | ~ | ✗ | ✗ | ~ | ✗ | — | ✓ | – | ✗ | ✗ | ✗ | – | ~ |
|
|
901
|
+
| **svg** | ✗ | ~ | ✗ | ✗ | ~ | ✗ | ✓ | — | – | ✗✗ | ✗✗ | ✗ | – | ~ |
|
|
902
|
+
| **odf** | – | – | – | – | – | – | – | – | — | – | – | – | – | → |
|
|
903
|
+
| **markdown** | ~ | ~ | ✗✗ | ~ | ~ | ✗ | ✗ | ✗✗ | – | — | ✗✗ | ~ | – | ~ |
|
|
904
|
+
| **csv** | ✗ | ✗ | ✓ | ✗ | ✗ | ✓ | ✗ | ✗ | – | ✗✗ | — | – | – | ~ |
|
|
905
|
+
| **rtf** | ~ | ~ | – | ~ | ~ | ✗ | ✗ | ✗ | – | ✗ | – | — | – | ~ |
|
|
906
|
+
| **wpd** | → | → | → | → | → | → | → | → | – | → | → | → | — | → |
|
|
907
|
+
| **pdf** | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | – | ✗✗ | ✗ | ✗ | – | — |
|
|
908
|
+
|
|
909
|
+
141 of 182 directional pairs are routable. The shared `ContentDocument` model is the hub, not PDF — twenty bridges bypass PDF entirely.
|
|
905
910
|
|
|
906
911
|
**X → PDF** is a genuine layout render: positioned text, images, tables, lists, vector primitives, styled through the full cascade. It is a faithful visual approximation, not pixel-identical — closeness depends on font availability.
|
|
907
912
|
|
|
@@ -923,6 +928,8 @@ Read as **row → column**. `✓` lossless, `~` bounded, `✗` lossy, `✗✗` s
|
|
|
923
928
|
|
|
924
929
|
**Every wordprocessing-family format (docx/odt/markdown/rtf) bridges to every presentation-family format (pptx/odp), and every drawing-family format (odg/svg) bridges to every presentation-family format too, through a semantic transform** — not just the two hand-written convenience pairs (docx⇄pptx, odt⇄odp): the pathfinder generates the full cross-product from the same two transform functions (`wordprocessingToPresentation`/`presentationToWordprocessing`, `drawingToPresentation`/`presentationToDrawing`), so e.g. `odp → docx` and `odt → pptx` are real routable pairs with no named function of their own. Slide boundaries are heuristic, but blocks survive intact. A wordprocessing format reaching a drawing format (or vice versa) chains two such transforms through presentation as a hub (e.g. `docx → pptx → odg`) with no PDF pivot at all — cheaper than a PDF round trip, but compounding two structural transforms is more lossy than one, hence those cells' `✗` rather than `~`.
|
|
925
930
|
|
|
931
|
+
**`wpd`'s whole row is `→`, never a fidelity grade, because it is read-only.** wpd-codec has a real reader and no writer at all (a deliberate scope decision, not an omission — see that package's own Scope), so there is no reverse conversion to measure loss against the way every other pair in this table can be. `wpd → docx`/`wpd → odt`/`wpd → markdown`/`wpd → rtf` are same-variant bridges at cost 1; `wpd → pptx`/`wpd → odp` are cross-variant transforms at cost 2; `wpd → pdf` is a direct layout-engine pass, the same edge markdown's own `hasLayoutPath` justifies; everything else composes through one of those. `wpd → odf` is the one cell excluded, matching every other row: nothing routes to `odf`.
|
|
932
|
+
|
|
926
933
|
**`.odb` extraction** is genuine verified data extraction across all four tiers, differing by what each storage shape carries. BLOB content recovers byte-for-byte. No reverse direction.
|
|
927
934
|
|
|
928
935
|
**SQL/rpt engines** are exact within their closed grammars, hard failures outside — never approximations.
|
|
@@ -5,12 +5,14 @@ interface FormatCapability {
|
|
|
5
5
|
readonly format: DocumentFormat;
|
|
6
6
|
readonly variant?: ContentVariant;
|
|
7
7
|
readonly hasLayoutPath: boolean;
|
|
8
|
+
readonly readOnly: boolean;
|
|
8
9
|
}
|
|
9
10
|
declare const FORMAT_CAPABILITIES: Readonly<Record<DocumentFormat, FormatCapability>>;
|
|
11
|
+
declare const READ_ONLY_FORMATS: ReadonlySet<DocumentFormat>;
|
|
10
12
|
declare class UnsupportedConversionError extends Error {
|
|
11
13
|
readonly source: DocumentFormat;
|
|
12
14
|
readonly target: DocumentFormat;
|
|
13
15
|
constructor(source: DocumentFormat, target: DocumentFormat);
|
|
14
16
|
}
|
|
15
17
|
//#endregion
|
|
16
|
-
export { UnsupportedConversionError as i, FORMAT_CAPABILITIES as n, FormatCapability as r, ContentVariant as t };
|
|
18
|
+
export { UnsupportedConversionError as a, READ_ONLY_FORMATS as i, FORMAT_CAPABILITIES as n, FormatCapability as r, ContentVariant as t };
|
|
@@ -5,12 +5,14 @@ interface FormatCapability {
|
|
|
5
5
|
readonly format: DocumentFormat;
|
|
6
6
|
readonly variant?: ContentVariant;
|
|
7
7
|
readonly hasLayoutPath: boolean;
|
|
8
|
+
readonly readOnly: boolean;
|
|
8
9
|
}
|
|
9
10
|
declare const FORMAT_CAPABILITIES: Readonly<Record<DocumentFormat, FormatCapability>>;
|
|
11
|
+
declare const READ_ONLY_FORMATS: ReadonlySet<DocumentFormat>;
|
|
10
12
|
declare class UnsupportedConversionError extends Error {
|
|
11
13
|
readonly source: DocumentFormat;
|
|
12
14
|
readonly target: DocumentFormat;
|
|
13
15
|
constructor(source: DocumentFormat, target: DocumentFormat);
|
|
14
16
|
}
|
|
15
17
|
//#endregion
|
|
16
|
-
export { UnsupportedConversionError as i, FORMAT_CAPABILITIES as n, FormatCapability as r, ContentVariant as t };
|
|
18
|
+
export { UnsupportedConversionError as a, READ_ONLY_FORMATS as i, FORMAT_CAPABILITIES as n, FormatCapability as r, ContentVariant as t };
|
package/dist/codecs/read.cjs
CHANGED
|
@@ -17,6 +17,7 @@ const require_ports_abort = require("../ports/abort.cjs");
|
|
|
17
17
|
const require_package_codec = require("../package-codec.cjs");
|
|
18
18
|
let ooxml_js = require("ooxml.js");
|
|
19
19
|
let rtf_codec = require("rtf-codec");
|
|
20
|
+
let wpd_codec = require("wpd-codec");
|
|
20
21
|
let pdf_codec_read = require("pdf-codec/read");
|
|
21
22
|
//#region src/codecs/read.ts
|
|
22
23
|
const CONTENT_READERS = {
|
|
@@ -58,6 +59,10 @@ const CONTENT_READERS = {
|
|
|
58
59
|
xlsx: (bytes, options) => {
|
|
59
60
|
require_ports_abort.throwIfAborted(options?.signal);
|
|
60
61
|
return (0, ooxml_js.readXlsxContent)(require_package_codec.decodeDocumentPackage("xlsx", require_model_bytes.requireArrayBufferBytes(bytes)));
|
|
62
|
+
},
|
|
63
|
+
wpd: (bytes, options) => {
|
|
64
|
+
require_ports_abort.throwIfAborted(options?.signal);
|
|
65
|
+
return (0, wpd_codec.readWpdContent)(bytes);
|
|
61
66
|
}
|
|
62
67
|
};
|
|
63
68
|
function readDocumentLayout(bytes, options) {
|
package/dist/codecs/read.js
CHANGED
|
@@ -16,6 +16,7 @@ import { throwIfAborted } from "../ports/abort.js";
|
|
|
16
16
|
import { decodeDocumentPackage } from "../package-codec.js";
|
|
17
17
|
import { readXlsxContent } from "ooxml.js";
|
|
18
18
|
import { readRtfContent } from "rtf-codec";
|
|
19
|
+
import { readWpdContent } from "wpd-codec";
|
|
19
20
|
import { readPdf } from "pdf-codec/read";
|
|
20
21
|
//#region src/codecs/read.ts
|
|
21
22
|
const CONTENT_READERS = {
|
|
@@ -57,6 +58,10 @@ const CONTENT_READERS = {
|
|
|
57
58
|
xlsx: (bytes, options) => {
|
|
58
59
|
throwIfAborted(options?.signal);
|
|
59
60
|
return readXlsxContent(decodeDocumentPackage("xlsx", requireArrayBufferBytes(bytes)));
|
|
61
|
+
},
|
|
62
|
+
wpd: (bytes, options) => {
|
|
63
|
+
throwIfAborted(options?.signal);
|
|
64
|
+
return readWpdContent(bytes);
|
|
60
65
|
}
|
|
61
66
|
};
|
|
62
67
|
function readDocumentLayout(bytes, options) {
|
package/dist/codecs/registry.cjs
CHANGED
|
@@ -66,7 +66,8 @@ const DOCUMENT_FORMAT_CODECS = {
|
|
|
66
66
|
xlsx: { content: {
|
|
67
67
|
read: require_codecs_read.CONTENT_READERS.xlsx,
|
|
68
68
|
write: (content) => require_package_codec.encodeDocumentPackage("xlsx", (0, ooxml_js.buildXlsxPackageFromContent)(content))
|
|
69
|
-
} }
|
|
69
|
+
} },
|
|
70
|
+
wpd: { content: { read: require_codecs_read.CONTENT_READERS.wpd } }
|
|
70
71
|
};
|
|
71
72
|
//#endregion
|
|
72
73
|
exports.DOCUMENT_FORMAT_CODECS = DOCUMENT_FORMAT_CODECS;
|
package/dist/codecs/registry.js
CHANGED
|
@@ -65,7 +65,8 @@ const DOCUMENT_FORMAT_CODECS = {
|
|
|
65
65
|
xlsx: { content: {
|
|
66
66
|
read: CONTENT_READERS.xlsx,
|
|
67
67
|
write: (content) => encodeDocumentPackage("xlsx", buildXlsxPackageFromContent(content))
|
|
68
|
-
} }
|
|
68
|
+
} },
|
|
69
|
+
wpd: { content: { read: CONTENT_READERS.wpd } }
|
|
69
70
|
};
|
|
70
71
|
//#endregion
|
|
71
72
|
export { DOCUMENT_FORMAT_CODECS };
|
|
@@ -4,68 +4,88 @@ const FORMAT_CAPABILITIES = {
|
|
|
4
4
|
docx: {
|
|
5
5
|
format: "docx",
|
|
6
6
|
variant: "wordprocessing",
|
|
7
|
-
hasLayoutPath: true
|
|
7
|
+
hasLayoutPath: true,
|
|
8
|
+
readOnly: false
|
|
8
9
|
},
|
|
9
10
|
odt: {
|
|
10
11
|
format: "odt",
|
|
11
12
|
variant: "wordprocessing",
|
|
12
|
-
hasLayoutPath: true
|
|
13
|
+
hasLayoutPath: true,
|
|
14
|
+
readOnly: false
|
|
13
15
|
},
|
|
14
16
|
pptx: {
|
|
15
17
|
format: "pptx",
|
|
16
18
|
variant: "presentation",
|
|
17
|
-
hasLayoutPath: true
|
|
19
|
+
hasLayoutPath: true,
|
|
20
|
+
readOnly: false
|
|
18
21
|
},
|
|
19
22
|
odp: {
|
|
20
23
|
format: "odp",
|
|
21
24
|
variant: "presentation",
|
|
22
|
-
hasLayoutPath: true
|
|
25
|
+
hasLayoutPath: true,
|
|
26
|
+
readOnly: false
|
|
23
27
|
},
|
|
24
28
|
ods: {
|
|
25
29
|
format: "ods",
|
|
26
30
|
variant: "spreadsheet",
|
|
27
|
-
hasLayoutPath: true
|
|
31
|
+
hasLayoutPath: true,
|
|
32
|
+
readOnly: false
|
|
28
33
|
},
|
|
29
34
|
xlsx: {
|
|
30
35
|
format: "xlsx",
|
|
31
36
|
variant: "spreadsheet",
|
|
32
|
-
hasLayoutPath: false
|
|
37
|
+
hasLayoutPath: false,
|
|
38
|
+
readOnly: false
|
|
33
39
|
},
|
|
34
40
|
csv: {
|
|
35
41
|
format: "csv",
|
|
36
42
|
variant: "spreadsheet",
|
|
37
|
-
hasLayoutPath: false
|
|
43
|
+
hasLayoutPath: false,
|
|
44
|
+
readOnly: false
|
|
38
45
|
},
|
|
39
46
|
odg: {
|
|
40
47
|
format: "odg",
|
|
41
48
|
variant: "drawing",
|
|
42
|
-
hasLayoutPath: true
|
|
49
|
+
hasLayoutPath: true,
|
|
50
|
+
readOnly: false
|
|
43
51
|
},
|
|
44
52
|
svg: {
|
|
45
53
|
format: "svg",
|
|
46
54
|
variant: "drawing",
|
|
47
|
-
hasLayoutPath: true
|
|
55
|
+
hasLayoutPath: true,
|
|
56
|
+
readOnly: false
|
|
48
57
|
},
|
|
49
58
|
odf: {
|
|
50
59
|
format: "odf",
|
|
51
60
|
variant: "formula",
|
|
52
|
-
hasLayoutPath: false
|
|
61
|
+
hasLayoutPath: false,
|
|
62
|
+
readOnly: true
|
|
53
63
|
},
|
|
54
64
|
markdown: {
|
|
55
65
|
format: "markdown",
|
|
56
66
|
variant: "wordprocessing",
|
|
57
|
-
hasLayoutPath: true
|
|
67
|
+
hasLayoutPath: true,
|
|
68
|
+
readOnly: false
|
|
58
69
|
},
|
|
59
70
|
rtf: {
|
|
60
71
|
format: "rtf",
|
|
61
72
|
variant: "wordprocessing",
|
|
62
|
-
hasLayoutPath: false
|
|
73
|
+
hasLayoutPath: false,
|
|
74
|
+
readOnly: false
|
|
75
|
+
},
|
|
76
|
+
wpd: {
|
|
77
|
+
format: "wpd",
|
|
78
|
+
variant: "wordprocessing",
|
|
79
|
+
hasLayoutPath: true,
|
|
80
|
+
readOnly: true
|
|
63
81
|
},
|
|
64
82
|
pdf: {
|
|
65
83
|
format: "pdf",
|
|
66
|
-
hasLayoutPath: false
|
|
84
|
+
hasLayoutPath: false,
|
|
85
|
+
readOnly: false
|
|
67
86
|
}
|
|
68
87
|
};
|
|
88
|
+
const READ_ONLY_FORMATS = new Set(Object.values(FORMAT_CAPABILITIES).filter((capability) => capability.readOnly).map((capability) => capability.format));
|
|
69
89
|
var UnsupportedConversionError = class extends Error {
|
|
70
90
|
source;
|
|
71
91
|
target;
|
|
@@ -78,4 +98,5 @@ var UnsupportedConversionError = class extends Error {
|
|
|
78
98
|
};
|
|
79
99
|
//#endregion
|
|
80
100
|
exports.FORMAT_CAPABILITIES = FORMAT_CAPABILITIES;
|
|
101
|
+
exports.READ_ONLY_FORMATS = READ_ONLY_FORMATS;
|
|
81
102
|
exports.UnsupportedConversionError = UnsupportedConversionError;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { ContentVariant, FORMAT_CAPABILITIES, FormatCapability, UnsupportedConversionError };
|
|
1
|
+
import { a as UnsupportedConversionError, i as READ_ONLY_FORMATS, n as FORMAT_CAPABILITIES, r as FormatCapability, t as ContentVariant } from "../capability-WJWAE-5Z.cjs";
|
|
2
|
+
export { ContentVariant, FORMAT_CAPABILITIES, FormatCapability, READ_ONLY_FORMATS, UnsupportedConversionError };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { ContentVariant, FORMAT_CAPABILITIES, FormatCapability, UnsupportedConversionError };
|
|
1
|
+
import { a as UnsupportedConversionError, i as READ_ONLY_FORMATS, n as FORMAT_CAPABILITIES, r as FormatCapability, t as ContentVariant } from "../capability-BmRwrPL9.js";
|
|
2
|
+
export { ContentVariant, FORMAT_CAPABILITIES, FormatCapability, READ_ONLY_FORMATS, UnsupportedConversionError };
|
|
@@ -3,68 +3,88 @@ const FORMAT_CAPABILITIES = {
|
|
|
3
3
|
docx: {
|
|
4
4
|
format: "docx",
|
|
5
5
|
variant: "wordprocessing",
|
|
6
|
-
hasLayoutPath: true
|
|
6
|
+
hasLayoutPath: true,
|
|
7
|
+
readOnly: false
|
|
7
8
|
},
|
|
8
9
|
odt: {
|
|
9
10
|
format: "odt",
|
|
10
11
|
variant: "wordprocessing",
|
|
11
|
-
hasLayoutPath: true
|
|
12
|
+
hasLayoutPath: true,
|
|
13
|
+
readOnly: false
|
|
12
14
|
},
|
|
13
15
|
pptx: {
|
|
14
16
|
format: "pptx",
|
|
15
17
|
variant: "presentation",
|
|
16
|
-
hasLayoutPath: true
|
|
18
|
+
hasLayoutPath: true,
|
|
19
|
+
readOnly: false
|
|
17
20
|
},
|
|
18
21
|
odp: {
|
|
19
22
|
format: "odp",
|
|
20
23
|
variant: "presentation",
|
|
21
|
-
hasLayoutPath: true
|
|
24
|
+
hasLayoutPath: true,
|
|
25
|
+
readOnly: false
|
|
22
26
|
},
|
|
23
27
|
ods: {
|
|
24
28
|
format: "ods",
|
|
25
29
|
variant: "spreadsheet",
|
|
26
|
-
hasLayoutPath: true
|
|
30
|
+
hasLayoutPath: true,
|
|
31
|
+
readOnly: false
|
|
27
32
|
},
|
|
28
33
|
xlsx: {
|
|
29
34
|
format: "xlsx",
|
|
30
35
|
variant: "spreadsheet",
|
|
31
|
-
hasLayoutPath: false
|
|
36
|
+
hasLayoutPath: false,
|
|
37
|
+
readOnly: false
|
|
32
38
|
},
|
|
33
39
|
csv: {
|
|
34
40
|
format: "csv",
|
|
35
41
|
variant: "spreadsheet",
|
|
36
|
-
hasLayoutPath: false
|
|
42
|
+
hasLayoutPath: false,
|
|
43
|
+
readOnly: false
|
|
37
44
|
},
|
|
38
45
|
odg: {
|
|
39
46
|
format: "odg",
|
|
40
47
|
variant: "drawing",
|
|
41
|
-
hasLayoutPath: true
|
|
48
|
+
hasLayoutPath: true,
|
|
49
|
+
readOnly: false
|
|
42
50
|
},
|
|
43
51
|
svg: {
|
|
44
52
|
format: "svg",
|
|
45
53
|
variant: "drawing",
|
|
46
|
-
hasLayoutPath: true
|
|
54
|
+
hasLayoutPath: true,
|
|
55
|
+
readOnly: false
|
|
47
56
|
},
|
|
48
57
|
odf: {
|
|
49
58
|
format: "odf",
|
|
50
59
|
variant: "formula",
|
|
51
|
-
hasLayoutPath: false
|
|
60
|
+
hasLayoutPath: false,
|
|
61
|
+
readOnly: true
|
|
52
62
|
},
|
|
53
63
|
markdown: {
|
|
54
64
|
format: "markdown",
|
|
55
65
|
variant: "wordprocessing",
|
|
56
|
-
hasLayoutPath: true
|
|
66
|
+
hasLayoutPath: true,
|
|
67
|
+
readOnly: false
|
|
57
68
|
},
|
|
58
69
|
rtf: {
|
|
59
70
|
format: "rtf",
|
|
60
71
|
variant: "wordprocessing",
|
|
61
|
-
hasLayoutPath: false
|
|
72
|
+
hasLayoutPath: false,
|
|
73
|
+
readOnly: false
|
|
74
|
+
},
|
|
75
|
+
wpd: {
|
|
76
|
+
format: "wpd",
|
|
77
|
+
variant: "wordprocessing",
|
|
78
|
+
hasLayoutPath: true,
|
|
79
|
+
readOnly: true
|
|
62
80
|
},
|
|
63
81
|
pdf: {
|
|
64
82
|
format: "pdf",
|
|
65
|
-
hasLayoutPath: false
|
|
83
|
+
hasLayoutPath: false,
|
|
84
|
+
readOnly: false
|
|
66
85
|
}
|
|
67
86
|
};
|
|
87
|
+
const READ_ONLY_FORMATS = new Set(Object.values(FORMAT_CAPABILITIES).filter((capability) => capability.readOnly).map((capability) => capability.format));
|
|
68
88
|
var UnsupportedConversionError = class extends Error {
|
|
69
89
|
source;
|
|
70
90
|
target;
|
|
@@ -76,4 +96,4 @@ var UnsupportedConversionError = class extends Error {
|
|
|
76
96
|
}
|
|
77
97
|
};
|
|
78
98
|
//#endregion
|
|
79
|
-
export { FORMAT_CAPABILITIES, UnsupportedConversionError };
|
|
99
|
+
export { FORMAT_CAPABILITIES, READ_ONLY_FORMATS, UnsupportedConversionError };
|
|
@@ -20,9 +20,22 @@ const LAYOUT_ENGINES = {
|
|
|
20
20
|
};
|
|
21
21
|
function executeToPdf(format, bytes, options) {
|
|
22
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
23
|
let content;
|
|
25
24
|
let fonts;
|
|
25
|
+
if (require_convert_composition.isReadOnlyContentFormat(format)) {
|
|
26
|
+
require_ports_abort.throwIfAborted(options?.signal);
|
|
27
|
+
const read = require_convert_composition.READ_ONLY_FORMAT_NODES[format].read(bytes, options);
|
|
28
|
+
content = {
|
|
29
|
+
...read,
|
|
30
|
+
metadata: require_model_metadata.resolveMetadataTimestamps(read.metadata, options?.clock)
|
|
31
|
+
};
|
|
32
|
+
fonts = (0, pdf_codec.createFontRegistry)({
|
|
33
|
+
fonts: options?.fonts,
|
|
34
|
+
onSubstitution: options?.onFontSubstitution
|
|
35
|
+
});
|
|
36
|
+
return renderToPdf(content, fonts, options);
|
|
37
|
+
}
|
|
38
|
+
const node = require_convert_composition.FORMAT_NODES[format];
|
|
26
39
|
if (require_convert_composition.isTextFormatNode(node)) {
|
|
27
40
|
require_ports_abort.throwIfAborted(options?.signal);
|
|
28
41
|
const text = node.decode(bytes);
|
|
@@ -57,6 +70,9 @@ function executeToPdf(format, bytes, options) {
|
|
|
57
70
|
onFontSubstitution: options?.onFontSubstitution
|
|
58
71
|
});
|
|
59
72
|
}
|
|
73
|
+
return renderToPdf(content, fonts, options);
|
|
74
|
+
}
|
|
75
|
+
function renderToPdf(content, fonts, options) {
|
|
60
76
|
const measurer = (0, pdf_codec.createFontMeasurer)(fonts);
|
|
61
77
|
let layout;
|
|
62
78
|
let pages;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DocumentFormat } from "./port.cjs";
|
|
2
|
-
import {
|
|
2
|
+
import { SourceContentFormat, UnifiedConversionOptions } from "./composition.cjs";
|
|
3
3
|
//#region src/convert/composition-to-pdf.d.ts
|
|
4
|
-
declare function executeToPdf(format:
|
|
4
|
+
declare function executeToPdf(format: SourceContentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
|
|
5
5
|
declare function convertDocument(source: DocumentFormat, target: DocumentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { convertDocument, executeToPdf };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DocumentFormat } from "./port.js";
|
|
2
|
-
import {
|
|
2
|
+
import { SourceContentFormat, UnifiedConversionOptions } from "./composition.js";
|
|
3
3
|
//#region src/convert/composition-to-pdf.d.ts
|
|
4
|
-
declare function executeToPdf(format:
|
|
4
|
+
declare function executeToPdf(format: SourceContentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
|
|
5
5
|
declare function convertDocument(source: DocumentFormat, target: DocumentFormat, bytes: Uint8Array<ArrayBuffer>, options?: UnifiedConversionOptions): Uint8Array<ArrayBuffer>;
|
|
6
6
|
//#endregion
|
|
7
7
|
export { convertDocument, executeToPdf };
|
|
@@ -6,7 +6,7 @@ import { throwIfAborted } from "../ports/abort.js";
|
|
|
6
6
|
import { convertSpreadsheetToLayout } from "../layout/sheets.js";
|
|
7
7
|
import { convertDrawingToLayout } from "../layout/drawing.js";
|
|
8
8
|
import { UnsupportedConversionError } from "./capability.js";
|
|
9
|
-
import { FORMAT_NODES, LAYOUT_CAPABLE, executeBridge, executeFromPdf, isTextFormatNode, resolveCompositionPlan, runCompositionPlan } from "./composition.js";
|
|
9
|
+
import { FORMAT_NODES, LAYOUT_CAPABLE, READ_ONLY_FORMAT_NODES, executeBridge, executeFromPdf, isReadOnlyContentFormat, isTextFormatNode, resolveCompositionPlan, runCompositionPlan } from "./composition.js";
|
|
10
10
|
import { assembleTree } from "document-schema.js";
|
|
11
11
|
import { createFontMeasurer, createFontRegistry, loadMathFont, writePdf } from "pdf-codec";
|
|
12
12
|
//#region src/convert/composition-to-pdf.ts
|
|
@@ -19,9 +19,22 @@ const LAYOUT_ENGINES = {
|
|
|
19
19
|
};
|
|
20
20
|
function executeToPdf(format, bytes, options) {
|
|
21
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
22
|
let content;
|
|
24
23
|
let fonts;
|
|
24
|
+
if (isReadOnlyContentFormat(format)) {
|
|
25
|
+
throwIfAborted(options?.signal);
|
|
26
|
+
const read = READ_ONLY_FORMAT_NODES[format].read(bytes, options);
|
|
27
|
+
content = {
|
|
28
|
+
...read,
|
|
29
|
+
metadata: resolveMetadataTimestamps(read.metadata, options?.clock)
|
|
30
|
+
};
|
|
31
|
+
fonts = createFontRegistry({
|
|
32
|
+
fonts: options?.fonts,
|
|
33
|
+
onSubstitution: options?.onFontSubstitution
|
|
34
|
+
});
|
|
35
|
+
return renderToPdf(content, fonts, options);
|
|
36
|
+
}
|
|
37
|
+
const node = FORMAT_NODES[format];
|
|
25
38
|
if (isTextFormatNode(node)) {
|
|
26
39
|
throwIfAborted(options?.signal);
|
|
27
40
|
const text = node.decode(bytes);
|
|
@@ -56,6 +69,9 @@ function executeToPdf(format, bytes, options) {
|
|
|
56
69
|
onFontSubstitution: options?.onFontSubstitution
|
|
57
70
|
});
|
|
58
71
|
}
|
|
72
|
+
return renderToPdf(content, fonts, options);
|
|
73
|
+
}
|
|
74
|
+
function renderToPdf(content, fonts, options) {
|
|
59
75
|
const measurer = createFontMeasurer(fonts);
|
|
60
76
|
let layout;
|
|
61
77
|
let pages;
|