@stll/folio-core 0.56.0 → 0.58.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.
Files changed (158) hide show
  1. package/dist/ai-edits/apply.js +122 -22
  2. package/dist/ai-edits/batch-claims.d.ts +3 -1
  3. package/dist/ai-edits/batch-claims.js +25 -1
  4. package/dist/ai-edits/table-row-column-mutations.js +17 -3
  5. package/dist/ai-suggestions/apply.js +20 -1
  6. package/dist/compare/inline-atoms.js +40 -16
  7. package/dist/compare/inline-provenance.js +12 -5
  8. package/dist/compat/eigenpal.d.ts +2 -1
  9. package/dist/compat/eigenpal.js +2 -1
  10. package/dist/controller/canonicalClipboard.d.ts +3 -1
  11. package/dist/controller/canonicalClipboard.js +31 -13
  12. package/dist/controller/canonicalComments.d.ts +41 -0
  13. package/dist/controller/canonicalComments.js +152 -0
  14. package/dist/controller/canonicalComposition.d.ts +17 -4
  15. package/dist/controller/canonicalComposition.js +125 -20
  16. package/dist/controller/canonicalInlineProjection.d.ts +6 -1
  17. package/dist/controller/canonicalInlineProjection.js +86 -3
  18. package/dist/controller/canonicalInput.d.ts +1 -1
  19. package/dist/controller/canonicalInput.js +14 -4
  20. package/dist/controller/canonicalInputTimer.d.ts +10 -1
  21. package/dist/controller/canonicalInputTimer.js +24 -1
  22. package/dist/controller/canonicalPublicOperations.d.ts +2 -2
  23. package/dist/controller/canonicalPublicOperations.js +107 -15
  24. package/dist/controller/canonicalSelection.d.ts +18 -0
  25. package/dist/controller/canonicalSelection.js +41 -0
  26. package/dist/controller/canonicalSession.d.ts +4 -1
  27. package/dist/controller/canonicalSession.js +106 -36
  28. package/dist/controller/canonicalStoryEditor.d.ts +3 -1
  29. package/dist/controller/canonicalStoryEditor.js +21 -1
  30. package/dist/controller/canonicalStructure.js +8 -3
  31. package/dist/controller/folioEditor.js +13 -0
  32. package/dist/controller/headerFooterEditorManager.d.ts +1 -1
  33. package/dist/controller/headerFooterEditorManager.js +25 -11
  34. package/dist/controller/hiddenEditorApi.d.ts +13 -2
  35. package/dist/controller/hiddenEditorApi.js +5 -1
  36. package/dist/controller/hiddenEditorManager.d.ts +3 -1
  37. package/dist/controller/hiddenEditorManager.js +167 -14
  38. package/dist/controller/noteEditorManager.d.ts +1 -1
  39. package/dist/controller/noteEditorManager.js +28 -13
  40. package/dist/docx/builtInStyles.js +13 -6
  41. package/dist/docx/containerChildren.gen.d.ts +3 -1
  42. package/dist/docx/containerChildren.gen.js +33 -1
  43. package/dist/docx/fieldParser.js +14 -2
  44. package/dist/docx/hyperlinkParser.d.ts +1 -1
  45. package/dist/docx/hyperlinkParser.js +20 -1
  46. package/dist/docx/inlineWrapperContent.d.ts +4 -4
  47. package/dist/docx/inlineWrapperContent.js +4 -4
  48. package/dist/docx/linkedSdtPreservation.d.ts +10 -0
  49. package/dist/docx/linkedSdtPreservation.js +37 -0
  50. package/dist/docx/listRendering.d.ts +18 -0
  51. package/dist/{prosemirror/conversion/listRenderingDefinition.js → docx/listRendering.js} +17 -3
  52. package/dist/docx/paragraphParser.js +88 -67
  53. package/dist/docx/paragraphPropertySource.d.ts +22 -1
  54. package/dist/docx/paragraphPropertySource.js +107 -1
  55. package/dist/docx/preservedRunContent.js +2 -1
  56. package/dist/docx/relsParser.js +26 -2
  57. package/dist/docx/rezip.js +9 -6
  58. package/dist/docx/selectiveSave.js +10 -8
  59. package/dist/docx/serializer/commentSerializer.d.ts +4 -1
  60. package/dist/docx/serializer/commentSerializer.js +7 -3
  61. package/dist/docx/serializer/paragraphSerializer.js +207 -94
  62. package/dist/docx/server/materializeYjsDocx.js +15 -7
  63. package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
  64. package/dist/i18n/messages/ar.gen.js +4 -0
  65. package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
  66. package/dist/i18n/messages/catalogs.gen.js +68 -0
  67. package/dist/i18n/messages/cs.gen.js +4 -0
  68. package/dist/i18n/messages/de.gen.js +4 -0
  69. package/dist/i18n/messages/en.gen.js +4 -0
  70. package/dist/i18n/messages/es.gen.js +4 -0
  71. package/dist/i18n/messages/et.gen.js +4 -0
  72. package/dist/i18n/messages/fr.gen.js +4 -0
  73. package/dist/i18n/messages/he.gen.js +4 -0
  74. package/dist/i18n/messages/hi.gen.js +4 -0
  75. package/dist/i18n/messages/hu.gen.js +4 -0
  76. package/dist/i18n/messages/lt.gen.js +4 -0
  77. package/dist/i18n/messages/lv.gen.js +4 -0
  78. package/dist/i18n/messages/messages.gen.d.ts +4 -0
  79. package/dist/i18n/messages/pl.gen.js +4 -0
  80. package/dist/i18n/messages/pt-BR.gen.js +4 -0
  81. package/dist/i18n/messages/sk.gen.js +4 -0
  82. package/dist/i18n/messages/tr.gen.js +4 -0
  83. package/dist/i18n/messages/zh-CN.gen.js +4 -0
  84. package/dist/index.d.ts +2 -1
  85. package/dist/index.js +2 -1
  86. package/dist/internal/revisionResolutionInline.js +25 -3
  87. package/dist/markdown/internals.js +7 -0
  88. package/dist/markdown/renderParagraph.js +11 -12
  89. package/dist/markdown/renderRuns.js +3 -13
  90. package/dist/markdown/types.d.ts +3 -0
  91. package/dist/panel-layout.d.ts +11 -9
  92. package/dist/panel-layout.js +13 -9
  93. package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
  94. package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
  95. package/dist/prosemirror/attrs/index.js +9 -0
  96. package/dist/prosemirror/commands/comments.js +60 -35
  97. package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
  98. package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
  99. package/dist/prosemirror/commentOps.js +15 -1
  100. package/dist/prosemirror/conversion/fromProseDoc.d.ts +8 -1
  101. package/dist/prosemirror/conversion/fromProseDoc.js +150 -30
  102. package/dist/prosemirror/conversion/toProseDoc.js +128 -40
  103. package/dist/prosemirror/extensions/core/ParagraphExtension.js +22 -5
  104. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
  105. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
  106. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +22 -14
  107. package/dist/prosemirror/extensions/marks/markUtils.js +8 -7
  108. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
  109. package/dist/prosemirror/extensions/nodes/ImageExtension.js +8 -1
  110. package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
  111. package/dist/prosemirror/fieldRepresentation.js +18 -0
  112. package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
  113. package/dist/prosemirror/hyperlinkRemoval.js +28 -9
  114. package/dist/prosemirror/imagePictureNames.d.ts +12 -0
  115. package/dist/prosemirror/imagePictureNames.js +20 -0
  116. package/dist/prosemirror/listNumbering.js +11 -5
  117. package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
  118. package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
  119. package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
  120. package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
  121. package/dist/prosemirror/noteReferenceReview.js +14 -1
  122. package/dist/prosemirror/paragraphFormattingProvenance.js +1 -0
  123. package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
  124. package/dist/prosemirror/plugins/documentStyles.js +17 -10
  125. package/dist/prosemirror/plugins/suggestionMode.js +47 -49
  126. package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
  127. package/dist/prosemirror/preservedXmlReview.js +35 -0
  128. package/dist/prosemirror/runFormattingFromMarks.js +2 -2
  129. package/dist/prosemirror/runFormattingReconciliation.js +5 -4
  130. package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
  131. package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
  132. package/dist/prosemirror/runStyleFormatting.d.ts +74 -2
  133. package/dist/prosemirror/runStyleFormatting.js +20 -1
  134. package/dist/prosemirror/schema/marks.d.ts +1 -0
  135. package/dist/prosemirror/schema/nodes.d.ts +3 -0
  136. package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
  137. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
  138. package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
  139. package/dist/prosemirror/styles/styleResolver.d.ts +4 -1
  140. package/dist/prosemirror/styles/styleResolver.js +32 -11
  141. package/dist/prosemirror/textInput.d.ts +5 -1
  142. package/dist/prosemirror/textInput.js +3 -3
  143. package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
  144. package/dist/prosemirror/trackedRevisionPath.js +39 -1
  145. package/dist/prosemirror/validation.js +3 -5
  146. package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
  147. package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
  148. package/dist/types/canonicalCapabilities.d.ts +18 -18
  149. package/dist/types/canonicalCapabilities.js +18 -18
  150. package/dist/types/canonicalComments.d.ts +51 -0
  151. package/dist/types/canonicalComments.js +0 -0
  152. package/dist/types/canonicalSections.d.ts +12 -0
  153. package/dist/types/canonicalSections.js +0 -0
  154. package/dist/utils/headingCollector.js +45 -4
  155. package/dist/utils/outlineDepth.d.ts +9 -0
  156. package/dist/utils/outlineDepth.js +9 -0
  157. package/package.json +2 -2
  158. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +0 -6
@@ -1,8 +1,9 @@
1
1
  import { rangedCommentIds } from "../../docx/commentAnchorIndex.js";
2
2
  import { resolveColorValueToHex } from "../../docx/drawingUtils.js";
3
3
  import { isInlineSdtContent, isTrackedChangeWrapperChild } from "../../docx/inlineWrapperContent.js";
4
- import { computeListRendering, getCachedNumberingMap } from "../../docx/numberingParser.js";
5
- import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
4
+ import { listRenderingDefinitionsMatch, resolveListRenderingDefinition } from "../../docx/listRendering.js";
5
+ import { getCachedNumberingMap } from "../../docx/numberingParser.js";
6
+ import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, createProseParagraphWithPropertySource, getDocumentParagraphPropertySourceContract, paragraphFormattingWithAuthoredIndentation, proseParagraphAttrsWithoutPropertySource, recreateProseNodeWithParagraphPropertySource, transportTableCellsWithParagraphPropertySources } from "../../docx/paragraphPropertySource.js";
6
7
  import { isBaselineVertAlign } from "../../docx/runParser.js";
7
8
  import { replayableShapeAlternateContent } from "../../docx/shapeAlternateContent.js";
8
9
  import { resolveTableLook } from "../../docx/tableLook.js";
@@ -25,11 +26,11 @@ import { setAutospacingBaseValue } from "../autospacingBase.js";
25
26
  import { withEnclosingRevision } from "../contentControlRevisions.js";
26
27
  import { emptyFieldRunPropertyChanges } from "../emptyFieldResultRuns.js";
27
28
  import { planEmptyRanges } from "../emptyRangeAnchor.js";
28
- import { INLINE_WRAPPER_MARK_NAME } from "../extensions/marks/InlineWrapperExtension.js";
29
29
  import { textFormattingToMarks } from "../extensions/marks/markUtils.js";
30
30
  import { MOVE_RANGE_BOUNDARY_NODE_NAME } from "../extensions/nodes/MoveRangeBoundaryExtension.js";
31
31
  import { RANGE_ANCHOR_NODE_NAME } from "../extensions/nodes/RangeAnchorExtension.js";
32
32
  import "../extensions/nodes/SdtExtension.js";
33
+ import { fieldRequiresStructuredContent } from "../fieldRepresentation.js";
33
34
  import { inlineWrapperLayer } from "../inlineWrapperStack.js";
34
35
  import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
35
36
  import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
@@ -37,26 +38,40 @@ import { stampNumberedRefFieldBaselines } from "../numberedRefFields.js";
37
38
  import { paragraphNumberingAttr } from "../numberingAttr.js";
38
39
  import { pageBreakRunParagraphProjectionDispositionForFeatures } from "../pageBreakRunProjection.js";
39
40
  import { directionFromBidi } from "../paragraphDirection.js";
41
+ import { paragraphIndentationFromFormatting } from "../paragraphIndentation.js";
40
42
  import { lineSpacingProvenanceFromSpacing } from "../paragraphSpacing.js";
41
43
  import { RUN_IDENTITY_MARK_NAME, hasRunIdentityPayload, runIdentityAttrs } from "../runIdentity.js";
42
44
  import { continueRunIdentitiesAcrossRevisions } from "../runIdentityAcrossRevisions.js";
43
- import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
45
+ import { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, resolveParagraphInheritedRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting } from "../runStyleFormatting.js";
44
46
  import { schema } from "../schema/index.js";
45
47
  import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
46
48
  import { extractTableParagraphOverlay, paragraphStyleCascadeAttrs, resolveRunFormattingWithoutDefaults } from "../styles/paragraphStyleCascade.js";
49
+ import { listIndentationProvenancePatch } from "../styles/resolvedStyleAttrs.js";
47
50
  import { cascadeStyleTextFormatting } from "../styles/styleToggleCascade.js";
48
51
  import { tableCellStyleRegions, tableRowBand } from "../styles/tableStyleRegions.js";
49
52
  import { canCarryTrackedRunMark, trackedRunInlineAtomDisposition } from "../trackedRunInlineAtoms.js";
50
53
  import { assertValidProseMirrorDocument } from "../validation.js";
51
54
  import { resolveEffectiveTableCellFormatting } from "./effectiveTableCellFormatting.js";
52
55
  import { HYPHEN_TEXT_CARRIERS } from "./hyphenTextCarriers.js";
53
- import { listRenderingDefinitionsMatch } from "./listRenderingDefinition.js";
54
56
  import { createMarkInterner } from "./markInterner.js";
55
57
  import { hasSinkChildren } from "./preservedSinkCarriers.js";
56
58
  import { sdtAttrsFromProperties } from "./sdtAttrs.js";
57
59
  import { panic } from "better-result";
58
60
  import { DRAWING_RAW_XML_MODES, PARSE_WARNING_CODES, mergeParagraphNumbering } from "@stll/docx-core/model";
59
61
  //#region src/prosemirror/conversion/toProseDoc.ts
62
+ /**
63
+ * Document to ProseMirror Conversion
64
+ *
65
+ * Converts our Document type (from DOCX parsing) to a ProseMirror document.
66
+ * Preserves all formatting attributes for round-trip fidelity.
67
+ *
68
+ * Style Resolution:
69
+ * When styles are provided, paragraph properties are resolved from the style chain:
70
+ * - Document defaults (docDefaults)
71
+ * - Normal style (if no explicit styleId)
72
+ * - Style chain (basedOn inheritance)
73
+ * - Inline properties (highest priority)
74
+ */
60
75
  const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
61
76
  const noPageBreakProjectionWarning = () => {};
62
77
  const pageBreakProjectionWarn = (warn) => warn === void 0 ? noPageBreakProjectionWarning : (detail) => {
@@ -106,6 +121,11 @@ const createHyperlinkInstanceIndexAllocator = () => {
106
121
  let index = 0;
107
122
  return () => index++;
108
123
  };
124
+ /** Imported occurrences belong to the projection walk, not to the referenced note. */
125
+ const createNoteReferenceOccurrenceAllocator = () => {
126
+ let index = 0;
127
+ return () => `source-note:${index++}`;
128
+ };
109
129
  /**
110
130
  * Find bookmark pairs across every editable inline wrapper in a document story.
111
131
  * Each endpoint is converted at its own structural position, so a range may
@@ -232,6 +252,7 @@ function toProseDoc(document, options) {
232
252
  const theme = options?.theme ?? document.package.theme ?? null;
233
253
  const nextTextBoxGroupId = createTextBoxGroupIdFactory();
234
254
  const nextHyperlinkInstanceIndex = createHyperlinkInstanceIndexAllocator();
255
+ const nextNoteReferenceOccurrenceId = createNoteReferenceOccurrenceAllocator();
235
256
  const pairedBookmarkIds = collectPairedBookmarkIds(paragraphs);
236
257
  const conversionContext = {
237
258
  listRenderings: /* @__PURE__ */ new Map(),
@@ -239,6 +260,7 @@ function toProseDoc(document, options) {
239
260
  theme,
240
261
  nextTextBoxGroupId,
241
262
  nextHyperlinkInstanceIndex,
263
+ nextNoteReferenceOccurrenceId,
242
264
  pairedBookmarkIds,
243
265
  pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(paragraphs),
244
266
  storyRangedCommentIds: rangedCommentIds(paragraphs),
@@ -385,13 +407,7 @@ const resolveListRendering = (numPr, context) => {
385
407
  const key = `${numPr.numId}:${numPr.ilvl ?? 0}`;
386
408
  const cached = context.listRenderings.get(key);
387
409
  if (cached !== void 0) return cached;
388
- const numbering = context.numbering;
389
- const rendering = numbering === void 0 ? null : computeListRendering(numPr, numbering);
390
- const nextLevel = numbering?.getLevel(numPr.numId, (numPr.ilvl ?? 0) + 1);
391
- const resolved = {
392
- rendering,
393
- nextSlotOffset: nextLevel?.pPr?.hangingIndent === true && nextLevel.pPr.indentFirstLine !== void 0 && nextLevel.pPr.indentFirstLine < 0 ? -nextLevel.pPr.indentFirstLine : void 0
394
- };
410
+ const resolved = resolveListRenderingDefinition(numPr, context.numbering);
395
411
  context.listRenderings.set(key, resolved);
396
412
  return resolved;
397
413
  };
@@ -406,12 +422,26 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
406
422
  let runIdentityId = 0;
407
423
  const runScope = {
408
424
  nextRunIdentityId: () => runIdentityId++,
425
+ nextNoteReferenceOccurrenceId: context.nextNoteReferenceOccurrenceId,
409
426
  createMark: context.createMark
410
427
  };
428
+ const directFormatting = paragraphFormattingWithAuthoredIndentation(paragraph);
411
429
  const { attrs, effectiveFrame } = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
430
+ if (directFormatting === void 0) Reflect.deleteProperty(attrs, "_originalFormatting");
431
+ else attrs._originalFormatting = directFormatting;
412
432
  const numPr = mergeParagraphNumbering(attrs.numPrFromStyle ?? void 0, attrs.numPr ?? void 0);
413
- if (numPr?.kind === "none") Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
433
+ if (numPr?.kind === "none" || paragraph.listRendering !== void 0 && context.numbering !== void 0 && numPr === void 0) Object.assign(attrs, CLEARED_LIST_RENDERING_ATTRS);
414
434
  else if (context.numbering !== void 0 && numPr?.kind === "reference") {
435
+ Object.assign(attrs, listIndentationProvenancePatch({
436
+ direct: paragraphIndentationFromFormatting(directFormatting),
437
+ styleFormatting: attrs._styleResolvedFormatting,
438
+ numberingSource: attrs.numPrFromStyle == null ? "paragraph" : "style",
439
+ numPr: {
440
+ numId: numPr.numId,
441
+ ilvl: numPr.ilvl ?? 0
442
+ },
443
+ numbering: context.numbering
444
+ }));
415
445
  const { rendering, nextSlotOffset } = resolveListRendering(numPr, context);
416
446
  if (rendering !== null) {
417
447
  const cached = paragraph.listRendering;
@@ -444,20 +474,12 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
444
474
  const paragraphRunFormatting = resolveRunFormattingWithoutDefaults(paragraph.formatting?.runProperties, styleResolver);
445
475
  let inheritableParagraphRunFormatting;
446
476
  if (paragraphRunFormatting && !isTocParagraph && paragraph.formatting?.styleId === void 0) inheritableParagraphRunFormatting = stripParagraphMarkFormattingForBodyRuns(paragraphRunFormatting);
447
- const { baseFormatting: baseRunFormatting, baseToggleCascade: orderedToggleFormatting, defaultFormatting: ordinaryBaseWithDefaultCharacter, defaultToggleCascade: defaultCharacterStyleCascade } = resolveParagraphBodyRunFormatting({
477
+ const { baseFormatting: baseRunFormatting, baseToggleCascade: orderedToggleFormatting, defaultFormatting: ordinaryBaseWithDefaultCharacter, defaultToggleCascade: defaultCharacterStyleCascade, inheritedFormatting: defaultRunFormatting, inheritedToggleCascade: defaultToggleCascade } = resolveParagraphInheritedRunFormatting({
448
478
  styleId: paragraph.formatting?.styleId,
449
479
  tableRunFormatting: extraRunFormatting,
450
- styleResolver
480
+ styleResolver,
481
+ paragraphMarkFormatting: inheritableParagraphRunFormatting
451
482
  });
452
- const ordinaryDefaultRunFormatting = mergeTextFormatting(ordinaryBaseWithDefaultCharacter, inheritableParagraphRunFormatting);
453
- const defaultToggleCascade = cascadeStyleTextFormatting([{
454
- cascade: defaultCharacterStyleCascade,
455
- type: "carried"
456
- }, {
457
- formatting: inheritableParagraphRunFormatting,
458
- type: "direct"
459
- }], { ordinaryFormatting: ordinaryDefaultRunFormatting });
460
- const defaultRunFormatting = defaultToggleCascade.formatting;
461
483
  if (extraRunFormatting !== void 0 || paragraph.content.length > 0) {
462
484
  if (extraRunFormatting !== void 0) attrs._tableRunFormatting = extraRunFormatting;
463
485
  if (defaultRunFormatting) attrs.defaultTextFormatting = defaultRunFormatting;
@@ -476,7 +498,7 @@ function convertParagraph(paragraph, styleResolver, context, extraRunFormatting,
476
498
  ...!hasCharacterStyle ? { implicitCharacterStyleApplied: true } : {},
477
499
  toggleCascade: inheritedToggleCascade
478
500
  };
479
- if (!(hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0)) return {
501
+ if (!isParagraphMarkSuppressionEligible(formatting)) return {
480
502
  formatting: defaultRunFormatting,
481
503
  implicitCharacterStyleApplied: true,
482
504
  toggleCascade: defaultToggleCascade
@@ -643,7 +665,7 @@ function applyCommentMarks(nodes, commentIds) {
643
665
  if (!commentMarkType) return nodes;
644
666
  const commentMarks = [...commentIds].toSorted((left, right) => left - right).map((commentId) => commentMarkType.create({ commentId }));
645
667
  return nodes.map((node) => {
646
- if (!node.isText && (!node.isInline || !node.type.allowsMarkType(commentMarkType))) return node;
668
+ if (!node.isInline) return node;
647
669
  let marks = node.marks;
648
670
  for (const commentMark of commentMarks) marks = commentMark.addToSet(marks);
649
671
  return node.mark(marks);
@@ -772,7 +794,7 @@ function convertTrackedChange(change, markType, nextHyperlinkInstanceIndex, runS
772
794
  return nodes.map((node) => withTrackedRunMark(node, mark, ancestor));
773
795
  }
774
796
  function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay) {
775
- const formatting = paragraph.formatting;
797
+ const formatting = paragraphFormattingWithAuthoredIndentation(paragraph);
776
798
  const styleId = formatting?.styleId;
777
799
  const styleName = styleId ? styleResolver?.getStyle(styleId)?.name : void 0;
778
800
  const tableOfContentsLevel = tableOfContentsStyleLevel({
@@ -1290,6 +1312,7 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
1290
1312
  function standaloneTableCellToProseMirror(cell, nodeType) {
1291
1313
  const nextTextBoxGroupId = createTextBoxGroupIdFactory();
1292
1314
  const nextHyperlinkInstanceIndex = createHyperlinkInstanceIndexAllocator();
1315
+ const nextNoteReferenceOccurrenceId = createNoteReferenceOccurrenceAllocator();
1293
1316
  const pageBreakRunSourceDescendants = buildPageBreakRunSourceDescendantIndex(cell.content);
1294
1317
  reportSourceContainerPageBreakRun(cell.content, "table-cell", pageBreakRunSourceDescendants, noPageBreakProjectionWarning);
1295
1318
  return convertTableCell({
@@ -1301,6 +1324,7 @@ function standaloneTableCellToProseMirror(cell, nodeType) {
1301
1324
  numbering: void 0,
1302
1325
  nextTextBoxGroupId,
1303
1326
  nextHyperlinkInstanceIndex,
1327
+ nextNoteReferenceOccurrenceId,
1304
1328
  pairedBookmarkIds: collectPairedBookmarkIds(cell.content),
1305
1329
  pageBreakRunSourceDescendants,
1306
1330
  storyRangedCommentIds: rangedCommentIds(cell.content),
@@ -1324,14 +1348,56 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1324
1348
  let fieldFormatting;
1325
1349
  let fieldPropertyChanges;
1326
1350
  const inlineNodes = [];
1327
- const hasStructuredSourceContent = fieldResultHasPageBreakContent(field) || field.type === "simpleField" && field.content.some((content) => content.type === "hyperlink" || content.type === "preservedInline" || content.type === "inlineWrapper");
1351
+ const hasStructuredSourceContent = fieldResultHasPageBreakContent(field) || field.type === "simpleField" && field.content.some((content) => content.type === "hyperlink" || content.type === "preservedInline" || content.type === "inlineWrapper" || content.type === "insertion" || content.type === "deletion" || content.type === "moveFrom" || content.type === "moveTo");
1328
1352
  const appendRun = (run, into) => {
1329
1353
  for (const content of run.content) if (content.type === "text") displayText += content.text;
1330
1354
  fieldFormatting ??= run.formatting;
1331
1355
  fieldPropertyChanges ??= run.propertyChanges;
1332
- if (!hasStructuredSourceContent) return;
1356
+ if (field.type !== "simpleField" && !hasStructuredSourceContent) return;
1333
1357
  into.push(...convertRun(run, getInheritedRunFormatting(run.formatting, field.fieldType), runScope, styleResolver, textBoxAnchors));
1334
1358
  };
1359
+ const collectDisplay = (items) => {
1360
+ for (const item of items) switch (item.type) {
1361
+ case "run":
1362
+ for (const child of item.content) if (child.type === "text") displayText += child.text;
1363
+ fieldFormatting ??= item.formatting;
1364
+ fieldPropertyChanges ??= item.propertyChanges;
1365
+ break;
1366
+ case "hyperlink":
1367
+ collectDisplay(item.children);
1368
+ break;
1369
+ case "inlineWrapper":
1370
+ case "inlineSdt":
1371
+ case "insertion":
1372
+ case "deletion":
1373
+ case "moveFrom":
1374
+ case "moveTo":
1375
+ collectDisplay(item.content);
1376
+ break;
1377
+ case "simpleField":
1378
+ collectDisplay(item.content);
1379
+ break;
1380
+ case "complexField":
1381
+ collectDisplay(item.fieldResult);
1382
+ break;
1383
+ case "preservedInline":
1384
+ displayText += item.text;
1385
+ break;
1386
+ case "mathEquation":
1387
+ displayText += item.plainText ?? "";
1388
+ break;
1389
+ case "bookmarkStart":
1390
+ case "bookmarkEnd":
1391
+ case "commentRangeStart":
1392
+ case "commentRangeEnd":
1393
+ case "commentReference":
1394
+ case "moveFromRangeStart":
1395
+ case "moveFromRangeEnd":
1396
+ case "moveToRangeStart":
1397
+ case "moveToRangeEnd": break;
1398
+ default: panic(`Unsupported field display content: ${JSON.stringify(item)}`);
1399
+ }
1400
+ };
1335
1401
  if (field.type === "simpleField") for (const { content, stack } of withInlineWrapperStacks(field.content)) {
1336
1402
  const itemNodes = [];
1337
1403
  switch (content.type) {
@@ -1355,6 +1421,16 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1355
1421
  runScope
1356
1422
  }));
1357
1423
  break;
1424
+ case "insertion":
1425
+ case "deletion":
1426
+ case "moveFrom":
1427
+ case "moveTo":
1428
+ collectDisplay(content.content);
1429
+ itemNodes.push(...convertTrackedChange(content, content.type === "insertion" || content.type === "moveTo" ? "insertion" : "deletion", nextHyperlinkInstanceIndex, runScope, {
1430
+ current: getInheritedRunFormatting,
1431
+ historical: getInheritedRunFormatting
1432
+ }, styleResolver, content.type === "moveFrom" || content.type === "moveTo" ? content.type : null, textBoxAnchors));
1433
+ break;
1358
1434
  default: break;
1359
1435
  }
1360
1436
  inlineNodes.push(...withInlineWrapperMark(itemNodes, stack));
@@ -1368,11 +1444,7 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1368
1444
  styleResolver,
1369
1445
  createMark: runScope.createMark
1370
1446
  });
1371
- const hasConvertedHyperlinkContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === "hyperlink"));
1372
- const hasConvertedPageBreakContent = inlineNodes.some((node) => node.type.name === "pageBreakRun");
1373
- const hasConvertedPreservedContent = inlineNodes.some((node) => node.type.name === "preservedXml");
1374
- const hasConvertedWrapperContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === INLINE_WRAPPER_MARK_NAME));
1375
- const createStructuredField = hasConvertedPageBreakContent || hasConvertedPreservedContent || hasStructuredSourceContent && (hasConvertedHyperlinkContent || hasConvertedWrapperContent);
1447
+ const createStructuredField = fieldRequiresStructuredContent(inlineNodes);
1376
1448
  const resultRuns = field.type === "simpleField" ? field.content.flatMap((content) => content.type === "run" ? [content] : []) : field.fieldResult;
1377
1449
  const emptyResultRuns = displayText === "" && resultRuns.length > 0 && (field.type === "complexField" || field.content.length === resultRuns.length) && resultRuns.every((run) => run.content.every((item) => item.type === "text" && item.text === "")) ? resultRuns : void 0;
1378
1450
  const resultPropertyChanges = emptyResultRuns ? emptyFieldRunPropertyChanges(emptyResultRuns) : fieldPropertyChanges;
@@ -1564,7 +1636,14 @@ function convertRun(run, resolvedStyleFormatting, runScope, styleResolver, textB
1564
1636
  const identity = runIdentityMark(run, runScope.nextRunIdentityId);
1565
1637
  if (identity) marks.push(identity);
1566
1638
  for (const content of run.content) {
1567
- const contentNodes = convertRunContent(content, marks, mergedFormatting, textBoxAnchors, run.formatting);
1639
+ const contentNodes = convertRunContent({
1640
+ content,
1641
+ marks,
1642
+ formatting: mergedFormatting,
1643
+ textBoxAnchors,
1644
+ authoredFormatting: run.formatting,
1645
+ nextNoteReferenceOccurrenceId: runScope.nextNoteReferenceOccurrenceId
1646
+ });
1568
1647
  nodes.push(...contentNodes);
1569
1648
  }
1570
1649
  return nodes;
@@ -1970,10 +2049,7 @@ const noteReferenceVertAlign = (vertAlign) => {
1970
2049
  * run was authored with.
1971
2050
  */
1972
2051
  const carriedRunFormatting = (formatting) => formatting && Object.keys(formatting).length > 0 ? formatting : void 0;
1973
- /**
1974
- * Convert RunContent to ProseMirror nodes
1975
- */
1976
- function convertRunContent(content, marks, formatting, textBoxAnchors, authoredFormatting) {
2052
+ function convertRunContent({ content, marks, formatting, textBoxAnchors, authoredFormatting, nextNoteReferenceOccurrenceId }) {
1977
2053
  switch (content.type) {
1978
2054
  case "noteMarker": return [schema.node("noteMarker", { kind: content.kind }).mark(marks)];
1979
2055
  case "text":
@@ -2013,6 +2089,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
2013
2089
  case "footnoteRef": {
2014
2090
  const footnoteMark = schema.mark("footnoteRef", {
2015
2091
  id: content.id.toString(),
2092
+ occurrenceId: nextNoteReferenceOccurrenceId(),
2016
2093
  noteType: "footnote",
2017
2094
  vertAlign: noteReferenceVertAlign(formatting?.vertAlign),
2018
2095
  customMarkFollows: content.customMarkFollows
@@ -2022,6 +2099,7 @@ function convertRunContent(content, marks, formatting, textBoxAnchors, authoredF
2022
2099
  case "endnoteRef": {
2023
2100
  const endnoteMark = schema.mark("footnoteRef", {
2024
2101
  id: content.id.toString(),
2102
+ occurrenceId: nextNoteReferenceOccurrenceId(),
2025
2103
  noteType: "endnote",
2026
2104
  vertAlign: noteReferenceVertAlign(formatting?.vertAlign),
2027
2105
  customMarkFollows: content.customMarkFollows
@@ -2149,6 +2227,7 @@ function convertImage({ image, rawXml, rawXmlMode, rawImageFingerprint, runForma
2149
2227
  src: image.src || "",
2150
2228
  preview: image.preview,
2151
2229
  docPrName: image.docPrName,
2230
+ pictureNames: image.pictureNames === void 0 ? void 0 : { ...image.pictureNames },
2152
2231
  alt: image.alt,
2153
2232
  title: image.title,
2154
2233
  width: widthPx,
@@ -2251,7 +2330,14 @@ function convertHyperlink(hyperlink, { getInheritedRunFormatting, styleResolver,
2251
2330
  const identity = runIdentityMark(child, runScope.nextRunIdentityId);
2252
2331
  if (identity) runMarks.push(identity);
2253
2332
  const allMarks = [...runMarks, linkMark];
2254
- for (const content of child.content) childNodes.push(...convertRunContent(content, allMarks, mergedFormatting, textBoxAnchors, child.formatting));
2333
+ for (const content of child.content) childNodes.push(...convertRunContent({
2334
+ content,
2335
+ marks: allMarks,
2336
+ formatting: mergedFormatting,
2337
+ textBoxAnchors,
2338
+ authoredFormatting: child.formatting,
2339
+ nextNoteReferenceOccurrenceId: runScope.nextNoteReferenceOccurrenceId
2340
+ }));
2255
2341
  break;
2256
2342
  }
2257
2343
  default: break;
@@ -2695,6 +2781,7 @@ function headerFooterToProseDoc(content, options) {
2695
2781
  const theme = options?.theme ?? null;
2696
2782
  const nextTextBoxGroupId = createTextBoxGroupIdFactory();
2697
2783
  const nextHyperlinkInstanceIndex = createHyperlinkInstanceIndexAllocator();
2784
+ const nextNoteReferenceOccurrenceId = createNoteReferenceOccurrenceAllocator();
2698
2785
  const pairedBookmarkIds = collectPairedBookmarkIds(content);
2699
2786
  const conversionContext = {
2700
2787
  listRenderings: /* @__PURE__ */ new Map(),
@@ -2702,6 +2789,7 @@ function headerFooterToProseDoc(content, options) {
2702
2789
  numbering: options?.numbering === void 0 ? void 0 : getCachedNumberingMap(options.numbering),
2703
2790
  nextTextBoxGroupId,
2704
2791
  nextHyperlinkInstanceIndex,
2792
+ nextNoteReferenceOccurrenceId,
2705
2793
  pairedBookmarkIds,
2706
2794
  pageBreakRunSourceDescendants: buildPageBreakRunSourceDescendantIndex(content),
2707
2795
  storyRangedCommentIds: rangedCommentIds(content),
@@ -14,12 +14,14 @@ import { CLEARED_LIST_RENDERING_ATTRS } from "../../listMarker.js";
14
14
  import { directParagraphAlignment } from "../../paragraphAlignment.js";
15
15
  import { directionIsRtl } from "../../paragraphDirection.js";
16
16
  import { directParagraphIndentation } from "../../paragraphIndentation.js";
17
+ import { recordReplacedParagraphProperties } from "../../paragraphPropertyCarry.js";
17
18
  import { directParagraphSpacing, withDirectParagraphSpacing } from "../../paragraphSpacing.js";
18
19
  import { getDocumentNumbering } from "../../plugins/documentNumbering.js";
19
20
  import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "../../plugins/documentStyleState.js";
21
+ import { SUGGESTION_META, makeRevisionInfo } from "../../plugins/suggestionMode.js";
20
22
  import { rebaseParagraphRuns } from "../../rebaseParagraphRuns.js";
21
23
  import { mintSectionProperties, parseSectionBreakType, sectionBreakTypeOf } from "../../sectionCarrier.js";
22
- import { listAttrsFromResolvedStyle, listLevelIndentAttrPatch, paragraphAttrsFromResolvedStyle } from "../../styles/resolvedStyleAttrs.js";
24
+ import { listAttrsFromResolvedStyle, listIndentationProvenancePatch, paragraphAttrsFromResolvedStyle } from "../../styles/resolvedStyleAttrs.js";
23
25
  import { createNodeExtension } from "../create.js";
24
26
  import { headingOutlineLevel, paragraphNumberingLevel, paragraphNumberingReferenceId } from "@stll/docx-core/model";
25
27
  import { Fragment } from "prosemirror-model";
@@ -263,6 +265,7 @@ const paragraphNodeSpec = {
263
265
  _emptyHyperlinks: { default: null },
264
266
  _originalFormatting: { default: null },
265
267
  _resolvedFormatting: { default: void 0 },
268
+ _styleResolvedFormatting: { default: void 0 },
266
269
  _autospacingBase: { default: null },
267
270
  _sectionProperties: { default: null },
268
271
  _propertyChanges: { default: null },
@@ -548,6 +551,7 @@ function makeApplyStyle() {
548
551
  const { $from, $to } = state.selection;
549
552
  if (!dispatch) return true;
550
553
  let tr = state.tr;
554
+ const revision = makeRevisionInfo(state);
551
555
  const seen = /* @__PURE__ */ new Set();
552
556
  state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
553
557
  if (node.type.name === "paragraph" && !seen.has(pos)) {
@@ -583,12 +587,24 @@ function makeApplyStyle() {
583
587
  numPr: null,
584
588
  numPrFromStyle: null
585
589
  });
586
- else if (directNumId !== void 0) Object.assign(newAttrs, listLevelIndentAttrPatch(restyledIndentation(styleAttrs, restyledOriginal), {
587
- numId: directNumId,
588
- ilvl: paragraphNumberingLevel(current.numPr ?? void 0) ?? 0
589
- }, resolvedAttrs.numbering ?? getDocumentNumbering(state)));
590
+ else if (directNumId !== void 0) Object.assign(newAttrs, listIndentationProvenancePatch({
591
+ direct: restyledIndentation(styleAttrs, restyledOriginal),
592
+ styleFormatting: resolvedAttrs.paragraphFormatting,
593
+ numberingSource: "paragraph",
594
+ numPr: {
595
+ numId: directNumId,
596
+ ilvl: paragraphNumberingLevel(current.numPr ?? void 0) ?? 0
597
+ },
598
+ numbering: resolvedAttrs.numbering ?? getDocumentNumbering(state)
599
+ }));
590
600
  }
591
601
  tr = tr.setNodeMarkup(pos, void 0, newAttrs);
602
+ if (revision) recordReplacedParagraphProperties({
603
+ tr,
604
+ position: pos,
605
+ replaced: node,
606
+ revision
607
+ });
592
608
  rebaseParagraphRuns({
593
609
  tr,
594
610
  position: pos,
@@ -598,6 +614,7 @@ function makeApplyStyle() {
598
614
  });
599
615
  }
600
616
  });
617
+ if (revision) tr.setMeta(SUGGESTION_META, true);
601
618
  dispatch(tr.scrollIntoView());
602
619
  return true;
603
620
  };
@@ -1,5 +1,5 @@
1
1
  import { mergeTextFormatting } from "../../../utils/textFormattingMerge.js";
2
- import { expectCharacterStyleMarkAttrs, expectRunFormattingOverrideMarkAttrs } from "../../attrs/index.js";
2
+ import { expectCharacterStyleMarkAttrs, expectParagraphAttrs, expectRunFormattingOverrideMarkAttrs } from "../../attrs/index.js";
3
3
  import { clearIndentOnBackspace } from "../../commands/clearParagraphIndent.js";
4
4
  import { keepSectionBreaksOnSurvivingMarks } from "../../commands/sectionBreak.js";
5
5
  import { getDocumentStyleResolver } from "../../plugins/documentStyleState.js";
@@ -23,27 +23,55 @@ function chainCommands(...commands) {
23
23
  return false;
24
24
  };
25
25
  }
26
- /**
27
- * Custom Enter handler: splits the block, inherits style-related attrs,
28
- * clears paragraph borders, and preserves run formatting on the new paragraph.
29
- *
30
- * splitBlock creates a new paragraph with default attrs (all null),
31
- * so we must manually copy style-related attrs from the source paragraph.
32
- * Word does NOT propagate paragraph borders (w:pBdr) on Enter.
33
- */
34
26
  const INHERITED_PARA_ATTRS = [
35
- "defaultTextFormatting",
36
- "styleId",
37
- "_tableOfContentsLevel",
38
- "lineSpacing",
39
- "lineSpacingRule",
40
- "snapToGrid",
41
- "spaceAfter",
42
- "spaceBefore",
43
- "spacingExplicit",
44
- "spacingFromDocDefaults",
45
- "spacingFromImplicitDefaultStyle",
46
- "contextualSpacing"
27
+ {
28
+ attr: "defaultTextFormatting",
29
+ formattingFields: ["runProperties"]
30
+ },
31
+ {
32
+ attr: "styleId",
33
+ formattingFields: ["styleId"]
34
+ },
35
+ {
36
+ attr: "_tableOfContentsLevel",
37
+ formattingFields: []
38
+ },
39
+ {
40
+ attr: "lineSpacing",
41
+ formattingFields: ["lineSpacing", "spacingPreservedAttributes"]
42
+ },
43
+ {
44
+ attr: "lineSpacingRule",
45
+ formattingFields: ["lineSpacingRule", "spacingPreservedAttributes"]
46
+ },
47
+ {
48
+ attr: "snapToGrid",
49
+ formattingFields: ["snapToGrid"]
50
+ },
51
+ {
52
+ attr: "spaceAfter",
53
+ formattingFields: ["spaceAfter", "spacingPreservedAttributes"]
54
+ },
55
+ {
56
+ attr: "spaceBefore",
57
+ formattingFields: ["spaceBefore", "spacingPreservedAttributes"]
58
+ },
59
+ {
60
+ attr: "spacingExplicit",
61
+ formattingFields: ["spacingExplicit"]
62
+ },
63
+ {
64
+ attr: "spacingFromDocDefaults",
65
+ formattingFields: []
66
+ },
67
+ {
68
+ attr: "spacingFromImplicitDefaultStyle",
69
+ formattingFields: []
70
+ },
71
+ {
72
+ attr: "contextualSpacing",
73
+ formattingFields: ["contextualSpacing"]
74
+ }
47
75
  ];
48
76
  /** Style formatting needed when the caret has no marks of its own. */
49
77
  const STYLE_MARK_NAMES = /* @__PURE__ */ new Set([
@@ -142,10 +170,31 @@ const splitBlockClearBorders = (state, dispatch, view) => {
142
170
  }
143
171
  const newAttrs = { ...newPara.attrs };
144
172
  let attrsChanged = false;
145
- if (sourcePara) for (const key of INHERITED_PARA_ATTRS) {
146
- const srcVal = sourcePara.attrs[key];
147
- if (srcVal !== null && newAttrs[key] === null) {
148
- newAttrs[key] = srcVal;
173
+ if (sourcePara) {
174
+ const sourceAttrs = expectParagraphAttrs(sourcePara);
175
+ const addedAttrs = expectParagraphAttrs(newPara);
176
+ const originalFormatting = { ...addedAttrs._originalFormatting };
177
+ const resolvedFormatting = { ...addedAttrs._resolvedFormatting };
178
+ for (const { attr, formattingFields } of INHERITED_PARA_ATTRS) {
179
+ const srcVal = sourceAttrs[attr];
180
+ if (srcVal !== null && newAttrs[attr] === null) {
181
+ newAttrs[attr] = srcVal;
182
+ attrsChanged = true;
183
+ }
184
+ if (newAttrs[attr] !== srcVal) continue;
185
+ for (const field of formattingFields) {
186
+ const original = sourceAttrs._originalFormatting?.[field];
187
+ if (original !== void 0) Reflect.set(originalFormatting, field, original);
188
+ const resolved = sourceAttrs._resolvedFormatting?.[field];
189
+ if (resolved !== void 0) Reflect.set(resolvedFormatting, field, resolved);
190
+ }
191
+ }
192
+ if (Object.keys(originalFormatting).length > 0) {
193
+ newAttrs["_originalFormatting"] = originalFormatting;
194
+ attrsChanged = true;
195
+ }
196
+ if (Object.keys(resolvedFormatting).length > 0) {
197
+ newAttrs["_resolvedFormatting"] = resolvedFormatting;
149
198
  attrsChanged = true;
150
199
  }
151
200
  }
@@ -1,4 +1,5 @@
1
1
  import { expectFootnoteRefMarkAttrs } from "../../attrs/index.js";
2
+ import { mintNoteReferenceOccurrenceId, noteReferenceOccurrencePlugin } from "../../noteReferenceOccurrences.js";
2
3
  import { suggestRangeDeletion, suggestionModeKey } from "../../plugins/suggestionMode.js";
3
4
  import { createMarkExtension } from "../create.js";
4
5
  import { expandNoteReferenceDeletionRange, noteReferenceRanges } from "./noteReferenceDeletion.js";
@@ -9,7 +10,9 @@ import { panic } from "better-result";
9
10
  *
10
11
  * Provides footnoteRef mark + insert/delete commands for footnotes and endnotes.
11
12
  */
13
+ const NOTE_REFERENCE_PARSE_PRIORITY = 60;
12
14
  const noteRefAttrsFromDom = (dom, noteType, vertAlign) => ({
15
+ occurrenceId: dom.dataset["noteOccurrence"] ?? mintNoteReferenceOccurrenceId(),
13
16
  id: dom.dataset["id"] ?? "",
14
17
  noteType: dom.dataset["noteType"] ?? noteType,
15
18
  ...vertAlign ? { vertAlign } : {}
@@ -21,6 +24,7 @@ const FootnoteRefExtension = createMarkExtension({
21
24
  inclusive: false,
22
25
  attrs: {
23
26
  id: {},
27
+ occurrenceId: {},
24
28
  noteType: { default: "footnote" },
25
29
  vertAlign: { default: null },
26
30
  customMarkFollows: { default: null }
@@ -28,18 +32,22 @@ const FootnoteRefExtension = createMarkExtension({
28
32
  parseDOM: [
29
33
  {
30
34
  tag: "sup.docx-footnote-ref",
35
+ priority: NOTE_REFERENCE_PARSE_PRIORITY,
31
36
  getAttrs: (dom) => noteRefAttrsFromDom(dom, "footnote", "superscript")
32
37
  },
33
38
  {
34
39
  tag: "sup.docx-endnote-ref",
40
+ priority: NOTE_REFERENCE_PARSE_PRIORITY,
35
41
  getAttrs: (dom) => noteRefAttrsFromDom(dom, "endnote", "superscript")
36
42
  },
37
43
  {
38
44
  tag: "span.docx-footnote-ref",
45
+ priority: NOTE_REFERENCE_PARSE_PRIORITY,
39
46
  getAttrs: (dom) => noteRefAttrsFromDom(dom, "footnote", "baseline")
40
47
  },
41
48
  {
42
49
  tag: "span.docx-endnote-ref",
50
+ priority: NOTE_REFERENCE_PARSE_PRIORITY,
43
51
  getAttrs: (dom) => noteRefAttrsFromDom(dom, "endnote", "baseline")
44
52
  }
45
53
  ],
@@ -53,6 +61,7 @@ const FootnoteRefExtension = createMarkExtension({
53
61
  {
54
62
  class: `docx-${noteType}-ref ${isSuperscript ? "docx-note-ref-superscript" : "docx-note-ref-baseline"}`,
55
63
  "data-id": id,
64
+ "data-note-occurrence": attrs.occurrenceId,
56
65
  "data-note-type": noteType
57
66
  },
58
67
  0
@@ -76,6 +85,7 @@ const FootnoteRefExtension = createMarkExtension({
76
85
  if (!footnoteRefType) panic("Missing mark type: footnoteRef");
77
86
  const mark = footnoteRefType.create({
78
87
  id: String(id),
88
+ occurrenceId: mintNoteReferenceOccurrenceId(),
79
89
  noteType,
80
90
  vertAlign: "superscript"
81
91
  });
@@ -100,6 +110,7 @@ const FootnoteRefExtension = createMarkExtension({
100
110
  return true;
101
111
  };
102
112
  return {
113
+ plugins: [noteReferenceOccurrencePlugin()],
103
114
  keyboardShortcuts: {
104
115
  Backspace: deleteWholeNoteReference("backward"),
105
116
  Delete: deleteWholeNoteReference("forward")