document-schema.js 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,7 +48,7 @@ graph TD
48
48
  style schema fill:#f9a825,stroke:#333,stroke-width:3px
49
49
  ```
50
50
 
51
- `ContentDocument` (the semantic pivot) is a discriminated union of five kinds: `wordprocessing` (docx/odt sections of paragraphs/runs/tables/images), `presentation` (pptx/odp slides of shapes), `spreadsheet` (xlsx/ods sheets of cells, columns, rows, print settings), `drawing` (odg pages of shapes plus vector primitives — rect/ellipse/line/path), and `formula` (an equation carrying its own MathML node tree plus StarMath source when the producing format had one). `ContentEmbeddedObjectSchema` lets any of the five embed another whole `ContentDocument`. Every paragraph/run/image/table/shape/vector/spreadsheet-cell leaf also carries its own canonical `headingLevel`-or-position fields directly: a `ContentParagraph`'s optional `headingLevel` (1 = the outermost heading, independent of the round-trip-only `styleId`), and every such leaf's optional `frames: LayoutFrame[]` — that node's own rendered page position(s) (`pageIndex` plus PDF user-space `xPt`/`yPt`/`widthPt`/`heightPt`), fused directly onto the content tree once a layout pass has run. `LayoutDocument` (the PDF-rendering pivot pdf-codec's `readPdf`/`writePdf` operate on directly, independent of any `ContentDocument`) is pages of positioned `LayoutItem`s (`text`/`image`/`rect`/`line`/`ellipse`/`path`/`link`) in PDF user-space coordinates. `DocumentPackageSchema` wraps `content` (required) with `pages` (optional, derived: each rendered page's own size, indexed to match every node's own `frames[].pageIndex`) — a single fused tree rather than a second, independent `LayoutDocument` correlated back to `content` only by matching `sourcePath` strings; the schema does not keep `content`'s populated `frames` fields and `pages` in sync or detect staleness.
51
+ `ContentDocument` (the semantic pivot) is a discriminated union of five kinds: `wordprocessing` (docx/odt sections of paragraphs/runs/tables/images), `presentation` (pptx/odp slides of shapes), `spreadsheet` (xlsx/ods sheets of cells, columns, rows, print settings), `drawing` (odg pages of shapes plus vector primitives — rect/ellipse/line/path), and `formula` (an equation carrying its own MathML node tree plus StarMath source when the producing format had one, extended with the two-layer math model: an optional verbatim-LaTeX `presentation` authoritative for rendering, an optional semantic `content: MathExpression` tree authoritative for computation, and provenance — neither layer stored derived from the other, so editing one never silently mutates the other). `ContentEmbeddedObjectSchema` lets any of the five embed another whole `ContentDocument`. Every paragraph/run/image/table/shape/vector/spreadsheet-cell leaf also carries its own canonical `headingLevel`-or-position fields directly: a `ContentParagraph`'s optional `headingLevel` (1 = the outermost heading, independent of the round-trip-only `styleId`), and every such leaf's optional `frames: LayoutFrame[]` — that node's own rendered page position(s) (`pageIndex` plus PDF user-space `xPt`/`yPt`/`widthPt`/`heightPt`), fused directly onto the content tree once a layout pass has run. `LayoutDocument` (the PDF-rendering pivot pdf-codec's `readPdf`/`writePdf` operate on directly, independent of any `ContentDocument`) is pages of positioned `LayoutItem`s (`text`/`image`/`rect`/`line`/`ellipse`/`path`/`link`) in PDF user-space coordinates. `DocumentPackageSchema` wraps `content` (required) with `pages` (optional, derived: each rendered page's own size, indexed to match every node's own `frames[].pageIndex`) — a single fused tree rather than a second, independent `LayoutDocument` correlated back to `content` only by matching `sourcePath` strings; the schema does not keep `content`'s populated `frames` fields and `pages` in sync or detect staleness. Every one of the five kinds also accepts an optional document-level `symbolTable` — the math curation layer mapping each written symbol glyph (within a scope) to its id, quantity kind, preferred unit, and definition source, alongside the unit registry (SI dimension-exponent vectors, exact rational conversions, per-unit-system normalisation contexts) that the `qty` nodes of lowered formulas resolve against.
52
52
 
53
53
  The package contains only [Zod](https://zod.dev) schemas, their inferred types, trivial schema-attached helpers (hex-colour conversion, recursive structural type guards), and two small structural interfaces (`ContentCodec`/`LayoutCodec`, see [Codecs](#codecs)). No XML, ZIP, PDF, or binary handling; the sole dependency is `zod`.
54
54
 
@@ -114,11 +114,11 @@ node_modules/document-schema.js/schemas/content-document.schema.json
114
114
  node_modules/document-schema.js/schemas/layout-document.schema.json
115
115
  ```
116
116
 
117
- Each file's `$id` is a jsdelivr URL pinned to the exact npm version — immutable and live on publish. The three files cross-reference via `$ref`s, so a validator resolving refs over HTTP can validate a whole `DocumentPackage`. `content-document.schema.json` carries a hand-authored `$defs` block for the recursive paragraph/table/embedded-object and MathML node models (Zod's converter cannot express these directly); `content-json-schema-defs.ts` holds those fragments, and a regression test compares each against a live `z.toJSONSchema()` of its real Zod counterpart so a field changed without updating its fragment fails a test. Fragments downstream of a `z.custom()` node (`ContentBlock`, `ContentTable`/`Cell`/`Row`, `ContentEmbeddedObjectBlock`, `MathMlNode`/`Element`/`Attribute`) still need hand re-verification against `src/content.ts`/`src/mathml.ts` — see below.
117
+ Each file's `$id` is a jsdelivr URL pinned to the exact npm version — immutable and live on publish. The three files cross-reference via `$ref`s, so a validator resolving refs over HTTP can validate a whole `DocumentPackage`. `content-document.schema.json` carries a hand-authored `$defs` block for the recursive paragraph/table/embedded-object and MathML node models (Zod's converter cannot express these directly); `content-json-schema-defs.ts` holds those fragments, and a regression test compares each against a live `z.toJSONSchema()` of its real Zod counterpart so a field changed without updating its fragment fails a test. Fragments downstream of a `z.custom()` node (`ContentBlock`, `ContentTable`/`Cell`/`Row`, `ContentEmbeddedObjectBlock`, `MathMlNode`/`Element`/`Attribute`, `ContentFormula`, `MathExpression` and its recursive variants) still need hand re-verification against `src/content.ts`/`src/mathml.ts`/`src/math.ts` — see below.
118
118
 
119
119
  ### `z.custom()` vs `z.lazy()` for recursive schemas
120
120
 
121
- `ContentBlockSchema`, `ContentEmbeddedObjectSchema`, and `MathMlNodeSchema` are `z.custom()` type-guard predicates rather than real Zod schemas, because `z.lazy()` was believed to collapse to `unknown` for recursive children. A throwaway spike (reverted) re-tested `MathMlNodeSchema` (the simplest case) against `zod@4.4.3`.
121
+ `ContentBlockSchema`, `ContentEmbeddedObjectSchema`, `MathMlNodeSchema`, and `MathExpressionSchema` are `z.custom()` type-guard predicates rather than real Zod schemas, because `z.lazy()` was believed to collapse to `unknown` for recursive children. A throwaway spike (reverted) re-tested `MathMlNodeSchema` (the simplest case) against `zod@4.4.3`.
122
122
 
123
123
  **Finding: `z.lazy()` works now, with one constructional gotcha.** The naive rewrite —
124
124
 
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_math = require("./math.cjs");
2
3
  const require_schema_io = require("./schema-io.cjs");
3
4
  //#region src/content-json-schema-defs.ts
4
5
  const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
@@ -10,6 +11,29 @@ const EMBEDDED_OBJECT_KINDS = [
10
11
  "drawing"
11
12
  ];
12
13
  const CONTENT_DOCUMENT_URI = require_schema_io.schemaUriFor("ContentDocument");
14
+ function mathBinderDef(kind) {
15
+ return {
16
+ type: "object",
17
+ properties: {
18
+ kind: {
19
+ type: "string",
20
+ const: kind
21
+ },
22
+ binder: { type: "string" },
23
+ lower: { $ref: "#/$defs/MathExpression" },
24
+ upper: { $ref: "#/$defs/MathExpression" },
25
+ body: { $ref: "#/$defs/MathExpression" }
26
+ },
27
+ required: [
28
+ "kind",
29
+ "binder",
30
+ "lower",
31
+ "upper",
32
+ "body"
33
+ ],
34
+ additionalProperties: false
35
+ };
36
+ }
13
37
  const CONTENT_DEFS = {
14
38
  Color: {
15
39
  type: "object",
@@ -477,6 +501,270 @@ const CONTENT_DEFS = {
477
501
  additionalProperties: false
478
502
  },
479
503
  { $ref: "#/$defs/MathMlElement" }
504
+ ] },
505
+ ContentFormula: {
506
+ type: "object",
507
+ properties: {
508
+ mathml: {
509
+ type: "array",
510
+ items: { $ref: "#/$defs/MathMlNode" }
511
+ },
512
+ starMath: { type: "string" },
513
+ presentation: { $ref: "#/$defs/MathPresentation" },
514
+ content: { $ref: "#/$defs/MathExpression" },
515
+ provenance: { $ref: "#/$defs/MathProvenance" }
516
+ },
517
+ required: ["mathml"],
518
+ additionalProperties: false
519
+ },
520
+ ExactRational: {
521
+ type: "object",
522
+ properties: {
523
+ numerator: {
524
+ type: "string",
525
+ pattern: "^(0|-?[1-9]\\d*)$"
526
+ },
527
+ denominator: {
528
+ type: "string",
529
+ pattern: "^[1-9]\\d*$"
530
+ }
531
+ },
532
+ required: ["numerator", "denominator"],
533
+ additionalProperties: false
534
+ },
535
+ DimensionVector: {
536
+ type: "object",
537
+ propertyNames: {
538
+ type: "string",
539
+ enum: [...require_math.SI_BASE_DIMENSIONS]
540
+ },
541
+ additionalProperties: {
542
+ type: "integer",
543
+ minimum: -MAX_SAFE_INTEGER,
544
+ maximum: MAX_SAFE_INTEGER
545
+ }
546
+ },
547
+ MathPresentation: {
548
+ type: "object",
549
+ properties: { latex: { type: "string" } },
550
+ required: ["latex"],
551
+ additionalProperties: false
552
+ },
553
+ MathProvenance: {
554
+ type: "object",
555
+ properties: {
556
+ source: { type: "string" },
557
+ pageRef: { type: "string" },
558
+ editTrail: {
559
+ type: "array",
560
+ items: { type: "string" }
561
+ }
562
+ },
563
+ required: ["source", "editTrail"],
564
+ additionalProperties: false
565
+ },
566
+ MathUncertainty: {
567
+ type: "object",
568
+ properties: {
569
+ magnitude: { $ref: "#/$defs/ExactRational" },
570
+ unit: { type: "string" },
571
+ coverageFactor: {
572
+ type: "number",
573
+ exclusiveMinimum: 0
574
+ }
575
+ },
576
+ required: ["magnitude"],
577
+ additionalProperties: false
578
+ },
579
+ MathSymbolEntry: {
580
+ type: "object",
581
+ properties: {
582
+ glyph: { type: "string" },
583
+ scope: { type: "string" },
584
+ id: { type: "string" },
585
+ quantityKind: { type: "string" },
586
+ preferredUnit: { type: "string" },
587
+ definitionSource: { type: "string" }
588
+ },
589
+ required: [
590
+ "glyph",
591
+ "scope",
592
+ "id"
593
+ ],
594
+ additionalProperties: false
595
+ },
596
+ MathUnit: {
597
+ type: "object",
598
+ properties: {
599
+ id: { type: "string" },
600
+ symbol: { type: "string" },
601
+ name: { type: "string" },
602
+ dimension: { $ref: "#/$defs/DimensionVector" },
603
+ factorToSi: { $ref: "#/$defs/ExactRational" },
604
+ offsetToSi: { $ref: "#/$defs/ExactRational" },
605
+ context: { type: "string" }
606
+ },
607
+ required: [
608
+ "id",
609
+ "symbol",
610
+ "dimension",
611
+ "factorToSi"
612
+ ],
613
+ additionalProperties: false
614
+ },
615
+ MathNormalisationContext: {
616
+ type: "object",
617
+ properties: {
618
+ id: { type: "string" },
619
+ bases: {
620
+ type: "array",
621
+ items: {
622
+ type: "object",
623
+ properties: {
624
+ unit: { type: "string" },
625
+ value: { $ref: "#/$defs/ExactRational" }
626
+ },
627
+ required: ["unit", "value"],
628
+ additionalProperties: false
629
+ }
630
+ }
631
+ },
632
+ required: ["id", "bases"],
633
+ additionalProperties: false
634
+ },
635
+ SymbolTable: {
636
+ type: "object",
637
+ properties: {
638
+ symbols: {
639
+ type: "array",
640
+ items: { $ref: "#/$defs/MathSymbolEntry" }
641
+ },
642
+ units: {
643
+ type: "array",
644
+ items: { $ref: "#/$defs/MathUnit" }
645
+ },
646
+ contexts: {
647
+ type: "array",
648
+ items: { $ref: "#/$defs/MathNormalisationContext" }
649
+ }
650
+ },
651
+ required: ["symbols", "units"],
652
+ additionalProperties: false
653
+ },
654
+ MathNum: {
655
+ type: "object",
656
+ properties: {
657
+ kind: {
658
+ type: "string",
659
+ const: "num"
660
+ },
661
+ numerator: {
662
+ type: "string",
663
+ pattern: "^(0|-?[1-9]\\d*)$"
664
+ },
665
+ denominator: {
666
+ type: "string",
667
+ pattern: "^[1-9]\\d*$"
668
+ }
669
+ },
670
+ required: [
671
+ "kind",
672
+ "numerator",
673
+ "denominator"
674
+ ],
675
+ additionalProperties: false
676
+ },
677
+ MathQty: {
678
+ type: "object",
679
+ properties: {
680
+ kind: {
681
+ type: "string",
682
+ const: "qty"
683
+ },
684
+ value: { $ref: "#/$defs/ExactRational" },
685
+ unit: { type: "string" },
686
+ uncertainty: { $ref: "#/$defs/MathUncertainty" }
687
+ },
688
+ required: [
689
+ "kind",
690
+ "value",
691
+ "unit"
692
+ ],
693
+ additionalProperties: false
694
+ },
695
+ MathSym: {
696
+ type: "object",
697
+ properties: {
698
+ kind: {
699
+ type: "string",
700
+ const: "sym"
701
+ },
702
+ id: { type: "string" }
703
+ },
704
+ required: ["kind", "id"],
705
+ additionalProperties: false
706
+ },
707
+ MathApp: {
708
+ type: "object",
709
+ properties: {
710
+ kind: {
711
+ type: "string",
712
+ const: "app"
713
+ },
714
+ operator: { type: "string" },
715
+ args: {
716
+ type: "array",
717
+ items: { $ref: "#/$defs/MathExpression" }
718
+ }
719
+ },
720
+ required: [
721
+ "kind",
722
+ "operator",
723
+ "args"
724
+ ],
725
+ additionalProperties: false
726
+ },
727
+ MathSum: mathBinderDef("sum"),
728
+ MathProd: mathBinderDef("prod"),
729
+ MathMatrix: {
730
+ type: "object",
731
+ properties: {
732
+ kind: {
733
+ type: "string",
734
+ const: "matrix"
735
+ },
736
+ rows: {
737
+ type: "array",
738
+ items: {
739
+ type: "array",
740
+ items: { $ref: "#/$defs/MathExpression" }
741
+ }
742
+ }
743
+ },
744
+ required: ["kind", "rows"],
745
+ additionalProperties: false
746
+ },
747
+ MathUnparsed: {
748
+ type: "object",
749
+ properties: {
750
+ kind: {
751
+ type: "string",
752
+ const: "unparsed"
753
+ },
754
+ latex: { type: "string" }
755
+ },
756
+ required: ["kind", "latex"],
757
+ additionalProperties: false
758
+ },
759
+ MathExpression: { oneOf: [
760
+ { $ref: "#/$defs/MathNum" },
761
+ { $ref: "#/$defs/MathQty" },
762
+ { $ref: "#/$defs/MathSym" },
763
+ { $ref: "#/$defs/MathApp" },
764
+ { $ref: "#/$defs/MathSum" },
765
+ { $ref: "#/$defs/MathProd" },
766
+ { $ref: "#/$defs/MathMatrix" },
767
+ { $ref: "#/$defs/MathUnparsed" }
480
768
  ] }
481
769
  };
482
770
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { SI_BASE_DIMENSIONS } from "./math.js";
1
2
  import { schemaUriFor } from "./schema-io.js";
2
3
  //#region src/content-json-schema-defs.ts
3
4
  const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
@@ -9,6 +10,29 @@ const EMBEDDED_OBJECT_KINDS = [
9
10
  "drawing"
10
11
  ];
11
12
  const CONTENT_DOCUMENT_URI = schemaUriFor("ContentDocument");
13
+ function mathBinderDef(kind) {
14
+ return {
15
+ type: "object",
16
+ properties: {
17
+ kind: {
18
+ type: "string",
19
+ const: kind
20
+ },
21
+ binder: { type: "string" },
22
+ lower: { $ref: "#/$defs/MathExpression" },
23
+ upper: { $ref: "#/$defs/MathExpression" },
24
+ body: { $ref: "#/$defs/MathExpression" }
25
+ },
26
+ required: [
27
+ "kind",
28
+ "binder",
29
+ "lower",
30
+ "upper",
31
+ "body"
32
+ ],
33
+ additionalProperties: false
34
+ };
35
+ }
12
36
  const CONTENT_DEFS = {
13
37
  Color: {
14
38
  type: "object",
@@ -476,6 +500,270 @@ const CONTENT_DEFS = {
476
500
  additionalProperties: false
477
501
  },
478
502
  { $ref: "#/$defs/MathMlElement" }
503
+ ] },
504
+ ContentFormula: {
505
+ type: "object",
506
+ properties: {
507
+ mathml: {
508
+ type: "array",
509
+ items: { $ref: "#/$defs/MathMlNode" }
510
+ },
511
+ starMath: { type: "string" },
512
+ presentation: { $ref: "#/$defs/MathPresentation" },
513
+ content: { $ref: "#/$defs/MathExpression" },
514
+ provenance: { $ref: "#/$defs/MathProvenance" }
515
+ },
516
+ required: ["mathml"],
517
+ additionalProperties: false
518
+ },
519
+ ExactRational: {
520
+ type: "object",
521
+ properties: {
522
+ numerator: {
523
+ type: "string",
524
+ pattern: "^(0|-?[1-9]\\d*)$"
525
+ },
526
+ denominator: {
527
+ type: "string",
528
+ pattern: "^[1-9]\\d*$"
529
+ }
530
+ },
531
+ required: ["numerator", "denominator"],
532
+ additionalProperties: false
533
+ },
534
+ DimensionVector: {
535
+ type: "object",
536
+ propertyNames: {
537
+ type: "string",
538
+ enum: [...SI_BASE_DIMENSIONS]
539
+ },
540
+ additionalProperties: {
541
+ type: "integer",
542
+ minimum: -MAX_SAFE_INTEGER,
543
+ maximum: MAX_SAFE_INTEGER
544
+ }
545
+ },
546
+ MathPresentation: {
547
+ type: "object",
548
+ properties: { latex: { type: "string" } },
549
+ required: ["latex"],
550
+ additionalProperties: false
551
+ },
552
+ MathProvenance: {
553
+ type: "object",
554
+ properties: {
555
+ source: { type: "string" },
556
+ pageRef: { type: "string" },
557
+ editTrail: {
558
+ type: "array",
559
+ items: { type: "string" }
560
+ }
561
+ },
562
+ required: ["source", "editTrail"],
563
+ additionalProperties: false
564
+ },
565
+ MathUncertainty: {
566
+ type: "object",
567
+ properties: {
568
+ magnitude: { $ref: "#/$defs/ExactRational" },
569
+ unit: { type: "string" },
570
+ coverageFactor: {
571
+ type: "number",
572
+ exclusiveMinimum: 0
573
+ }
574
+ },
575
+ required: ["magnitude"],
576
+ additionalProperties: false
577
+ },
578
+ MathSymbolEntry: {
579
+ type: "object",
580
+ properties: {
581
+ glyph: { type: "string" },
582
+ scope: { type: "string" },
583
+ id: { type: "string" },
584
+ quantityKind: { type: "string" },
585
+ preferredUnit: { type: "string" },
586
+ definitionSource: { type: "string" }
587
+ },
588
+ required: [
589
+ "glyph",
590
+ "scope",
591
+ "id"
592
+ ],
593
+ additionalProperties: false
594
+ },
595
+ MathUnit: {
596
+ type: "object",
597
+ properties: {
598
+ id: { type: "string" },
599
+ symbol: { type: "string" },
600
+ name: { type: "string" },
601
+ dimension: { $ref: "#/$defs/DimensionVector" },
602
+ factorToSi: { $ref: "#/$defs/ExactRational" },
603
+ offsetToSi: { $ref: "#/$defs/ExactRational" },
604
+ context: { type: "string" }
605
+ },
606
+ required: [
607
+ "id",
608
+ "symbol",
609
+ "dimension",
610
+ "factorToSi"
611
+ ],
612
+ additionalProperties: false
613
+ },
614
+ MathNormalisationContext: {
615
+ type: "object",
616
+ properties: {
617
+ id: { type: "string" },
618
+ bases: {
619
+ type: "array",
620
+ items: {
621
+ type: "object",
622
+ properties: {
623
+ unit: { type: "string" },
624
+ value: { $ref: "#/$defs/ExactRational" }
625
+ },
626
+ required: ["unit", "value"],
627
+ additionalProperties: false
628
+ }
629
+ }
630
+ },
631
+ required: ["id", "bases"],
632
+ additionalProperties: false
633
+ },
634
+ SymbolTable: {
635
+ type: "object",
636
+ properties: {
637
+ symbols: {
638
+ type: "array",
639
+ items: { $ref: "#/$defs/MathSymbolEntry" }
640
+ },
641
+ units: {
642
+ type: "array",
643
+ items: { $ref: "#/$defs/MathUnit" }
644
+ },
645
+ contexts: {
646
+ type: "array",
647
+ items: { $ref: "#/$defs/MathNormalisationContext" }
648
+ }
649
+ },
650
+ required: ["symbols", "units"],
651
+ additionalProperties: false
652
+ },
653
+ MathNum: {
654
+ type: "object",
655
+ properties: {
656
+ kind: {
657
+ type: "string",
658
+ const: "num"
659
+ },
660
+ numerator: {
661
+ type: "string",
662
+ pattern: "^(0|-?[1-9]\\d*)$"
663
+ },
664
+ denominator: {
665
+ type: "string",
666
+ pattern: "^[1-9]\\d*$"
667
+ }
668
+ },
669
+ required: [
670
+ "kind",
671
+ "numerator",
672
+ "denominator"
673
+ ],
674
+ additionalProperties: false
675
+ },
676
+ MathQty: {
677
+ type: "object",
678
+ properties: {
679
+ kind: {
680
+ type: "string",
681
+ const: "qty"
682
+ },
683
+ value: { $ref: "#/$defs/ExactRational" },
684
+ unit: { type: "string" },
685
+ uncertainty: { $ref: "#/$defs/MathUncertainty" }
686
+ },
687
+ required: [
688
+ "kind",
689
+ "value",
690
+ "unit"
691
+ ],
692
+ additionalProperties: false
693
+ },
694
+ MathSym: {
695
+ type: "object",
696
+ properties: {
697
+ kind: {
698
+ type: "string",
699
+ const: "sym"
700
+ },
701
+ id: { type: "string" }
702
+ },
703
+ required: ["kind", "id"],
704
+ additionalProperties: false
705
+ },
706
+ MathApp: {
707
+ type: "object",
708
+ properties: {
709
+ kind: {
710
+ type: "string",
711
+ const: "app"
712
+ },
713
+ operator: { type: "string" },
714
+ args: {
715
+ type: "array",
716
+ items: { $ref: "#/$defs/MathExpression" }
717
+ }
718
+ },
719
+ required: [
720
+ "kind",
721
+ "operator",
722
+ "args"
723
+ ],
724
+ additionalProperties: false
725
+ },
726
+ MathSum: mathBinderDef("sum"),
727
+ MathProd: mathBinderDef("prod"),
728
+ MathMatrix: {
729
+ type: "object",
730
+ properties: {
731
+ kind: {
732
+ type: "string",
733
+ const: "matrix"
734
+ },
735
+ rows: {
736
+ type: "array",
737
+ items: {
738
+ type: "array",
739
+ items: { $ref: "#/$defs/MathExpression" }
740
+ }
741
+ }
742
+ },
743
+ required: ["kind", "rows"],
744
+ additionalProperties: false
745
+ },
746
+ MathUnparsed: {
747
+ type: "object",
748
+ properties: {
749
+ kind: {
750
+ type: "string",
751
+ const: "unparsed"
752
+ },
753
+ latex: { type: "string" }
754
+ },
755
+ required: ["kind", "latex"],
756
+ additionalProperties: false
757
+ },
758
+ MathExpression: { oneOf: [
759
+ { $ref: "#/$defs/MathNum" },
760
+ { $ref: "#/$defs/MathQty" },
761
+ { $ref: "#/$defs/MathSym" },
762
+ { $ref: "#/$defs/MathApp" },
763
+ { $ref: "#/$defs/MathSum" },
764
+ { $ref: "#/$defs/MathProd" },
765
+ { $ref: "#/$defs/MathMatrix" },
766
+ { $ref: "#/$defs/MathUnparsed" }
479
767
  ] }
480
768
  };
481
769
  //#endregion