document-schema.js 2.3.1 → 2.3.2

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![GitHub](https://img.shields.io/badge/GitHub-181717?logo=github&logoColor=white)](https://github.com/ExaDev/document-schema.js) [![npm](https://img.shields.io/badge/npm-CB3837?logo=npm&logoColor=white)](https://www.npmjs.com/package/document-schema.js) [![Release](https://img.shields.io/github/v/release/ExaDev/document-schema.js)](https://github.com/ExaDev/document-schema.js/releases/latest) [![CI](https://img.shields.io/github/actions/workflow/status/ExaDev/document-schema.js/ci.yml?branch=main)](https://github.com/ExaDev/document-schema.js/actions)
4
4
 
5
- > The canonical, format-agnostic content and layout schema pivot shared by [ooxml.js](https://github.com/ExaDev/ooxml.js), [odf.js](https://github.com/ExaDev/odf.js), [documents.js](https://github.com/ExaDev/documents.js), and [pdf-codec](https://github.com/ExaDev/pdf-codec).
5
+ > The canonical, format-agnostic content and layout schema pivot shared by [ooxml.js](https://github.com/ExaDev/ooxml.js), [odf.js](https://github.com/ExaDev/odf.js), [documents.js](https://github.com/ExaDev/documents.js), [pdf-codec](https://github.com/ExaDev/pdf-codec), and [markdown-codec](https://github.com/ExaDev/markdown-codec).
6
6
 
7
7
  Both `ooxml.js` and `documents.js` independently arrived at the same content vocabulary -- paragraphs, runs, tables, images, shapes, slides -- because `documents.js`'s docx/pptx-to-PDF pipeline needed a richer model than `ooxml.js`'s own readers originally produced, and that model was later ported back into `ooxml.js` itself. The result was two field-identical copies maintained in two places. This package is the fix: one schema, imported by every format package instead of redefined by each. It also sidesteps a circular dependency that would otherwise appear once `odf.js` exists, since `documents.js` depends on both `ooxml.js` and `odf.js`.
8
8
 
@@ -27,6 +27,7 @@ graph TD
27
27
  mdcodec --> documents
28
28
  documents --> cli
29
29
  odf --> cli
30
+ pdfcodec --> cli
30
31
 
31
32
  click schema "https://github.com/ExaDev/document-schema.js" "document-schema.js"
32
33
  click ooxml "https://github.com/ExaDev/ooxml.js" "ooxml.js"
@@ -41,7 +42,7 @@ graph TD
41
42
 
42
43
  `ContentDocument` (the semantic pivot) is a discriminated union of five kinds: `wordprocessing` (docx/odt-style sections of paragraphs/runs/tables/images), `presentation` (pptx/odp-style slides of shapes), `spreadsheet` (xlsx/ods-style sheets of cells, columns, rows, and print settings), `drawing` (odg-style pages of shapes plus vector primitives -- rect/ellipse/line/path), and `formula` (an equation, carrying its own MathML presentation-layer node tree plus the StarMath source when the producing format had one). `ContentEmbeddedObjectSchema` lets any of the five embed another whole `ContentDocument` -- including a `formula` one, which is what an embedded equation inside a document or slide now carries. `LayoutDocument` (the PDF-rendering pivot) is pages of positioned `LayoutItem`s -- `text`/`image`/`rect`/`line`/`ellipse`/`path`/`link` -- in PDF user-space coordinates, with `LayoutPathSchema` modelling a general vector path rather than only axis-aligned rectangles. `DocumentPackageSchema` is a small envelope pairing the two: `content` required, `layout` optional (it's a derived artifact, absent until something lays the content out), correlated via each item's own `sourcePath` when both are present -- a pairing this schema does not itself keep in sync or detect as stale.
43
44
 
44
- It contains only [Zod](https://zod.dev) schemas, their inferred types, and a handful of trivial schema-attached helpers (hex-colour conversion, recursive structural type guards for the mutually-recursive table/block/embedded-object types and for the MathML node tree). There is no XML, ZIP, PDF, or other binary handling here, and no `zod` dependency other than `zod` itself.
45
+ It contains only [Zod](https://zod.dev) schemas, their inferred types, a handful of trivial schema-attached helpers (hex-colour conversion, recursive structural type guards for the mutually-recursive table/block/embedded-object types and for the MathML node tree), and two small structural interfaces (`ContentCodec`/`LayoutCodec`, see [Codecs](#codecs) below) that a sibling package's own format codec can implement -- no runtime code of their own either. There is no XML, ZIP, PDF, or other binary handling here, and no `zod` dependency other than `zod` itself.
45
46
 
46
47
  The GitHub repository is [`ExaDev/document-schema.js`](https://github.com/ExaDev/document-schema.js), matching the published npm package name.
47
48
 
@@ -62,6 +63,21 @@ import { schemaUriFor } from 'document-schema.js/schema-io';
62
63
  import { ColorSchema } from 'document-schema.js/color';
63
64
  ```
64
65
 
66
+ ## Codecs
67
+
68
+ Alongside the schemas themselves, `ContentCodec`/`LayoutCodec` (`src/codec.ts`) are the format-agnostic *interfaces* a sibling package's own docx/pptx/odt/odp/ods/odg/xlsx/markdown/PDF codec can implement, so a caller working across formats can hold one of these instead of a format-specific function pair:
69
+
70
+ ```ts
71
+ import type { ContentCodec, LayoutCodec } from 'document-schema.js';
72
+
73
+ declare const docxCodec: ContentCodec; // read(bytes) -> ContentDocument; write(content) -> bytes -- write is optional
74
+ declare const pdfCodec: LayoutCodec; // read(bytes) -> LayoutDocument; write(layout) -> bytes -- write is required
75
+ ```
76
+
77
+ The two are deliberately separate interfaces rather than one `DocumentCodec` shaped like `DocumentPackage`, because the formats they model are asymmetric: most formats (docx/pptx/odt/odp/ods/odg/markdown) only ever produce *content* on read, with layout always a later, engine-driven step; PDF is the mirror image, producing *layout* cheaply on read and content only via a separate, expensive, lossy, opt-in reconstruction pass that is emphatically not part of "reading" a PDF. `ContentCodec.write` is deliberately optional -- this models a real, permanent asymmetry, not a temporary gap: the `odf` format (a standalone ODF formula document) has a reader but genuinely no builder at all, since recovering structured MathML from rendered glyphs is a categorically different, OCR-adjacent problem than generating them. `LayoutCodec.write` is not optional, since PDF -- the only format with a `LayoutCodec` implementation anywhere in this family -- always supports both directions equally readily. Both interfaces are generic over their own `TOptions` (defaulting to `unknown`) rather than sharing one options shape across every implementation, since each real format's own read/write options are format-specific today (an `AbortSignal`, a font-substitution callback, a diagnostic sink) and forcing them into one shared shape would either be too narrow for some formats or carry fields meaningless to others.
78
+
79
+ Neither interface constructs a `DocumentPackage` itself: a codec's `read()` returns one half (content, or layout, never both), and composing a `DocumentPackage` from a `ContentCodec.read()` result plus a separately-run layout-engine pass is the caller's job, one level up from either interface -- `documents.js`'s own `DOCUMENT_FORMAT_CODECS` registry (`src/codecs/registry.ts`) is the concrete example, implementing a `ContentCodec`/`LayoutCodec` pair per format over its own existing read/build/layout functions.
80
+
65
81
  ## JSON Schema
66
82
 
67
83
  Alongside the Zod schemas/types above, the package publishes three plain [JSON Schema](https://json-schema.org) files -- generated from the same Zod definitions via [`z.toJSONSchema()`](https://zod.dev/json-schema) at build time (`scripts/generate-json-schemas.mjs`) -- for non-TypeScript consumers that want to validate against or generate types from these shapes without depending on Zod at all:
@@ -139,10 +155,11 @@ try {
139
155
 
140
156
  - [ooxml.js](https://github.com/ExaDev/ooxml.js) — its `readDocx`/`readPptx`/`readXlsxContent` return `ContentSection[]`/`ContentSlide[]`/spreadsheet `ContentSheet[]` typed against this package's own schemas, not a locally-defined lookalike.
141
157
  - [odf.js](https://github.com/ExaDev/odf.js) — its ODF typed readers (`readOdt`, `readOdp`, `readOds`, `readOdg`, …) return the same shared types, so an ODF document and an OOXML document speak the identical pivot.
142
- - [documents.js](https://github.com/ExaDev/documents.js) — the primary consumer of both `ContentDocument` and `LayoutDocument`, which it converts between via its layout engines and its `pdf-codec` dependency, and of `DocumentPackage` as the `onDocument` side-channel value its conversion functions hand back.
158
+ - [documents.js](https://github.com/ExaDev/documents.js) — the primary consumer of both `ContentDocument` and `LayoutDocument`, which it converts between via its layout engines and its `pdf-codec` dependency, and of `DocumentPackage` as the `onDocument` side-channel value its conversion functions hand back. Its own `DOCUMENT_FORMAT_CODECS` registry additionally implements this package's `ContentCodec`/`LayoutCodec` interfaces per format, over its existing read/build/layout functions.
143
159
  - [pdf-codec](https://github.com/ExaDev/pdf-codec) — the hand-written PDF codec extracted from `documents.js`: `readPdf`/`writePdf` and its own `pdfCodec` z.codec() pair operate entirely in terms of this package's `LayoutDocument` (plus the item kinds it's built from -- `LayoutItem`/`LayoutText`/`LayoutImage`/`LayoutRect`/`LayoutEllipse`/`LayoutLink`/`LayoutPath`/`LayoutSubpath`/`LayoutPathSegment`/`LayoutPage`/`LayoutImageAsset`/`LayoutMetadata`), `Color`/`LayoutFont` (aliased `LayoutColor`/`LayoutFont` at its own call sites), and `LAYOUT_FORMAT_VERSION`/`COLOR_BLACK`/`LayoutDocumentSchema` -- it never redeclares any of these itself, unlike its own `MathBox`/`PositionedFormula` mirror of `documents.js`'s MathML types (a deliberate, narrower exception -- see pdf-codec's own README).
160
+ - [markdown-codec](https://github.com/ExaDev/markdown-codec) — the hand-written CommonMark+GFM codec: `readMarkdown`/`writeMarkdown` and its own `markdownCodec` z.codec() pair read and write this package's `ContentDocument` directly, the identical `wordprocessing` pivot `ooxml.js`'s `readDocx` and `odf.js`'s `readOdt` also produce.
144
161
 
145
- None of these four packages depend on each other for this vocabulary — each depends on `document-schema.js` directly, which is the whole point: one schema, not four independently-maintained, drift-prone copies.
162
+ None of these five packages depend on each other for this vocabulary — each depends on `document-schema.js` directly, which is the whole point: one schema, not five independently-maintained, drift-prone copies.
146
163
 
147
164
  ## npm aliases
148
165
 
package/dist/layout.d.cts CHANGED
@@ -9,12 +9,12 @@ declare const LayoutTextSchema: z.ZodObject<{
9
9
  font: z.ZodObject<{
10
10
  family: z.ZodString;
11
11
  weight: z.ZodEnum<{
12
- bold: "bold";
13
12
  normal: "normal";
13
+ bold: "bold";
14
14
  }>;
15
15
  style: z.ZodEnum<{
16
- italic: "italic";
17
16
  normal: "normal";
17
+ italic: "italic";
18
18
  }>;
19
19
  }, z.core.$strip>;
20
20
  sizePt: z.ZodNumber;
@@ -202,12 +202,12 @@ declare const LayoutItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
202
202
  font: z.ZodObject<{
203
203
  family: z.ZodString;
204
204
  weight: z.ZodEnum<{
205
- bold: "bold";
206
205
  normal: "normal";
206
+ bold: "bold";
207
207
  }>;
208
208
  style: z.ZodEnum<{
209
- italic: "italic";
210
209
  normal: "normal";
210
+ italic: "italic";
211
211
  }>;
212
212
  }, z.core.$strip>;
213
213
  sizePt: z.ZodNumber;
@@ -353,12 +353,12 @@ declare const LayoutPageSchema: z.ZodObject<{
353
353
  font: z.ZodObject<{
354
354
  family: z.ZodString;
355
355
  weight: z.ZodEnum<{
356
- bold: "bold";
357
356
  normal: "normal";
357
+ bold: "bold";
358
358
  }>;
359
359
  style: z.ZodEnum<{
360
- italic: "italic";
361
360
  normal: "normal";
361
+ italic: "italic";
362
362
  }>;
363
363
  }, z.core.$strip>;
364
364
  sizePt: z.ZodNumber;
@@ -528,12 +528,12 @@ declare const LayoutDocumentSchema: z.ZodObject<{
528
528
  font: z.ZodObject<{
529
529
  family: z.ZodString;
530
530
  weight: z.ZodEnum<{
531
- bold: "bold";
532
531
  normal: "normal";
532
+ bold: "bold";
533
533
  }>;
534
534
  style: z.ZodEnum<{
535
- italic: "italic";
536
535
  normal: "normal";
536
+ italic: "italic";
537
537
  }>;
538
538
  }, z.core.$strip>;
539
539
  sizePt: z.ZodNumber;
package/dist/layout.d.ts CHANGED
@@ -9,12 +9,12 @@ declare const LayoutTextSchema: z.ZodObject<{
9
9
  font: z.ZodObject<{
10
10
  family: z.ZodString;
11
11
  weight: z.ZodEnum<{
12
- bold: "bold";
13
12
  normal: "normal";
13
+ bold: "bold";
14
14
  }>;
15
15
  style: z.ZodEnum<{
16
- italic: "italic";
17
16
  normal: "normal";
17
+ italic: "italic";
18
18
  }>;
19
19
  }, z.core.$strip>;
20
20
  sizePt: z.ZodNumber;
@@ -202,12 +202,12 @@ declare const LayoutItemSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
202
202
  font: z.ZodObject<{
203
203
  family: z.ZodString;
204
204
  weight: z.ZodEnum<{
205
- bold: "bold";
206
205
  normal: "normal";
206
+ bold: "bold";
207
207
  }>;
208
208
  style: z.ZodEnum<{
209
- italic: "italic";
210
209
  normal: "normal";
210
+ italic: "italic";
211
211
  }>;
212
212
  }, z.core.$strip>;
213
213
  sizePt: z.ZodNumber;
@@ -353,12 +353,12 @@ declare const LayoutPageSchema: z.ZodObject<{
353
353
  font: z.ZodObject<{
354
354
  family: z.ZodString;
355
355
  weight: z.ZodEnum<{
356
- bold: "bold";
357
356
  normal: "normal";
357
+ bold: "bold";
358
358
  }>;
359
359
  style: z.ZodEnum<{
360
- italic: "italic";
361
360
  normal: "normal";
361
+ italic: "italic";
362
362
  }>;
363
363
  }, z.core.$strip>;
364
364
  sizePt: z.ZodNumber;
@@ -528,12 +528,12 @@ declare const LayoutDocumentSchema: z.ZodObject<{
528
528
  font: z.ZodObject<{
529
529
  family: z.ZodString;
530
530
  weight: z.ZodEnum<{
531
- bold: "bold";
532
531
  normal: "normal";
532
+ bold: "bold";
533
533
  }>;
534
534
  style: z.ZodEnum<{
535
- italic: "italic";
536
535
  normal: "normal";
536
+ italic: "italic";
537
537
  }>;
538
538
  }, z.core.$strip>;
539
539
  sizePt: z.ZodNumber;
@@ -515,12 +515,12 @@ declare const DocumentPackageSchema: z.ZodObject<{
515
515
  font: z.ZodObject<{
516
516
  family: z.ZodString;
517
517
  weight: z.ZodEnum<{
518
- bold: "bold";
519
518
  normal: "normal";
519
+ bold: "bold";
520
520
  }>;
521
521
  style: z.ZodEnum<{
522
- italic: "italic";
523
522
  normal: "normal";
523
+ italic: "italic";
524
524
  }>;
525
525
  }, z.core.$strip>;
526
526
  sizePt: z.ZodNumber;
package/dist/package.d.ts CHANGED
@@ -515,12 +515,12 @@ declare const DocumentPackageSchema: z.ZodObject<{
515
515
  font: z.ZodObject<{
516
516
  family: z.ZodString;
517
517
  weight: z.ZodEnum<{
518
- bold: "bold";
519
518
  normal: "normal";
519
+ bold: "bold";
520
520
  }>;
521
521
  style: z.ZodEnum<{
522
- italic: "italic";
523
522
  normal: "normal";
523
+ italic: "italic";
524
524
  }>;
525
525
  }, z.core.$strip>;
526
526
  sizePt: z.ZodNumber;
@@ -9,7 +9,7 @@ const SCHEMA_FILE_NAMES = {
9
9
  LayoutDocument: "layout-document.schema.json"
10
10
  };
11
11
  function schemaUriFor(kind) {
12
- return `https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/${SCHEMA_FILE_NAMES[kind]}`;
12
+ return `https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/${SCHEMA_FILE_NAMES[kind]}`;
13
13
  }
14
14
  const SCHEMA_URI_PATTERN = /^https:\/\/cdn\.jsdelivr\.net\/npm\/document-schema\.js@[^/]+\/schemas\/(document-package|content-document|layout-document)\.schema\.json$/;
15
15
  function kindForFileStem(stem) {
package/dist/schema-io.js CHANGED
@@ -8,7 +8,7 @@ const SCHEMA_FILE_NAMES = {
8
8
  LayoutDocument: "layout-document.schema.json"
9
9
  };
10
10
  function schemaUriFor(kind) {
11
- return `https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/${SCHEMA_FILE_NAMES[kind]}`;
11
+ return `https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/${SCHEMA_FILE_NAMES[kind]}`;
12
12
  }
13
13
  const SCHEMA_URI_PATTERN = /^https:\/\/cdn\.jsdelivr\.net\/npm\/document-schema\.js@[^/]+\/schemas\/(document-package|content-document|layout-document)\.schema\.json$/;
14
14
  function kindForFileStem(stem) {
package/dist/style.d.cts CHANGED
@@ -10,12 +10,12 @@ type Alignment = z.infer<typeof AlignmentSchema>;
10
10
  declare const LayoutFontSchema: z.ZodObject<{
11
11
  family: z.ZodString;
12
12
  weight: z.ZodEnum<{
13
- bold: "bold";
14
13
  normal: "normal";
14
+ bold: "bold";
15
15
  }>;
16
16
  style: z.ZodEnum<{
17
- italic: "italic";
18
17
  normal: "normal";
18
+ italic: "italic";
19
19
  }>;
20
20
  }, z.core.$strip>;
21
21
  type LayoutFont = z.infer<typeof LayoutFontSchema>;
package/dist/style.d.ts CHANGED
@@ -10,12 +10,12 @@ type Alignment = z.infer<typeof AlignmentSchema>;
10
10
  declare const LayoutFontSchema: z.ZodObject<{
11
11
  family: z.ZodString;
12
12
  weight: z.ZodEnum<{
13
- bold: "bold";
14
13
  normal: "normal";
14
+ bold: "bold";
15
15
  }>;
16
16
  style: z.ZodEnum<{
17
- italic: "italic";
18
17
  normal: "normal";
18
+ italic: "italic";
19
19
  }>;
20
20
  }, z.core.$strip>;
21
21
  type LayoutFont = z.infer<typeof LayoutFontSchema>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "document-schema.js",
3
- "version": "2.3.1",
3
+ "version": "2.3.2",
4
4
  "description": "The canonical, format-agnostic content and layout schemas shared by ooxml.js, odf.js, and documents.js -- pure Zod schemas, no behaviour.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/content-document.schema.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/content-document.schema.json",
4
4
  "oneOf": [
5
5
  {
6
6
  "type": "object",
@@ -1208,7 +1208,7 @@
1208
1208
  ]
1209
1209
  },
1210
1210
  "document": {
1211
- "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/content-document.schema.json"
1211
+ "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/content-document.schema.json"
1212
1212
  },
1213
1213
  "frame": {
1214
1214
  "$ref": "#/$defs/Box"
@@ -2499,7 +2499,7 @@
2499
2499
  ]
2500
2500
  },
2501
2501
  "document": {
2502
- "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/content-document.schema.json"
2502
+ "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/content-document.schema.json"
2503
2503
  },
2504
2504
  "frame": {
2505
2505
  "$ref": "#/$defs/Box"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/document-package.schema.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/document-package.schema.json",
4
4
  "type": "object",
5
5
  "properties": {
6
6
  "formatVersion": {
@@ -8,10 +8,10 @@
8
8
  "const": 1
9
9
  },
10
10
  "content": {
11
- "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/content-document.schema.json"
11
+ "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/content-document.schema.json"
12
12
  },
13
13
  "layout": {
14
- "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/layout-document.schema.json"
14
+ "$ref": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/layout-document.schema.json"
15
15
  }
16
16
  },
17
17
  "required": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.1/schemas/layout-document.schema.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/document-schema.js@2.3.2/schemas/layout-document.schema.json",
4
4
  "type": "object",
5
5
  "properties": {
6
6
  "formatVersion": {