@beyondwork/docx-react-component 1.0.101 → 1.0.103

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 (41) hide show
  1. package/package.json +1 -1
  2. package/src/core/commands/formatting-commands.ts +8 -7
  3. package/src/core/commands/paragraph-layout-commands.ts +11 -10
  4. package/src/core/commands/section-layout-commands.ts +7 -6
  5. package/src/core/commands/style-commands.ts +3 -2
  6. package/src/io/export/build-app-properties-xml.ts +24 -0
  7. package/src/io/normalize/normalize-text.ts +6 -5
  8. package/src/io/ooxml/docprops.ts +298 -0
  9. package/src/io/ooxml/parse-anchor.ts +15 -15
  10. package/src/io/ooxml/parse-drawing.ts +5 -5
  11. package/src/io/ooxml/parse-fields.ts +16 -15
  12. package/src/io/ooxml/parse-font-table.ts +2 -1
  13. package/src/io/ooxml/parse-footnotes.ts +3 -2
  14. package/src/io/ooxml/parse-headers-footers.ts +7 -6
  15. package/src/io/ooxml/parse-main-document.ts +41 -40
  16. package/src/io/ooxml/parse-numbering.ts +3 -2
  17. package/src/io/ooxml/parse-object.ts +6 -6
  18. package/src/io/ooxml/parse-paragraph-formatting.ts +12 -11
  19. package/src/io/ooxml/parse-picture.ts +16 -16
  20. package/src/io/ooxml/parse-run-formatting.ts +11 -10
  21. package/src/io/ooxml/parse-settings.ts +2 -1
  22. package/src/io/ooxml/parse-shapes.ts +18 -17
  23. package/src/io/ooxml/parse-styles.ts +16 -16
  24. package/src/io/ooxml/parse-theme.ts +5 -4
  25. package/src/model/canonical-document.ts +920 -815
  26. package/src/runtime/formatting/document-lookup.ts +3 -2
  27. package/src/runtime/formatting/formatting-context.ts +66 -25
  28. package/src/runtime/formatting/index.ts +18 -0
  29. package/src/runtime/formatting/layout-inputs.ts +256 -0
  30. package/src/runtime/formatting/numbering/geometry.ts +13 -12
  31. package/src/runtime/formatting/style-cascade.ts +2 -1
  32. package/src/runtime/formatting/table-style-resolver.ts +8 -7
  33. package/src/runtime/surface-projection.ts +31 -36
  34. package/src/session/export/stateful-export-pipeline.ts +9 -4
  35. package/src/session/export/stateful-export.ts +22 -6
  36. package/src/session/import/canonical-assembly.ts +2 -3
  37. package/src/session/import/loader-types.ts +3 -1
  38. package/src/session/import/loader.ts +12 -0
  39. package/src/session/import/normalize.ts +2 -1
  40. package/src/session/import/source-package-evidence.ts +1016 -0
  41. package/src/session/shared/session-utils.ts +9 -0
@@ -1,4 +1,4 @@
1
- import type { AnchorGeometry } from "../../model/canonical-document.ts";
1
+ import type { AnchorGeometry, Mutable } from "../../model/canonical-document.ts";
2
2
  import {
3
3
  type XmlElementNode,
4
4
  findFirstChild,
@@ -46,11 +46,11 @@ export function parseAnchorGeometry(container: XmlElementNode): AnchorGeometry {
46
46
  const dp: NonNullable<AnchorGeometry["docPr"]> = {
47
47
  id: docPrEl.attributes.id ?? "",
48
48
  };
49
- if (docPrEl.attributes.name) dp.name = docPrEl.attributes.name;
50
- if (docPrEl.attributes.descr) dp.descr = docPrEl.attributes.descr;
49
+ if (docPrEl.attributes.name) (dp as Mutable<typeof dp>).name = docPrEl.attributes.name;
50
+ if (docPrEl.attributes.descr) (dp as Mutable<typeof dp>).descr = docPrEl.attributes.descr;
51
51
  // Phase 4.6 G8 — wp:docPr hidden flag
52
52
  const hidden = readBoolAttr(docPrEl, "hidden");
53
- if (hidden !== undefined) dp.hidden = hidden;
53
+ if (hidden !== undefined) (dp as Mutable<typeof dp>).hidden = hidden;
54
54
  return dp;
55
55
  })()
56
56
  : undefined;
@@ -62,21 +62,21 @@ export function parseAnchorGeometry(container: XmlElementNode): AnchorGeometry {
62
62
  // Phase 4.2 G1 — wrapPolygon coords for wrapTight / wrapThrough.
63
63
  const wrapPolygon = readWrapPolygon(container);
64
64
 
65
- const geometry: AnchorGeometry = {
65
+ const geometry: Mutable<AnchorGeometry> = {
66
66
  display,
67
67
  extent,
68
68
  wrapMode,
69
69
  };
70
70
 
71
- if (wrapPolygon) geometry.wrapPolygon = wrapPolygon;
72
- if (positionHEl) geometry.positionH = readAxisPosition(positionHEl);
73
- if (positionVEl) geometry.positionV = readAxisPosition(positionVEl);
74
- if (distMargins) geometry.distMargins = distMargins;
75
- if (relativeHeight !== undefined) geometry.relativeHeight = relativeHeight;
76
- if (behindDoc !== undefined) geometry.behindDoc = behindDoc;
77
- if (layoutInCell !== undefined) geometry.layoutInCell = layoutInCell;
78
- if (allowOverlap !== undefined) geometry.allowOverlap = allowOverlap;
79
- if (simplePos !== undefined) geometry.simplePos = simplePos;
71
+ if (wrapPolygon) (geometry as Mutable<typeof geometry>).wrapPolygon = wrapPolygon;
72
+ if (positionHEl) (geometry as Mutable<typeof geometry>).positionH = readAxisPosition(positionHEl);
73
+ if (positionVEl) (geometry as Mutable<typeof geometry>).positionV = readAxisPosition(positionVEl);
74
+ if (distMargins) (geometry as Mutable<typeof geometry>).distMargins = distMargins;
75
+ if (relativeHeight !== undefined) (geometry as Mutable<typeof geometry>).relativeHeight = relativeHeight;
76
+ if (behindDoc !== undefined) (geometry as Mutable<typeof geometry>).behindDoc = behindDoc;
77
+ if (layoutInCell !== undefined) (geometry as Mutable<typeof geometry>).layoutInCell = layoutInCell;
78
+ if (allowOverlap !== undefined) (geometry as Mutable<typeof geometry>).allowOverlap = allowOverlap;
79
+ if (simplePos !== undefined) (geometry as Mutable<typeof geometry>).simplePos = simplePos;
80
80
  if (docPr) geometry.docPr = docPr;
81
81
  if (frameLocks) geometry.frameLocks = frameLocks;
82
82
 
@@ -136,7 +136,7 @@ function readFrameLocks(
136
136
  const keys = ["noChangeAspect", "noResize", "noMove", "noRot", "noSelect", "noGrp"] as const;
137
137
  for (const key of keys) {
138
138
  const v = readBoolAttr(locks, key);
139
- if (v !== undefined) result[key] = v;
139
+ if (v !== undefined) (result as Mutable<typeof result>)[key] = v;
140
140
  }
141
141
  return Object.keys(result).length > 0 ? result : undefined;
142
142
  }
@@ -2,7 +2,7 @@ import type { OpcRelationship } from "./part-manifest.ts";
2
2
  import { normalizePartPath, resolveRelationshipTarget } from "./part-manifest.ts";
3
3
  import type { InlineMediaPart } from "./parse-inline-media.ts";
4
4
  import type { ChartPartLookup } from "./parse-complex-content.ts";
5
- import type { DrawingFrameNode, AnchorGeometry } from "../../model/canonical-document.ts";
5
+ import type { AnchorGeometry, DrawingFrameNode, Mutable } from "../../model/canonical-document.ts";
6
6
  import { parseAnchorGeometry } from "./parse-anchor.ts";
7
7
  import { parsePicture } from "./parse-picture.ts";
8
8
  import { parseShapeContent, type TxbxBlockParser } from "./parse-shapes.ts";
@@ -190,14 +190,14 @@ function resolveContent(
190
190
  resolveRelationshipTarget(opts.sourcePartPath ?? "/word/document.xml", rel),
191
191
  );
192
192
  const mediaPart = opts.mediaParts?.get(partPath);
193
- pic.packagePartName = partPath;
194
- pic.mediaId = `media:${partPath.slice(1)}`;
193
+ (pic as Mutable<typeof pic>).packagePartName = partPath;
194
+ (pic as Mutable<typeof pic>).mediaId = `media:${partPath.slice(1)}`;
195
195
  if (mediaPart?.contentType) {
196
- pic.contentType = mediaPart.contentType;
196
+ (pic as Mutable<typeof pic>).contentType = mediaPart.contentType;
197
197
  }
198
198
  }
199
199
  // F4.1 — preserve outer drawing XML for lossless round-trip serialization
200
- pic.rawXml = rawXml;
200
+ (pic as Mutable<typeof pic>).rawXml = rawXml;
201
201
  return pic;
202
202
  }
203
203
  }
@@ -328,6 +328,7 @@ import type {
328
328
  TocInstructionModel,
329
329
  TocRegion,
330
330
  TocStructure,
331
+ Mutable,
331
332
  } from "../../model/canonical-document.ts";
332
333
  import { parseFieldSwitches } from "./parse-field-switches.ts";
333
334
 
@@ -379,14 +380,14 @@ export function classifyFieldInstruction(instruction: string): {
379
380
  let switches: FieldNode["switches"] | undefined;
380
381
  if (family === "REF" || family === "PAGEREF" || family === "NOTEREF" || family === "TOC") {
381
382
  const raw = parseFieldSwitches(trimmed);
382
- const sw: FieldNode["switches"] = {};
383
- if (raw.hyperlink) sw.hyperlink = true;
384
- if (raw.relativePosition) sw.relativePosition = true;
385
- if (raw.numericRef) sw.numericRef = true;
386
- if (raw.recursive) sw.recursive = true;
387
- if (raw.suppressNonDelimiter) sw.suppressNonDelimiter = true;
388
- if (raw.includeNumbering) sw.includeNumbering = true;
389
- if (raw.includeLevel) sw.includeLevel = true;
383
+ const sw: Mutable<NonNullable<FieldNode["switches"]>> = {};
384
+ if (raw.hyperlink) (sw as Mutable<typeof sw>).hyperlink = true;
385
+ if (raw.relativePosition) (sw as Mutable<typeof sw>).relativePosition = true;
386
+ if (raw.numericRef) (sw as Mutable<typeof sw>).numericRef = true;
387
+ if (raw.recursive) (sw as Mutable<typeof sw>).recursive = true;
388
+ if (raw.suppressNonDelimiter) (sw as Mutable<typeof sw>).suppressNonDelimiter = true;
389
+ if (raw.includeNumbering) (sw as Mutable<typeof sw>).includeNumbering = true;
390
+ if (raw.includeLevel) (sw as Mutable<typeof sw>).includeLevel = true;
390
391
  if (Object.keys(sw).length > 0) {
391
392
  switches = sw;
392
393
  }
@@ -430,7 +431,7 @@ export function buildFieldRegistry(
430
431
  ? { family: node.fieldFamily, supported: isSupportedFieldFamily(node.fieldFamily), target: node.fieldTarget, switches: node.switches }
431
432
  : classifyFieldInstruction(node.instruction);
432
433
  const displayText = flattenFieldText(node.children);
433
- const entry: FieldRegistryEntry = {
434
+ const entry: Mutable<FieldRegistryEntry> = {
434
435
  fieldIndex,
435
436
  fieldFamily: classification.family,
436
437
  supported: classification.supported,
@@ -460,7 +461,7 @@ export function buildFieldRegistry(
460
461
  ? { family: node.fieldFamily, supported: isSupportedFieldFamily(node.fieldFamily), target: node.fieldTarget, switches: node.switches }
461
462
  : classifyFieldInstruction(node.instruction);
462
463
  const displayText = flattenFieldText(node.children);
463
- const entry: FieldRegistryEntry = {
464
+ const entry: Mutable<FieldRegistryEntry> = {
464
465
  fieldIndex,
465
466
  fieldFamily: classification.family,
466
467
  supported: classification.supported,
@@ -512,7 +513,7 @@ export function parseTocLevelRange(instruction: string): { from: number; to: num
512
513
  }
513
514
 
514
515
  export function parseTocInstruction(instruction: string): TocInstructionModel {
515
- const model: TocInstructionModel = {
516
+ const model: Mutable<TocInstructionModel> = {
516
517
  raw: instruction,
517
518
  outlineRange: { from: 1, to: 9 },
518
519
  };
@@ -867,7 +868,7 @@ function tocLevelFromStyle(styleId: string | undefined): number {
867
868
  }
868
869
 
869
870
  function extractCachedTocEntry(
870
- paragraph: ParagraphNode,
871
+ paragraph: Mutable<ParagraphNode>,
871
872
  paragraphIndexByNode: WeakMap<ParagraphNode, number>,
872
873
  ): TocCachedEntry | undefined {
873
874
  if (!isTocParagraphStyle(paragraph.styleId)) {
@@ -1004,7 +1005,7 @@ export function resolveRefFieldText(
1004
1005
  * applies these to the live document.
1005
1006
  */
1006
1007
  export function refreshFieldRegistry(
1007
- registry: FieldRegistry,
1008
+ registry: Mutable<FieldRegistry>,
1008
1009
  bookmarkNameMap: Map<string, { bookmarkId: string; paragraphIndex: number }>,
1009
1010
  ): FieldRegistry {
1010
1011
  const refreshed: FieldRegistryEntry[] = registry.supported.map((entry) => {
@@ -1060,7 +1061,7 @@ function walkFieldDocument(
1060
1061
  }
1061
1062
 
1062
1063
  function walkSubPartFields(
1063
- subParts: SubPartsCatalog,
1064
+ subParts: Mutable<SubPartsCatalog>,
1064
1065
  visit: (node: DocumentNode, paragraphIndex: number) => void,
1065
1066
  ): void {
1066
1067
  for (const header of subParts.headers) {
@@ -1112,7 +1113,7 @@ function flattenParagraphInlineText(children: InlineNode[]): string {
1112
1113
  }
1113
1114
 
1114
1115
  function flattenBookmarkContent(
1115
- paragraph: ParagraphNode,
1116
+ paragraph: Mutable<ParagraphNode>,
1116
1117
  bookmarkId: string,
1117
1118
  ): string {
1118
1119
  let inside = false;
@@ -13,6 +13,7 @@
13
13
  import type {
14
14
  CanonicalFontEntry,
15
15
  CanonicalFontTable,
16
+ Mutable,
16
17
  } from "../../model/canonical-document.ts";
17
18
  import type { XmlElementNode } from "./xml-element.ts";
18
19
  import { parseXml } from "./xml-parser.ts";
@@ -32,7 +33,7 @@ export function parseFontTable(xml: string): CanonicalFontTable {
32
33
  const name = child.attributes["w:name"] ?? child.attributes["name"];
33
34
  if (!name) continue;
34
35
 
35
- const entry: CanonicalFontEntry = { name };
36
+ const entry: Mutable<CanonicalFontEntry> = { name };
36
37
 
37
38
  for (const sub of child.children) {
38
39
  if (sub.type !== "element") continue;
@@ -11,6 +11,7 @@ import type {
11
11
  TableNode,
12
12
  TableRowNode,
13
13
  TextMark,
14
+ Mutable,
14
15
  } from "../../model/canonical-document.ts";
15
16
  import { classifyFieldInstruction } from "./parse-fields.ts";
16
17
  import { isSafeTableFieldInstruction } from "./table-opaque-preservation.ts";
@@ -644,7 +645,7 @@ function parseRunProperties(rElement: XmlElementNode): TextMark[] {
644
645
  function readParagraphSpacing(pPr: XmlElementNode): ParagraphSpacing | undefined {
645
646
  const spacingNode = findChildElementOptional(pPr, "spacing");
646
647
  if (!spacingNode) return undefined;
647
- const result: ParagraphSpacing = {};
648
+ const result: Mutable<ParagraphSpacing> = {};
648
649
  const before = readStringAttr(spacingNode, "w:before");
649
650
  if (before) result.before = Number.parseInt(before, 10);
650
651
  const after = readStringAttr(spacingNode, "w:after");
@@ -661,7 +662,7 @@ function readParagraphSpacing(pPr: XmlElementNode): ParagraphSpacing | undefined
661
662
  function readParagraphIndentation(pPr: XmlElementNode): ParagraphIndentation | undefined {
662
663
  const indNode = findChildElementOptional(pPr, "ind");
663
664
  if (!indNode) return undefined;
664
- const result: ParagraphIndentation = {};
665
+ const result: Mutable<ParagraphIndentation> = {};
665
666
  const left = readStringAttr(indNode, "w:left");
666
667
  if (left) result.left = Number.parseInt(left, 10);
667
668
  const right = readStringAttr(indNode, "w:right");
@@ -11,6 +11,7 @@ import type {
11
11
  TableNode,
12
12
  TableRowNode,
13
13
  TextMark,
14
+ Mutable,
14
15
  } from "../../model/canonical-document.ts";
15
16
  import type { LegacyFormFieldNode } from "../../model/canonical-document.ts";
16
17
  import { resolveHighlightColor } from "./highlight-colors.ts";
@@ -500,7 +501,7 @@ function parseRunElement(
500
501
  const noteId =
501
502
  readStringAttr(child, "w:id") ?? "";
502
503
  if (noteId) {
503
- const ref: FootnoteRefNode = {
504
+ const ref: Mutable<FootnoteRefNode> = {
504
505
  type: "footnote_ref",
505
506
  noteId,
506
507
  noteKind: "footnote",
@@ -511,7 +512,7 @@ function parseRunElement(
511
512
  const noteId =
512
513
  readStringAttr(child, "w:id") ?? "";
513
514
  if (noteId) {
514
- const ref: FootnoteRefNode = {
515
+ const ref: Mutable<FootnoteRefNode> = {
515
516
  type: "footnote_ref",
516
517
  noteId,
517
518
  noteKind: "endnote",
@@ -594,7 +595,7 @@ function parseRunChildNode(
594
595
  const noteId =
595
596
  readStringAttr(child, "w:id") ?? "";
596
597
  if (noteId) {
597
- const ref: FootnoteRefNode = {
598
+ const ref: Mutable<FootnoteRefNode> = {
598
599
  type: "footnote_ref",
599
600
  noteId,
600
601
  noteKind: "footnote",
@@ -607,7 +608,7 @@ function parseRunChildNode(
607
608
  const noteId =
608
609
  readStringAttr(child, "w:id") ?? "";
609
610
  if (noteId) {
610
- const ref: FootnoteRefNode = {
611
+ const ref: Mutable<FootnoteRefNode> = {
611
612
  type: "footnote_ref",
612
613
  noteId,
613
614
  noteKind: "endnote",
@@ -970,7 +971,7 @@ function parseRunProperties(rElement: XmlElementNode): TextMark[] {
970
971
  function readParagraphSpacing(pPr: XmlElementNode): ParagraphSpacing | undefined {
971
972
  const spacingNode = findChildElementOptional(pPr, "spacing");
972
973
  if (!spacingNode) return undefined;
973
- const result: ParagraphSpacing = {};
974
+ const result: Mutable<ParagraphSpacing> = {};
974
975
  const before = readStringAttr(spacingNode, "w:before");
975
976
  if (before) result.before = Number.parseInt(before, 10);
976
977
  const after = readStringAttr(spacingNode, "w:after");
@@ -987,7 +988,7 @@ function readParagraphSpacing(pPr: XmlElementNode): ParagraphSpacing | undefined
987
988
  function readParagraphIndentation(pPr: XmlElementNode): ParagraphIndentation | undefined {
988
989
  const indNode = findChildElementOptional(pPr, "ind");
989
990
  if (!indNode) return undefined;
990
- const result: ParagraphIndentation = {};
991
+ const result: Mutable<ParagraphIndentation> = {};
991
992
  const left = readStringAttr(indNode, "w:left");
992
993
  if (left) result.left = Number.parseInt(left, 10);
993
994
  const right = readStringAttr(indNode, "w:right");
@@ -26,6 +26,7 @@ import type {
26
26
  SectionPageBorders,
27
27
  DrawingFrameNode,
28
28
  UnknownPropertyChild,
29
+ Mutable,
29
30
  } from "../../model/canonical-document.ts";
30
31
  import type { OpcRelationship } from "./part-manifest.ts";
31
32
  import { SCOPE_MARKER_BOOKMARK_PREFIX } from "./parse-scope-markers.ts";
@@ -2288,7 +2289,7 @@ function readParagraphSpacing(node: XmlElementNode): ParagraphSpacing | undefine
2288
2289
  );
2289
2290
  if (!spacingNode) return undefined;
2290
2291
 
2291
- const spacing: ParagraphSpacing = {};
2292
+ const spacing: Mutable<ParagraphSpacing> = {};
2292
2293
  const before = spacingNode.attributes["w:before"] ?? spacingNode.attributes.before;
2293
2294
  const after = spacingNode.attributes["w:after"] ?? spacingNode.attributes.after;
2294
2295
  const line = spacingNode.attributes["w:line"] ?? spacingNode.attributes.line;
@@ -2332,7 +2333,7 @@ function readParagraphIndentation(node: XmlElementNode): ParagraphIndentation |
2332
2333
  );
2333
2334
  if (!indNode) return undefined;
2334
2335
 
2335
- const indentation: ParagraphIndentation = {};
2336
+ const indentation: Mutable<ParagraphIndentation> = {};
2336
2337
  const left = indNode.attributes["w:left"] ?? indNode.attributes.left;
2337
2338
  const right = indNode.attributes["w:right"] ?? indNode.attributes.right;
2338
2339
  const firstLine = indNode.attributes["w:firstLine"] ?? indNode.attributes.firstLine;
@@ -2450,7 +2451,7 @@ function readParagraphBorders(node: XmlElementNode): ParagraphBorders | undefine
2450
2451
  return undefined;
2451
2452
  }
2452
2453
 
2453
- const borders: ParagraphBorders = {};
2454
+ const borders: Mutable<ParagraphBorders> = {};
2454
2455
  for (const [name, key] of [
2455
2456
  ["top", "top"],
2456
2457
  ["left", "left"],
@@ -2481,7 +2482,7 @@ function readParagraphShading(node: XmlElementNode): ParagraphShading | undefine
2481
2482
  return undefined;
2482
2483
  }
2483
2484
 
2484
- const shading: ParagraphShading = {};
2485
+ const shading: Mutable<ParagraphShading> = {};
2485
2486
  const fill = shadingNode.attributes["w:fill"] ?? shadingNode.attributes.fill;
2486
2487
  const color = shadingNode.attributes["w:color"] ?? shadingNode.attributes.color;
2487
2488
  const val = shadingNode.attributes["w:val"] ?? shadingNode.attributes.val;
@@ -2491,14 +2492,14 @@ function readParagraphShading(node: XmlElementNode): ParagraphShading | undefine
2491
2492
  const themeColor = shadingNode.attributes["w:themeColor"] ?? shadingNode.attributes.themeColor;
2492
2493
  const themeColorTint = shadingNode.attributes["w:themeColorTint"] ?? shadingNode.attributes.themeColorTint;
2493
2494
  const themeColorShade = shadingNode.attributes["w:themeColorShade"] ?? shadingNode.attributes.themeColorShade;
2494
- if (fill) shading.fill = fill;
2495
- if (color) shading.color = color;
2496
- if (val) shading.val = val;
2497
- if (themeFill) shading.themeFill = themeFill;
2498
- if (themeFillTint) shading.themeFillTint = themeFillTint;
2499
- if (themeFillShade) shading.themeFillShade = themeFillShade;
2500
- if (themeColor) shading.themeColor = themeColor;
2501
- if (themeColorTint) shading.themeColorTint = themeColorTint;
2495
+ if (fill) (shading as Mutable<typeof shading>).fill = fill;
2496
+ if (color) (shading as Mutable<typeof shading>).color = color;
2497
+ if (val) (shading as Mutable<typeof shading>).val = val;
2498
+ if (themeFill) (shading as Mutable<typeof shading>).themeFill = themeFill;
2499
+ if (themeFillTint) (shading as Mutable<typeof shading>).themeFillTint = themeFillTint;
2500
+ if (themeFillShade) (shading as Mutable<typeof shading>).themeFillShade = themeFillShade;
2501
+ if (themeColor) (shading as Mutable<typeof shading>).themeColor = themeColor;
2502
+ if (themeColorTint) (shading as Mutable<typeof shading>).themeColorTint = themeColorTint;
2502
2503
  if (themeColorShade) shading.themeColorShade = themeColorShade;
2503
2504
  return Object.keys(shading).length > 0 ? shading : undefined;
2504
2505
  }
@@ -2511,7 +2512,7 @@ function readParagraphCnfStyle(node: XmlElementNode): string | undefined {
2511
2512
  }
2512
2513
 
2513
2514
  function readBorder(node: XmlElementNode): ParagraphBorders[keyof ParagraphBorders] {
2514
- const border: NonNullable<ParagraphBorders[keyof ParagraphBorders]> = {};
2515
+ const border: Mutable<NonNullable<ParagraphBorders[keyof ParagraphBorders]>> = {};
2515
2516
  const value = node.attributes["w:val"] ?? node.attributes.val;
2516
2517
  const size = node.attributes["w:sz"] ?? node.attributes.sz;
2517
2518
  const space = node.attributes["w:space"] ?? node.attributes.space;
@@ -3632,7 +3633,7 @@ function readSectionPropertiesXmlFromPPr(
3632
3633
  export function parseSectionPropertiesFromElement(
3633
3634
  node: XmlElementNode,
3634
3635
  ): SectionProperties {
3635
- const props: SectionProperties = {};
3636
+ const props: Mutable<SectionProperties> = {};
3636
3637
 
3637
3638
  for (const child of node.children) {
3638
3639
  if (child.type !== "element") continue;
@@ -3643,7 +3644,7 @@ export function parseSectionPropertiesFromElement(
3643
3644
  const w = safeParseInt(child.attributes["w:w"]);
3644
3645
  const h = safeParseInt(child.attributes["w:h"]);
3645
3646
  if (w !== undefined && h !== undefined) {
3646
- const pageSize: PageSize = { width: w, height: h };
3647
+ const pageSize: Mutable<PageSize> = { width: w, height: h };
3647
3648
  const orient = child.attributes["w:orient"];
3648
3649
  if (orient === "landscape" || orient === "portrait") {
3649
3650
  pageSize.orientation = orient;
@@ -3658,26 +3659,26 @@ export function parseSectionPropertiesFromElement(
3658
3659
  const bottom = safeParseInt(child.attributes["w:bottom"]);
3659
3660
  const left = safeParseInt(child.attributes["w:left"]);
3660
3661
  if (top !== undefined && right !== undefined && bottom !== undefined && left !== undefined) {
3661
- const margins: PageMargins = { top, right, bottom, left };
3662
+ const margins: Mutable<PageMargins> = { top, right, bottom, left };
3662
3663
  const header = safeParseInt(child.attributes["w:header"]);
3663
3664
  const footer = safeParseInt(child.attributes["w:footer"]);
3664
3665
  const gutter = safeParseInt(child.attributes["w:gutter"]);
3665
- if (header !== undefined) margins.header = header;
3666
- if (footer !== undefined) margins.footer = footer;
3667
- if (gutter !== undefined) margins.gutter = gutter;
3666
+ if (header !== undefined) (margins as Mutable<typeof margins>).header = header;
3667
+ if (footer !== undefined) (margins as Mutable<typeof margins>).footer = footer;
3668
+ if (gutter !== undefined) (margins as Mutable<typeof margins>).gutter = gutter;
3668
3669
  props.pageMargins = margins;
3669
3670
  }
3670
3671
  break;
3671
3672
  }
3672
3673
  case "cols": {
3673
- const columns: ColumnProperties = {};
3674
+ const columns: Mutable<ColumnProperties> = {};
3674
3675
  const num = safeParseInt(child.attributes["w:num"]);
3675
3676
  const space = safeParseInt(child.attributes["w:space"]);
3676
3677
  const equalWidth = child.attributes["w:equalWidth"];
3677
3678
  const sep = child.attributes["w:sep"];
3678
- if (num !== undefined) columns.count = num;
3679
- if (space !== undefined) columns.space = space;
3680
- if (equalWidth !== undefined) columns.equalWidth = equalWidth !== "0" && equalWidth !== "false";
3679
+ if (num !== undefined) (columns as Mutable<typeof columns>).count = num;
3680
+ if (space !== undefined) (columns as Mutable<typeof columns>).space = space;
3681
+ if (equalWidth !== undefined) (columns as Mutable<typeof columns>).equalWidth = equalWidth !== "0" && equalWidth !== "false";
3681
3682
  if (sep === "1" || sep === "true") columns.separator = true;
3682
3683
  const colDefs: Array<{ width: number; space?: number }> = [];
3683
3684
  for (const colChild of child.children) {
@@ -3689,31 +3690,31 @@ export function parseSectionPropertiesFromElement(
3689
3690
  }
3690
3691
  }
3691
3692
  }
3692
- if (colDefs.length > 0) columns.columns = colDefs;
3693
+ if (colDefs.length > 0) (columns as Mutable<typeof columns>).columns = colDefs;
3693
3694
  if (Object.keys(columns).length > 0) props.columns = columns;
3694
3695
  break;
3695
3696
  }
3696
3697
  case "pgNumType": {
3697
- const numbering: PageNumbering = {};
3698
+ const numbering: Mutable<PageNumbering> = {};
3698
3699
  const fmt = child.attributes["w:fmt"];
3699
3700
  const start = safeParseInt(child.attributes["w:start"]);
3700
3701
  const chapStyle = child.attributes["w:chapStyle"];
3701
3702
  const chapSep = child.attributes["w:chapSep"];
3702
- if (fmt) numbering.format = fmt;
3703
- if (start !== undefined) numbering.start = start;
3704
- if (chapStyle) numbering.chapStyle = chapStyle;
3705
- if (chapSep) numbering.chapSep = chapSep;
3703
+ if (fmt) (numbering as Mutable<typeof numbering>).format = fmt;
3704
+ if (start !== undefined) (numbering as Mutable<typeof numbering>).start = start;
3705
+ if (chapStyle) (numbering as Mutable<typeof numbering>).chapStyle = chapStyle;
3706
+ if (chapSep) (numbering as Mutable<typeof numbering>).chapSep = chapSep;
3706
3707
  if (Object.keys(numbering).length > 0) props.pageNumbering = numbering;
3707
3708
  break;
3708
3709
  }
3709
3710
  case "lnNumType": {
3710
- const lineNumbering: SectionLineNumbering = {};
3711
+ const lineNumbering: Mutable<SectionLineNumbering> = {};
3711
3712
  const countBy = safeParseInt(child.attributes["w:countBy"]);
3712
3713
  const start = safeParseInt(child.attributes["w:start"]);
3713
3714
  const distance = safeParseInt(child.attributes["w:distance"]);
3714
3715
  const restart = child.attributes["w:restart"];
3715
- if (countBy !== undefined) lineNumbering.countBy = countBy;
3716
- if (start !== undefined) lineNumbering.start = start;
3716
+ if (countBy !== undefined) (lineNumbering as Mutable<typeof lineNumbering>).countBy = countBy;
3717
+ if (start !== undefined) (lineNumbering as Mutable<typeof lineNumbering>).start = start;
3717
3718
  if (distance !== undefined) lineNumbering.distance = distance;
3718
3719
  if (
3719
3720
  restart === "newPage" ||
@@ -3728,7 +3729,7 @@ export function parseSectionPropertiesFromElement(
3728
3729
  break;
3729
3730
  }
3730
3731
  case "pgBorders": {
3731
- const pageBorders: SectionPageBorders = {};
3732
+ const pageBorders: Mutable<SectionPageBorders> = {};
3732
3733
  const offsetFrom = child.attributes["w:offsetFrom"];
3733
3734
  const display = child.attributes["w:display"];
3734
3735
  const zOrder = child.attributes["w:zOrder"];
@@ -3765,7 +3766,7 @@ export function parseSectionPropertiesFromElement(
3765
3766
  break;
3766
3767
  }
3767
3768
  case "docGrid": {
3768
- const documentGrid: SectionDocumentGrid = {};
3769
+ const documentGrid: Mutable<SectionDocumentGrid> = {};
3769
3770
  const type = child.attributes["w:type"];
3770
3771
  const linePitch = safeParseInt(child.attributes["w:linePitch"]);
3771
3772
  const charSpace = safeParseInt(child.attributes["w:charSpace"]);
@@ -3777,7 +3778,7 @@ export function parseSectionPropertiesFromElement(
3777
3778
  ) {
3778
3779
  documentGrid.type = type;
3779
3780
  }
3780
- if (linePitch !== undefined) documentGrid.linePitch = linePitch;
3781
+ if (linePitch !== undefined) (documentGrid as Mutable<typeof documentGrid>).linePitch = linePitch;
3781
3782
  if (charSpace !== undefined) documentGrid.charSpace = charSpace;
3782
3783
  if (Object.keys(documentGrid).length > 0) {
3783
3784
  props.documentGrid = documentGrid;
@@ -3856,7 +3857,7 @@ function safeParseInt(value: string | undefined): number | undefined {
3856
3857
  function readFootnoteLikeProperties(
3857
3858
  node: XmlElementNode,
3858
3859
  ): FootnoteProperties | undefined {
3859
- const result: FootnoteProperties = {};
3860
+ const result: Mutable<FootnoteProperties> = {};
3860
3861
 
3861
3862
  for (const child of node.children) {
3862
3863
  if (child.type !== "element") continue;
@@ -3902,15 +3903,15 @@ function readFootnoteLikeProperties(
3902
3903
  }
3903
3904
 
3904
3905
  function parseBorderSpec(node: XmlElementNode): BorderSpec | undefined {
3905
- const border: BorderSpec = {};
3906
+ const border: Mutable<BorderSpec> = {};
3906
3907
  const value = node.attributes["w:val"];
3907
3908
  const size = safeParseInt(node.attributes["w:sz"]);
3908
3909
  const space = safeParseInt(node.attributes["w:space"]);
3909
3910
  const color = node.attributes["w:color"];
3910
3911
 
3911
- if (value) border.value = value;
3912
- if (size !== undefined) border.size = size;
3913
- if (space !== undefined) border.space = space;
3912
+ if (value) (border as Mutable<typeof border>).value = value;
3913
+ if (size !== undefined) (border as Mutable<typeof border>).size = size;
3914
+ if (space !== undefined) (border as Mutable<typeof border>).space = space;
3914
3915
  if (color) border.color = color;
3915
3916
 
3916
3917
  return Object.keys(border).length > 0 ? border : undefined;
@@ -8,6 +8,7 @@ import type {
8
8
  ParagraphSpacing,
9
9
  ParagraphIndentation,
10
10
  TabStop,
11
+ Mutable,
11
12
  } from "../../model/canonical-document.ts";
12
13
  import { readRunProperties } from "./parse-run-formatting.ts";
13
14
  import type { OpcRelationship } from "./part-manifest.ts";
@@ -519,7 +520,7 @@ function readParagraphIndentation(node: XmlElementNode): ParagraphIndentation |
519
520
  return undefined;
520
521
  }
521
522
 
522
- const indentation: ParagraphIndentation = {};
523
+ const indentation: Mutable<ParagraphIndentation> = {};
523
524
  const left = readStringAttr(indNode, "w:start") ?? readStringAttr(indNode, "w:left");
524
525
  const right = readStringAttr(indNode, "w:end") ?? readStringAttr(indNode, "w:right");
525
526
  const firstLine = readStringAttr(indNode, "w:firstLine");
@@ -560,7 +561,7 @@ function readParagraphSpacing(node: XmlElementNode): ParagraphSpacing | undefine
560
561
  return undefined;
561
562
  }
562
563
 
563
- const spacing: ParagraphSpacing = {};
564
+ const spacing: Mutable<ParagraphSpacing> = {};
564
565
  const before = readStringAttr(spacingNode, "w:before");
565
566
  const after = readStringAttr(spacingNode, "w:after");
566
567
  const line = readStringAttr(spacingNode, "w:line");
@@ -18,7 +18,7 @@
18
18
  * responsibility post-v2.0; this module emits only data.
19
19
  */
20
20
 
21
- import type { OleEmbedNode } from "../../model/canonical-document.ts";
21
+ import type { OleEmbedNode, Mutable } from "../../model/canonical-document.ts";
22
22
  import type { OpcRelationship } from "./part-manifest.ts";
23
23
  import type { XmlElementNode } from "./xml-element.ts";
24
24
  import { resolveOleRelationship } from "./parse-ole-relationship.ts";
@@ -93,13 +93,13 @@ export function parseObject(
93
93
 
94
94
  const metadata: OleEmbedNode["metadata"] = {};
95
95
  if (resolved.originalFilename) {
96
- metadata.originalFilename = resolved.originalFilename;
96
+ (metadata as Mutable<typeof metadata>).originalFilename = resolved.originalFilename;
97
97
  }
98
98
  if (classId) {
99
- metadata.classId = classId;
99
+ (metadata as Mutable<typeof metadata>).classId = classId;
100
100
  }
101
101
  if (shapeId) {
102
- metadata.shapeId = shapeId;
102
+ (metadata as Mutable<typeof metadata>).shapeId = shapeId;
103
103
  }
104
104
 
105
105
  const id =
@@ -107,7 +107,7 @@ export function parseObject(
107
107
  ? `ole-embed-${resolved.relationshipId}-${occurrenceIndex}`
108
108
  : `ole-embed-${resolved.relationshipId}`;
109
109
 
110
- const result: OleEmbedNode = {
110
+ const result: Mutable<OleEmbedNode> = {
111
111
  type: "ole_embed",
112
112
  id,
113
113
  embedType: "oleObject",
@@ -116,7 +116,7 @@ export function parseObject(
116
116
  rawXml,
117
117
  };
118
118
  if (progId) {
119
- result.progId = progId;
119
+ (result as Mutable<typeof result>).progId = progId;
120
120
  }
121
121
  return result;
122
122
  }
@@ -14,6 +14,7 @@ import type {
14
14
  ParagraphShading,
15
15
  ParagraphSpacing,
16
16
  TabStop,
17
+ Mutable,
17
18
  } from "../../model/canonical-document.ts";
18
19
  import { readRunProperties } from "./parse-run-formatting.ts";
19
20
  import { findChildOptional, localName, readIntAttr, readIntVal, readOnOff } from "./xml-attr-helpers.ts";
@@ -87,31 +88,31 @@ const PPR_GRAB_BAG_DESCRIPTOR: PropertyGrabBagDescriptor = {
87
88
  };
88
89
 
89
90
  function readSpacing(node: XmlElementNode): ParagraphSpacing | undefined {
90
- const out: ParagraphSpacing = {};
91
+ const out: Mutable<ParagraphSpacing> = {};
91
92
  const before = readIntAttr(node, "w:before");
92
93
  const after = readIntAttr(node, "w:after");
93
94
  const line = readIntAttr(node, "w:line");
94
95
  const rule = node.attributes["w:lineRule"] ?? node.attributes.lineRule;
95
- if (before !== undefined) out.before = before;
96
- if (after !== undefined) out.after = after;
96
+ if (before !== undefined) (out as Mutable<typeof out>).before = before;
97
+ if (after !== undefined) (out as Mutable<typeof out>).after = after;
97
98
  if (line !== undefined) out.line = line;
98
99
  if (rule) {
99
100
  const n = rule.toLowerCase();
100
- if (n === "auto" || n === "exact") out.lineRule = n;
101
+ if (n === "auto" || n === "exact") (out as Mutable<typeof out>).lineRule = n;
101
102
  else if (n === "atleast") out.lineRule = "atLeast";
102
103
  }
103
104
  return Object.keys(out).length > 0 ? out : undefined;
104
105
  }
105
106
 
106
107
  function readIndent(node: XmlElementNode): ParagraphIndentation | undefined {
107
- const out: ParagraphIndentation = {};
108
+ const out: Mutable<ParagraphIndentation> = {};
108
109
  const left = readIntAttr(node, "w:left") ?? readIntAttr(node, "w:start");
109
110
  const right = readIntAttr(node, "w:right") ?? readIntAttr(node, "w:end");
110
111
  const firstLine = readIntAttr(node, "w:firstLine");
111
112
  const hanging = readIntAttr(node, "w:hanging");
112
- if (left !== undefined) out.left = left;
113
- if (right !== undefined) out.right = right;
114
- if (firstLine !== undefined) out.firstLine = firstLine;
113
+ if (left !== undefined) (out as Mutable<typeof out>).left = left;
114
+ if (right !== undefined) (out as Mutable<typeof out>).right = right;
115
+ if (firstLine !== undefined) (out as Mutable<typeof out>).firstLine = firstLine;
115
116
  if (hanging !== undefined) out.hanging = hanging;
116
117
  return Object.keys(out).length > 0 ? out : undefined;
117
118
  }
@@ -138,7 +139,7 @@ function readTabStops(node: XmlElementNode): TabStop[] | undefined {
138
139
  }
139
140
 
140
141
  function readBorders(node: XmlElementNode): ParagraphBorders | undefined {
141
- const out: ParagraphBorders = {};
142
+ const out: Mutable<ParagraphBorders> = {};
142
143
  const sides = ["top", "bottom", "left", "right", "between", "bar"] as const;
143
144
  for (const side of sides) {
144
145
  const child = findChildOptional(node, side);
@@ -205,7 +206,7 @@ function readShading(node: XmlElementNode): ParagraphShading | undefined {
205
206
  * text frames, drop-caps); extension attrs are rare in that corpus.
206
207
  */
207
208
  export function readFrameProperties(node: XmlElementNode): FrameProperties | undefined {
208
- const out: FrameProperties = {};
209
+ const out: Mutable<FrameProperties> = {};
209
210
  const width = readIntAttr(node, "w:w");
210
211
  if (width !== undefined) out.widthTwips = width;
211
212
  const height = readIntAttr(node, "w:h");
@@ -268,7 +269,7 @@ export function readParagraphProperties(
268
269
  ): CanonicalParagraphFormatting | undefined {
269
270
  if (!node) return undefined;
270
271
 
271
- const out: CanonicalParagraphFormatting = {};
272
+ const out: Mutable<CanonicalParagraphFormatting> = {};
272
273
 
273
274
  const spacingNode = findChildOptional(node, "spacing");
274
275
  if (spacingNode) {