@beyondwork/docx-react-component 1.0.102 → 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 (33) 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/normalize/normalize-text.ts +6 -5
  7. package/src/io/ooxml/parse-anchor.ts +15 -15
  8. package/src/io/ooxml/parse-drawing.ts +5 -5
  9. package/src/io/ooxml/parse-fields.ts +16 -15
  10. package/src/io/ooxml/parse-font-table.ts +2 -1
  11. package/src/io/ooxml/parse-footnotes.ts +3 -2
  12. package/src/io/ooxml/parse-headers-footers.ts +7 -6
  13. package/src/io/ooxml/parse-main-document.ts +41 -40
  14. package/src/io/ooxml/parse-numbering.ts +3 -2
  15. package/src/io/ooxml/parse-object.ts +6 -6
  16. package/src/io/ooxml/parse-paragraph-formatting.ts +12 -11
  17. package/src/io/ooxml/parse-picture.ts +16 -16
  18. package/src/io/ooxml/parse-run-formatting.ts +11 -10
  19. package/src/io/ooxml/parse-settings.ts +2 -1
  20. package/src/io/ooxml/parse-shapes.ts +18 -17
  21. package/src/io/ooxml/parse-styles.ts +16 -16
  22. package/src/io/ooxml/parse-theme.ts +5 -4
  23. package/src/model/canonical-document.ts +835 -833
  24. package/src/runtime/formatting/document-lookup.ts +3 -2
  25. package/src/runtime/formatting/formatting-context.ts +66 -25
  26. package/src/runtime/formatting/index.ts +18 -0
  27. package/src/runtime/formatting/layout-inputs.ts +256 -0
  28. package/src/runtime/formatting/numbering/geometry.ts +13 -12
  29. package/src/runtime/formatting/style-cascade.ts +2 -1
  30. package/src/runtime/formatting/table-style-resolver.ts +8 -7
  31. package/src/runtime/surface-projection.ts +31 -36
  32. package/src/session/import/normalize.ts +2 -1
  33. package/src/session/import/source-package-evidence.ts +612 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@beyondwork/docx-react-component",
3
3
  "publisher": "beyondwork",
4
- "version": "1.0.102",
4
+ "version": "1.0.103",
5
5
  "description": "Embeddable React Word (docx) editor with review, comments, tracked changes, and round-trip OOXML fidelity.",
6
6
  "type": "module",
7
7
  "sideEffects": [
@@ -37,6 +37,7 @@ import type {
37
37
  ParagraphNode,
38
38
  TextMark,
39
39
  TextNode,
40
+ Mutable,
40
41
  } from "../../model/canonical-document.ts";
41
42
 
42
43
  // ---------------------------------------------------------------------------
@@ -659,7 +660,7 @@ export function applyTextMarkOperationToDocumentRange(
659
660
  updateMarks,
660
661
  );
661
662
  if (transformed.changed) {
662
- block.children = transformed.nodes;
663
+ (block as Mutable<typeof block>).children = transformed.nodes;
663
664
  changed = true;
664
665
  }
665
666
  }
@@ -862,7 +863,7 @@ function resolveMarkUpdater(
862
863
  }
863
864
 
864
865
  function applyAlignment(
865
- paragraph: ParagraphNode,
866
+ paragraph: Mutable<ParagraphNode>,
866
867
  alignment: FormattingAlignment,
867
868
  ): boolean {
868
869
  const nextAlignment = alignment === "justify" ? "both" : alignment;
@@ -880,7 +881,7 @@ function applyAlignment(
880
881
  * must clone first if the source is shared. Returns `false` when no change
881
882
  * occurred (already at the 0 / 8 bound, or no-op).
882
883
  */
883
- export function applyIndentation(paragraph: ParagraphNode, delta: -1 | 1): boolean {
884
+ export function applyIndentation(paragraph: Mutable<ParagraphNode>, delta: -1 | 1): boolean {
884
885
  if (paragraph.numbering) {
885
886
  const nextLevel = clamp(paragraph.numbering.level + delta, 0, 8);
886
887
  if (nextLevel === paragraph.numbering.level) {
@@ -904,10 +905,10 @@ export function applyIndentation(paragraph: ParagraphNode, delta: -1 | 1): boole
904
905
  ...(paragraph.indentation ?? {}),
905
906
  };
906
907
  if (nextLeft > 0) {
907
- nextIndentation.left = nextLeft;
908
+ (nextIndentation as Mutable<typeof nextIndentation>).left = nextLeft;
908
909
  paragraph.indentation = nextIndentation;
909
910
  } else if (paragraph.indentation) {
910
- delete nextIndentation.left;
911
+ delete (nextIndentation as Mutable<typeof nextIndentation>).left;
911
912
  paragraph.indentation =
912
913
  Object.keys(nextIndentation).length > 0 ? nextIndentation : undefined;
913
914
  }
@@ -1042,7 +1043,7 @@ function getConsistentValue<TItem, TValue>(
1042
1043
  function visitParagraphBindings(
1043
1044
  blocks: BlockNode[],
1044
1045
  surfaceBlocks: SurfaceBlockSnapshot[],
1045
- visitor: (paragraph: ParagraphNode, surface: ParagraphSurfaceBlock) => void,
1046
+ visitor: (paragraph: Mutable<ParagraphNode>, surface: ParagraphSurfaceBlock) => void,
1046
1047
  ): void {
1047
1048
  for (let index = 0; index < Math.min(blocks.length, surfaceBlocks.length); index += 1) {
1048
1049
  const block = blocks[index];
@@ -1146,7 +1147,7 @@ function transformInlineNodes(
1146
1147
  }
1147
1148
 
1148
1149
  function transformTextNode(
1149
- node: TextNode,
1150
+ node: Mutable<TextNode>,
1150
1151
  start: number,
1151
1152
  selectionFrom: number,
1152
1153
  selectionTo: number,
@@ -11,6 +11,7 @@ import type {
11
11
  TableCellNode,
12
12
  TableNode,
13
13
  TableRowNode,
14
+ Mutable,
14
15
  } from "../../model/canonical-document.ts";
15
16
 
16
17
  export interface ParagraphLayoutCommandContext {
@@ -26,7 +27,7 @@ export interface ParagraphLayoutMutationResult {
26
27
  export function setActiveParagraphIndentation(
27
28
  document: CanonicalDocumentEnvelope,
28
29
  snapshot: RuntimeRenderSnapshot,
29
- indentation: ParagraphIndentation,
30
+ indentation: Mutable<ParagraphIndentation>,
30
31
  _context: ParagraphLayoutCommandContext,
31
32
  ): ParagraphLayoutMutationResult {
32
33
  return mutateActiveParagraph(document, snapshot, (paragraph) => {
@@ -66,7 +67,7 @@ export function setActiveParagraphTabStops(
66
67
  function mutateActiveParagraph(
67
68
  document: CanonicalDocumentEnvelope,
68
69
  snapshot: RuntimeRenderSnapshot,
69
- mutate: (paragraph: ParagraphNode) => boolean,
70
+ mutate: (paragraph: Mutable<ParagraphNode>) => boolean,
70
71
  ): ParagraphLayoutMutationResult {
71
72
  const surface = snapshot.surface;
72
73
  if (!surface) {
@@ -190,27 +191,27 @@ function collectCanonicalParagraphs(
190
191
  return output;
191
192
  }
192
193
 
193
- function collectParagraphsFromTable(table: TableNode, output: ParagraphNode[]): void {
194
+ function collectParagraphsFromTable(table: Mutable<TableNode>, output: ParagraphNode[]): void {
194
195
  for (const row of table.rows) {
195
196
  collectParagraphsFromRow(row, output);
196
197
  }
197
198
  }
198
199
 
199
- function collectParagraphsFromRow(row: TableRowNode, output: ParagraphNode[]): void {
200
+ function collectParagraphsFromRow(row: Mutable<TableRowNode>, output: ParagraphNode[]): void {
200
201
  for (const cell of row.cells) {
201
202
  collectParagraphsFromCell(cell, output);
202
203
  }
203
204
  }
204
205
 
205
- function collectParagraphsFromCell(cell: TableCellNode, output: ParagraphNode[]): void {
206
+ function collectParagraphsFromCell(cell: Mutable<TableCellNode>, output: ParagraphNode[]): void {
206
207
  collectCanonicalParagraphs(cell.children, output);
207
208
  }
208
209
 
209
210
  function mergeIndentationPatch(
210
211
  current: ParagraphIndentation | undefined,
211
- patch: ParagraphIndentation,
212
+ patch: Mutable<ParagraphIndentation>,
212
213
  ): ParagraphIndentation | undefined {
213
- const merged: ParagraphIndentation = {
214
+ const merged: Mutable<ParagraphIndentation> = {
214
215
  ...(current ?? {}),
215
216
  };
216
217
 
@@ -237,9 +238,9 @@ function mergeIndentationPatch(
237
238
  }
238
239
 
239
240
  function normalizeIndentation(
240
- indentation: ParagraphIndentation,
241
+ indentation: Mutable<ParagraphIndentation>,
241
242
  ): ParagraphIndentation | undefined {
242
- const normalized: ParagraphIndentation = {};
243
+ const normalized: Mutable<ParagraphIndentation> = {};
243
244
  if (indentation.left !== undefined && indentation.left > 0) {
244
245
  normalized.left = Math.round(indentation.left);
245
246
  }
@@ -250,7 +251,7 @@ function normalizeIndentation(
250
251
  normalized.firstLine = Math.round(indentation.firstLine);
251
252
  }
252
253
  if (indentation.hanging !== undefined && indentation.hanging > 0) {
253
- normalized.hanging = Math.round(indentation.hanging);
254
+ (normalized as Mutable<typeof normalized>).hanging = Math.round(indentation.hanging);
254
255
  delete normalized.firstLine;
255
256
  }
256
257
  return Object.keys(normalized).length > 0 ? normalized : undefined;
@@ -21,6 +21,7 @@ import type {
21
21
  PageSize,
22
22
  SectionBreakNode,
23
23
  SectionProperties,
24
+ Mutable,
24
25
  } from "../../model/canonical-document.ts";
25
26
  import type {
26
27
  MarginPresetDefinition,
@@ -145,7 +146,7 @@ export function insertSectionBreak(
145
146
 
146
147
  const sectionTarget = resolveSectionTarget(cloned, surface.blocks, position);
147
148
  const inheritedProperties = cloneSectionProperties(sectionTarget?.properties);
148
- const sectionBreak: SectionBreakNode = {
149
+ const sectionBreak: Mutable<SectionBreakNode> = {
149
150
  type: "section_break",
150
151
  sectionProperties: {
151
152
  ...inheritedProperties,
@@ -178,7 +179,7 @@ export function insertSectionBreakAfterSectionIndex(
178
179
  const inheritedProperties = cloneSectionProperties(
179
180
  getSectionPropertiesAtIndex(cloned, sectionIndex),
180
181
  );
181
- const sectionBreak: SectionBreakNode = {
182
+ const sectionBreak: Mutable<SectionBreakNode> = {
182
183
  type: "section_break",
183
184
  sectionProperties: {
184
185
  ...inheritedProperties,
@@ -364,9 +365,9 @@ export function setSectionPageNumberingAtSectionIndex(
364
365
 
365
366
  const nextProperties = cloneSectionProperties(target.properties);
366
367
  if (pageNumbering === null) {
367
- delete nextProperties.pageNumbering;
368
+ delete (nextProperties as Mutable<typeof nextProperties>).pageNumbering;
368
369
  } else {
369
- nextProperties.pageNumbering = {
370
+ (nextProperties as Mutable<typeof nextProperties>).pageNumbering = {
370
371
  ...(target.properties?.pageNumbering ?? {}),
371
372
  ...pageNumbering,
372
373
  };
@@ -683,10 +684,10 @@ function findNearestSectionBreak(
683
684
  }
684
685
 
685
686
  function applySectionLayoutPatch(
686
- existing: SectionProperties,
687
+ existing: Mutable<SectionProperties>,
687
688
  patch: SectionLayoutPatch,
688
689
  ): SectionProperties {
689
- const result: SectionProperties = { ...existing };
690
+ const result: Mutable<SectionProperties> = { ...existing };
690
691
 
691
692
  if (patch.pageSize) {
692
693
  result.pageSize = {
@@ -8,6 +8,7 @@ import type {
8
8
  DocumentRootNode,
9
9
  ParagraphNode,
10
10
  TableNode,
11
+ Mutable,
11
12
  } from "../../model/canonical-document.ts";
12
13
 
13
14
  type CanonicalDocumentEnvelope = PersistedEditorSnapshot["canonicalDocument"];
@@ -161,7 +162,7 @@ function isValidTableStyleId(
161
162
  function visitParagraphBindings(
162
163
  blocks: BlockNode[],
163
164
  surfaceBlocks: SurfaceBlockSnapshot[],
164
- visitor: (paragraph: ParagraphNode, surface: Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>) => void,
165
+ visitor: (paragraph: Mutable<ParagraphNode>, surface: Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>) => void,
165
166
  ): void {
166
167
  for (let index = 0; index < Math.min(blocks.length, surfaceBlocks.length); index += 1) {
167
168
  const block = blocks[index];
@@ -203,7 +204,7 @@ function visitParagraphBindings(
203
204
  function visitTableBindings(
204
205
  blocks: BlockNode[],
205
206
  surfaceBlocks: SurfaceBlockSnapshot[],
206
- visitor: (table: TableNode, surface: Extract<SurfaceBlockSnapshot, { kind: "table" }>) => void,
207
+ visitor: (table: Mutable<TableNode>, surface: Extract<SurfaceBlockSnapshot, { kind: "table" }>) => void,
207
208
  ): void {
208
209
  for (let index = 0; index < Math.min(blocks.length, surfaceBlocks.length); index += 1) {
209
210
  const block = blocks[index];
@@ -18,6 +18,7 @@ import type {
18
18
  TextMark,
19
19
  TextNode,
20
20
  SdtNode,
21
+ Mutable,
21
22
  } from "../../model/canonical-document.ts";
22
23
  import type {
23
24
  ParsedAltChunkNode,
@@ -108,7 +109,7 @@ export function normalizeParsedTextDocument(
108
109
  }
109
110
  }
110
111
 
111
- const content: DocumentRootNode = { type: "doc", children };
112
+ const content: Mutable<DocumentRootNode> = { type: "doc", children };
112
113
 
113
114
  return {
114
115
  content,
@@ -180,7 +181,7 @@ export async function normalizeParsedTextDocumentAsync(
180
181
  }
181
182
  }
182
183
 
183
- const content: DocumentRootNode = { type: "doc", children };
184
+ const content: Mutable<DocumentRootNode> = { type: "doc", children };
184
185
 
185
186
  return {
186
187
  content,
@@ -432,7 +433,7 @@ function normalizeInlineChildren(
432
433
 
433
434
  const previous = normalized[normalized.length - 1];
434
435
  if (previous?.type === "text" && sameMarks(previous.marks, node.marks)) {
435
- previous.text += node.text;
436
+ (previous as Mutable<typeof previous>).text += node.text;
436
437
  } else {
437
438
  normalized.push({
438
439
  type: "text",
@@ -752,7 +753,7 @@ function normalizeHyperlink(node: ParsedHyperlinkNode): {
752
753
  }
753
754
  const previous = children[children.length - 1];
754
755
  if (previous?.type === "text" && sameMarks(previous.marks, child.marks)) {
755
- previous.text += child.text;
756
+ (previous as Mutable<typeof previous>).text += child.text;
756
757
  } else {
757
758
  children.push({
758
759
  type: "text",
@@ -835,7 +836,7 @@ function recordOpaqueFragment(
835
836
  const rangeStart = state.cursor;
836
837
  const rangeEnd = state.cursor + 1;
837
838
 
838
- const record: OpaqueFragmentRecord = {
839
+ const record: Mutable<OpaqueFragmentRecord> = {
839
840
  fragmentId,
840
841
  payloadKind: "xml-subtree",
841
842
  payloadReference: rawXml,
@@ -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");