@stll/folio-core 0.55.0 → 0.57.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 (225) hide show
  1. package/dist/ai-edits/apply.js +214 -52
  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/headless.js +2 -2
  5. package/dist/ai-edits/table-row-column-mutations.js +17 -3
  6. package/dist/ai-edits/types.d.ts +7 -1
  7. package/dist/ai-suggestions/apply.js +20 -1
  8. package/dist/compare/compare.js +1 -0
  9. package/dist/compare/inline-atoms.js +40 -16
  10. package/dist/compare/inline-provenance.js +12 -5
  11. package/dist/compare/reproducible-package.d.ts +0 -17
  12. package/dist/compare/reproducible-package.js +12 -18
  13. package/dist/compat/eigenpal.d.ts +2 -1
  14. package/dist/compat/eigenpal.js +2 -1
  15. package/dist/controller/canonicalClipboard.d.ts +23 -0
  16. package/dist/controller/canonicalClipboard.js +482 -0
  17. package/dist/controller/canonicalClipboardResources.d.ts +21 -0
  18. package/dist/controller/canonicalClipboardResources.js +382 -0
  19. package/dist/controller/canonicalComments.d.ts +41 -0
  20. package/dist/controller/canonicalComments.js +152 -0
  21. package/dist/controller/canonicalComposition.d.ts +24 -3
  22. package/dist/controller/canonicalComposition.js +208 -48
  23. package/dist/controller/canonicalInlineProjection.d.ts +118 -0
  24. package/dist/controller/canonicalInlineProjection.js +476 -0
  25. package/dist/controller/canonicalInput.d.ts +13 -4
  26. package/dist/controller/canonicalInput.js +62 -14
  27. package/dist/controller/canonicalInputTimer.d.ts +16 -0
  28. package/dist/controller/canonicalInputTimer.js +34 -0
  29. package/dist/controller/canonicalPublicOperations.d.ts +48 -0
  30. package/dist/controller/canonicalPublicOperations.js +648 -0
  31. package/dist/controller/canonicalSelection.d.ts +18 -0
  32. package/dist/controller/canonicalSelection.js +32 -0
  33. package/dist/controller/canonicalSession.d.ts +27 -6
  34. package/dist/controller/canonicalSession.js +298 -116
  35. package/dist/controller/canonicalStoryEditor.d.ts +7 -3
  36. package/dist/controller/canonicalStoryEditor.js +27 -2
  37. package/dist/controller/canonicalStructure.js +57 -4
  38. package/dist/controller/canonicalTocSelection.d.ts +11 -0
  39. package/dist/controller/canonicalTocSelection.js +43 -0
  40. package/dist/controller/folioEditor.d.ts +2 -9
  41. package/dist/controller/folioEditor.js +18 -4
  42. package/dist/controller/headerFooterEditorManager.d.ts +2 -1
  43. package/dist/controller/headerFooterEditorManager.js +26 -11
  44. package/dist/controller/hiddenEditorApi.d.ts +24 -3
  45. package/dist/controller/hiddenEditorApi.js +8 -0
  46. package/dist/controller/hiddenEditorManager.d.ts +5 -1
  47. package/dist/controller/hiddenEditorManager.js +378 -43
  48. package/dist/controller/noteEditorManager.d.ts +2 -1
  49. package/dist/controller/noteEditorManager.js +29 -13
  50. package/dist/document-operations.d.ts +8 -1
  51. package/dist/document-operations.js +6 -4
  52. package/dist/docx/blockPlainText.d.ts +1 -1
  53. package/dist/docx/blockPlainText.js +11 -3
  54. package/dist/docx/builtInStyles.js +13 -6
  55. package/dist/docx/canonicalResourceSave.d.ts +16 -0
  56. package/dist/docx/canonicalResourceSave.js +27 -0
  57. package/dist/docx/canonicalSave.d.ts +29 -0
  58. package/dist/docx/canonicalSave.js +101 -0
  59. package/dist/docx/canonicalStoryRepack.d.ts +1 -1
  60. package/dist/docx/canonicalStoryRepack.js +38 -5
  61. package/dist/docx/containerChildren.gen.d.ts +3 -1
  62. package/dist/docx/containerChildren.gen.js +33 -1
  63. package/dist/docx/documentParser.d.ts +1 -13
  64. package/dist/docx/documentParser.js +1 -47
  65. package/dist/docx/ensureParaIds.js +10 -4
  66. package/dist/docx/fieldParser.js +14 -2
  67. package/dist/docx/footnoteParser.d.ts +1 -11
  68. package/dist/docx/footnoteParser.js +1 -16
  69. package/dist/docx/headerFooterParser.d.ts +1 -9
  70. package/dist/docx/headerFooterParser.js +1 -12
  71. package/dist/docx/headerFooterVerbatim.d.ts +26 -1
  72. package/dist/docx/headerFooterVerbatim.js +81 -3
  73. package/dist/docx/hyperlinkParser.d.ts +1 -1
  74. package/dist/docx/hyperlinkParser.js +20 -1
  75. package/dist/docx/imageParser.d.ts +13 -1
  76. package/dist/docx/imageParser.js +20 -11
  77. package/dist/docx/inlineWrapperContent.d.ts +4 -4
  78. package/dist/docx/inlineWrapperContent.js +4 -4
  79. package/dist/docx/linkedSdtPreservation.d.ts +10 -0
  80. package/dist/docx/linkedSdtPreservation.js +37 -0
  81. package/dist/docx/metadataPrivacy.js +6 -1
  82. package/dist/docx/packageParts.js +9 -3
  83. package/dist/docx/paragraphParser.js +88 -67
  84. package/dist/docx/paragraphPropertySource.d.ts +22 -1
  85. package/dist/docx/paragraphPropertySource.js +109 -2
  86. package/dist/docx/parser.js +2 -1
  87. package/dist/docx/preservedRunContent.js +2 -1
  88. package/dist/docx/relsParser.js +26 -2
  89. package/dist/docx/removeHeaderFooterParts.js +17 -6
  90. package/dist/docx/rezip.d.ts +49 -5
  91. package/dist/docx/rezip.js +754 -235
  92. package/dist/docx/saveDiagnostics.d.ts +11 -0
  93. package/dist/docx/selectiveSave.d.ts +2 -1
  94. package/dist/docx/selectiveSave.js +42 -11
  95. package/dist/docx/selectiveXmlPatch.js +7 -5
  96. package/dist/docx/serializer/commentSerializer.d.ts +4 -1
  97. package/dist/docx/serializer/commentSerializer.js +7 -3
  98. package/dist/docx/serializer/documentSerializer.d.ts +9 -2
  99. package/dist/docx/serializer/documentSerializer.js +29 -10
  100. package/dist/docx/serializer/paragraphSerializer.js +207 -94
  101. package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
  102. package/dist/docx/server/materializeYjsDocx.js +14 -6
  103. package/dist/docx/server/migrateYjsAttrSchema.js +17 -5
  104. package/dist/docx/storyBlockReplay.d.ts +21 -1
  105. package/dist/docx/storyBlockReplay.js +113 -9
  106. package/dist/docx/storyPlainText.d.ts +20 -0
  107. package/dist/docx/storyPlainText.js +23 -0
  108. package/dist/docx/structuralXmlPatch.js +10 -22
  109. package/dist/docx/styleParser.d.ts +5 -1
  110. package/dist/docx/styleParser.js +1 -1
  111. package/dist/docx/tableParser.d.ts +1 -8
  112. package/dist/docx/tableParser.js +1 -28
  113. package/dist/docx/textBoxParser.d.ts +1 -5
  114. package/dist/docx/textBoxParser.js +1 -20
  115. package/dist/docx/unzip.js +6 -1
  116. package/dist/i18n/messages/ar.gen.js +4 -0
  117. package/dist/i18n/messages/catalogs.gen.d.ts +68 -0
  118. package/dist/i18n/messages/catalogs.gen.js +68 -0
  119. package/dist/i18n/messages/cs.gen.js +4 -0
  120. package/dist/i18n/messages/de.gen.js +4 -0
  121. package/dist/i18n/messages/en.gen.js +4 -0
  122. package/dist/i18n/messages/es.gen.js +4 -0
  123. package/dist/i18n/messages/et.gen.js +4 -0
  124. package/dist/i18n/messages/fr.gen.js +4 -0
  125. package/dist/i18n/messages/he.gen.js +4 -0
  126. package/dist/i18n/messages/hi.gen.js +4 -0
  127. package/dist/i18n/messages/hu.gen.js +4 -0
  128. package/dist/i18n/messages/lt.gen.js +4 -0
  129. package/dist/i18n/messages/lv.gen.js +4 -0
  130. package/dist/i18n/messages/messages.gen.d.ts +4 -0
  131. package/dist/i18n/messages/pl.gen.js +4 -0
  132. package/dist/i18n/messages/pt-BR.gen.js +4 -0
  133. package/dist/i18n/messages/sk.gen.js +4 -0
  134. package/dist/i18n/messages/tr.gen.js +4 -0
  135. package/dist/i18n/messages/zh-CN.gen.js +4 -0
  136. package/dist/index.d.ts +2 -1
  137. package/dist/index.js +2 -1
  138. package/dist/internal/acceptedBlockProjection.d.ts +12 -0
  139. package/dist/internal/acceptedBlockProjection.js +45 -0
  140. package/dist/internal/revisionResolutionInline.js +25 -3
  141. package/dist/managers/DocumentLoaderManager.js +2 -1
  142. package/dist/markdown/escape.d.ts +3 -1
  143. package/dist/markdown/escape.js +9 -2
  144. package/dist/markdown/renderBlock.js +5 -120
  145. package/dist/markdown/renderParagraph.js +4 -2
  146. package/dist/markdown/renderRuns.d.ts +7 -1
  147. package/dist/markdown/renderRuns.js +33 -24
  148. package/dist/panel-layout.d.ts +11 -9
  149. package/dist/panel-layout.js +13 -9
  150. package/dist/prosemirror/addTrackedDeletionMark.d.ts +18 -0
  151. package/dist/prosemirror/addTrackedDeletionMark.js +87 -0
  152. package/dist/prosemirror/attrs/index.js +5 -0
  153. package/dist/prosemirror/canonicalCommands.d.ts +28 -4
  154. package/dist/prosemirror/canonicalCommands.js +11 -4
  155. package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
  156. package/dist/prosemirror/canonicalSelectionRange.js +15 -0
  157. package/dist/prosemirror/clipboardIntent.d.ts +7 -0
  158. package/dist/prosemirror/clipboardIntent.js +9 -0
  159. package/dist/prosemirror/commands/comments.js +60 -35
  160. package/dist/prosemirror/commands/pageBreak.js +2 -2
  161. package/dist/prosemirror/commands/pastePlainText.js +2 -1
  162. package/dist/prosemirror/commands/propertyChangeScope.js +3 -6
  163. package/dist/prosemirror/commands/resolveParagraphProperties.js +22 -13
  164. package/dist/prosemirror/commentOps.js +15 -1
  165. package/dist/prosemirror/conversion/fromProseDoc.js +22 -3
  166. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
  167. package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
  168. package/dist/prosemirror/conversion/toProseDoc.d.ts +7 -1
  169. package/dist/prosemirror/conversion/toProseDoc.js +124 -22
  170. package/dist/prosemirror/extensions/core/ParagraphExtension.js +61 -35
  171. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +74 -25
  172. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +11 -0
  173. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +65 -29
  174. package/dist/prosemirror/extensions/marks/markUtils.js +11 -8
  175. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +5 -2
  176. package/dist/prosemirror/fieldRepresentation.d.ts +8 -0
  177. package/dist/prosemirror/fieldRepresentation.js +18 -0
  178. package/dist/prosemirror/hyperlinkRemoval.d.ts +13 -1
  179. package/dist/prosemirror/hyperlinkRemoval.js +28 -9
  180. package/dist/prosemirror/insertOperations.js +2 -1
  181. package/dist/prosemirror/listNumbering.js +11 -5
  182. package/dist/prosemirror/noteReferenceOccurrenceId.d.ts +5 -0
  183. package/dist/prosemirror/noteReferenceOccurrenceId.js +5 -0
  184. package/dist/prosemirror/noteReferenceOccurrences.d.ts +21 -0
  185. package/dist/prosemirror/noteReferenceOccurrences.js +185 -0
  186. package/dist/prosemirror/noteReferenceReview.js +14 -1
  187. package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
  188. package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
  189. package/dist/prosemirror/plugins/documentStyles.d.ts +4 -1
  190. package/dist/prosemirror/plugins/documentStyles.js +17 -10
  191. package/dist/prosemirror/plugins/suggestionMode.js +48 -48
  192. package/dist/prosemirror/preservedXmlReview.d.ts +6 -0
  193. package/dist/prosemirror/preservedXmlReview.js +35 -0
  194. package/dist/prosemirror/runFormattingFromMarks.js +2 -2
  195. package/dist/prosemirror/runFormattingReconciliation.js +5 -4
  196. package/dist/prosemirror/runPropertyChangeResolution.d.ts +8 -1
  197. package/dist/prosemirror/runPropertyChangeResolution.js +24 -2
  198. package/dist/prosemirror/runStyleFormatting.d.ts +3 -1
  199. package/dist/prosemirror/runStyleFormatting.js +3 -1
  200. package/dist/prosemirror/schema/marks.d.ts +1 -0
  201. package/dist/prosemirror/schema/nodes.d.ts +2 -0
  202. package/dist/prosemirror/styles/paragraphStyleCascade.js +4 -1
  203. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +15 -15
  204. package/dist/prosemirror/styles/resolvedStyleAttrs.js +69 -28
  205. package/dist/prosemirror/textInput.d.ts +5 -1
  206. package/dist/prosemirror/textInput.js +3 -3
  207. package/dist/prosemirror/trackedRevisionPath.d.ts +5 -1
  208. package/dist/prosemirror/trackedRevisionPath.js +39 -1
  209. package/dist/prosemirror/validation.js +3 -5
  210. package/dist/prosemirror/yjsDocumentMetadata.d.ts +9 -3
  211. package/dist/prosemirror/yjsDocumentMetadata.js +37 -8
  212. package/dist/types/canonicalCapabilities.d.ts +201 -0
  213. package/dist/types/canonicalCapabilities.js +198 -0
  214. package/dist/types/canonicalComments.d.ts +51 -0
  215. package/dist/types/canonicalComments.js +0 -0
  216. package/dist/types/canonicalSave.d.ts +11 -0
  217. package/dist/types/canonicalSave.js +0 -0
  218. package/dist/types/canonicalSections.d.ts +12 -0
  219. package/dist/types/canonicalSections.js +0 -0
  220. package/dist/types/docxSerialization.d.ts +14 -0
  221. package/dist/types/docxSerialization.js +7 -0
  222. package/dist/utils/headingCollector.js +45 -4
  223. package/dist/utils/outlineDepth.d.ts +9 -0
  224. package/dist/utils/outlineDepth.js +9 -0
  225. package/package.json +4 -4
@@ -1,5 +1,6 @@
1
+ import { runFormattingInlineAtomDisposition } from "./runFormattingInlineCarriers.js";
1
2
  import { RUN_FORMATTING_MARK_NAMES } from "./runFormattingMarkNames.js";
2
- import { reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
3
+ import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
3
4
  //#region src/prosemirror/runPropertyChangeResolution.ts
4
5
  /**
5
6
  * Rebuild the pre-change run marks against the paragraph's live style cascade.
@@ -14,5 +15,26 @@ const reconstructRejectedRunFormattingMarks = ({ node, paragraphContext, previou
14
15
  ...styleResolver !== void 0 ? { styleResolver } : {}
15
16
  }).filter(({ type }) => RUN_FORMATTING_MARK_NAMES.has(type.name));
16
17
  };
18
+ /** Restored deletions inherit the live paragraph cascade without authoring their historical visuals. */
19
+ const restoreHistoricalRunFormatting = ({ node, paragraphContext, styleResolver }) => {
20
+ const disposition = runFormattingInlineAtomDisposition(node);
21
+ if (disposition === null || disposition === "not-a-run") return node.marks;
22
+ if (paragraphContext.paragraphMarkFormatting === void 0) return node.marks;
23
+ return reconcileRunFormattingMarks({
24
+ authoredFormatting: readAuthoredRunFormatting({
25
+ context: {
26
+ baseParagraphFormatting: paragraphContext.baseParagraphFormatting,
27
+ paragraphFormatting: paragraphContext.baseParagraphFormatting,
28
+ paragraphMarkFormatting: void 0,
29
+ paragraphMarkPrecedesStyle: false
30
+ },
31
+ marks: node.marks,
32
+ ...styleResolver !== void 0 ? { styleResolver } : {}
33
+ }),
34
+ context: paragraphContext,
35
+ node,
36
+ ...styleResolver !== void 0 ? { styleResolver } : {}
37
+ });
38
+ };
17
39
  //#endregion
18
- export { reconstructRejectedRunFormattingMarks };
40
+ export { reconstructRejectedRunFormattingMarks, restoreHistoricalRunFormatting };
@@ -5,6 +5,8 @@ import { cascadeStyleTextFormatting } from "./styles/styleToggleCascade.js";
5
5
  import { Mark, Node } from "prosemirror-model";
6
6
  //#region src/prosemirror/runStyleFormatting.d.ts
7
7
  declare const hasDirectRunFormatting: (formatting: document_d_exports.TextFormatting | undefined) => boolean;
8
+ /** A stated run property or character style establishes paragraph-mark suppression. */
9
+ declare const isParagraphMarkSuppressionEligible: (formatting: document_d_exports.TextFormatting | undefined) => boolean;
8
10
  declare const stripParagraphMarkOnlyFormatting: (formatting: document_d_exports.TextFormatting) => document_d_exports.TextFormatting | undefined;
9
11
  declare const stripParagraphMarkFormattingForBodyRuns: (formatting: document_d_exports.TextFormatting) => document_d_exports.TextFormatting | undefined;
10
12
  type SuppressParagraphMarkFormattingOptions = {
@@ -66,4 +68,4 @@ type ResolveEffectiveRunStyleFormattingOptions = {
66
68
  /** Resolve the non-direct run cascade from shared document styles and the current paragraph. */
67
69
  declare const resolveEffectiveRunStyleFormatting: ({ marks, paragraphFormatting, styleResolver }: ResolveEffectiveRunStyleFormattingOptions) => document_d_exports.TextFormatting | undefined;
68
70
  //#endregion
69
- export { ParagraphRunStyleContext, RunStyleResolver, getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
71
+ export { ParagraphRunStyleContext, RunStyleResolver, getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
@@ -20,6 +20,8 @@ const hasDirectRunFormatting = (formatting) => {
20
20
  if (!formatting) return false;
21
21
  return Object.entries(formatting).some(([property, value]) => property !== "styleId" && value !== void 0);
22
22
  };
23
+ /** A stated run property or character style establishes paragraph-mark suppression. */
24
+ const isParagraphMarkSuppressionEligible = (formatting) => hasDirectRunFormatting(formatting) || formatting?.styleId !== void 0;
23
25
  const stripParagraphMarkOnlyFormatting = (formatting) => {
24
26
  const { allCaps: _allCaps, highlight: _highlight, shading: _shading, smallCaps: _smallCaps, vertAlign: _vertAlign, preserved: _preserved, ...formattingForBody } = formatting;
25
27
  return Object.keys(formattingForBody).length > 0 ? formattingForBody : void 0;
@@ -182,4 +184,4 @@ const resolveEffectiveRunStyleFormatting = ({ marks, paragraphFormatting, styleR
182
184
  });
183
185
  };
184
186
  //#endregion
185
- export { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
187
+ export { getParagraphMarkSuppressionOverrides, hasDirectRunFormatting, isParagraphMarkSuppressionEligible, nearestParagraphRunStyleContext, paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting, resolveParagraphBodyRunFormatting, stripParagraphMarkFormattingForBodyRuns, stripParagraphMarkOnlyFormatting, suppressParagraphMarkFormatting };
@@ -78,6 +78,7 @@ type TextEffectAttrs = {
78
78
  effect: Exclude<document_d_exports.TextEffect, "none">;
79
79
  };
80
80
  type FootnoteRefAttrs = {
81
+ occurrenceId: string;
81
82
  id: string | number;
82
83
  noteType?: "footnote" | "endnote";
83
84
  vertAlign?: "baseline" | "superscript";
@@ -272,6 +272,8 @@ type ParagraphAttrs = {
272
272
  * paragraph. `TableCellAttrs._resolvedBorders` is the same device.
273
273
  */
274
274
  _resolvedFormatting?: document_d_exports.ParagraphFormatting;
275
+ /** Style-only inheritance baseline, before numbering-level indentation. PM-only. */
276
+ _styleResolvedFormatting?: document_d_exports.ParagraphFormatting;
275
277
  /** Import-effective spacing baseline for HTML auto-spacing detection.
276
278
  * PM-only; never serialized back into DOCX formatting. */
277
279
  _autospacingBase?: {
@@ -59,7 +59,10 @@ function paragraphStyleCascadeAttrs({ styleId, formatting, styleResolver, tableP
59
59
  };
60
60
  const stylePpr = styleResolver.resolveParagraphStyleInTable(styleId, tableParagraphOverlay).paragraphFormatting;
61
61
  const resolvedFormatting = styleResolvedParagraphFormatting(stylePpr);
62
- if (resolvedFormatting) attrs._resolvedFormatting = resolvedFormatting;
62
+ if (resolvedFormatting) {
63
+ attrs._resolvedFormatting = resolvedFormatting;
64
+ attrs._styleResolvedFormatting = resolvedFormatting;
65
+ }
63
66
  set("alignment", formatting?.alignment ?? stylePpr?.alignment);
64
67
  set("alignmentFromStyle", stylePpr?.alignment);
65
68
  set("spaceBefore", formatting?.spaceBefore ?? stylePpr?.spaceBefore);
@@ -1,3 +1,4 @@
1
+ import { document_d_exports } from "../../types/document.js";
1
2
  import { ParagraphAttrs, ParagraphAttrsPatch } from "../schema/nodes.js";
2
3
  import { ResolvedParagraphStyle } from "./styleResolver.js";
3
4
  import { NumberingMap } from "../../docx/numberingParser.js";
@@ -38,17 +39,18 @@ declare function listAttrsFromNumbering(numPr: {
38
39
  numId: number;
39
40
  ilvl: number;
40
41
  }, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
41
- /**
42
- * The numbering level's indentation a directly numbered paragraph reads as its
43
- * own where it states none: the load path folds the level's `w:ind` into the
44
- * paragraph (a direct `w:ind` wins per group, left vs first line/hanging), so
45
- * a paragraph a command numbers carries it too, and the save writes it where a
46
- * reopen reads it back.
47
- */
48
- declare function listLevelIndentAttrPatch(stated: DirectParagraphIndentation | undefined, numPr: {
49
- numId: number;
50
- ilvl: number;
51
- }, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
42
+ type ListIndentationProvenanceOptions = {
43
+ direct: DirectParagraphIndentation | undefined;
44
+ styleFormatting: document_d_exports.ParagraphFormatting | undefined;
45
+ numberingSource: "style" | "paragraph";
46
+ numPr: {
47
+ numId: number;
48
+ ilvl: number;
49
+ } | undefined;
50
+ numbering: NumberingMap | null | undefined;
51
+ };
52
+ /** Project effective indentation and both inheritance layers together. */
53
+ declare function listIndentationProvenancePatch({ direct, styleFormatting, numberingSource, numPr, numbering }: ListIndentationProvenanceOptions): ParagraphAttrsPatch;
52
54
  /**
53
55
  * The indentation a paragraph leaving its list keeps: the level's indentation
54
56
  * it only read from its numbering goes with the numbering, back to what its
@@ -57,11 +59,9 @@ declare function listLevelIndentAttrPatch(stated: DirectParagraphIndentation | u
57
59
  */
58
60
  declare function listLevelIndentRemovalPatch(attrs: Readonly<ParagraphAttrs>, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
59
61
  /** Recompute every level-dependent attr when a paragraph changes list level. */
60
- declare function listLevelAttrPatch(attrs: {
61
- listImplicitChildLevelAdvances?: number | null;
62
- }, numPr: {
62
+ declare function listLevelAttrPatch(attrs: Pick<ParagraphAttrs, "listImplicitChildLevelAdvances" | "_originalFormatting" | "_resolvedFormatting" | "_styleResolvedFormatting" | "numPr" | "numPrFromStyle" | "indentLeft" | "indentRight" | "indentFirstLine" | "hangingIndent">, numPr: {
63
63
  numId: number;
64
64
  ilvl: number;
65
65
  }, numbering: NumberingMap | null | undefined): ParagraphAttrsPatch;
66
66
  //#endregion
67
- export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listLevelAttrPatch, listLevelIndentAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
67
+ export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listIndentationProvenancePatch, listLevelAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
@@ -6,6 +6,7 @@ import { CLEARED_LIST_RENDERING_ATTRS } from "../listMarker.js";
6
6
  import { listRenderingAttrPatch } from "../listRenderingAttrs.js";
7
7
  import { paragraphNumberingAttr } from "../numberingAttr.js";
8
8
  import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
9
+ import { directParagraphIndentation, paragraphIndentationAttrPatch, paragraphIndentationFromFormatting, withDirectParagraphIndentation } from "../paragraphIndentation.js";
9
10
  //#region src/prosemirror/styles/resolvedStyleAttrs.ts
10
11
  /**
11
12
  * Shared helper for projecting a resolved paragraph style onto ProseMirror
@@ -48,6 +49,7 @@ function paragraphAttrsFromResolvedStyle(resolved, identity) {
48
49
  borders: ppr?.borders ?? null,
49
50
  defaultTextFormatting: hasRunFormatting ? runFormatting : null,
50
51
  _resolvedFormatting: styleResolvedParagraphFormatting(ppr),
52
+ _styleResolvedFormatting: styleResolvedParagraphFormatting(ppr),
51
53
  _autospacingBase: autospacingBaseFromResolvedParagraphFormatting(ppr),
52
54
  _tableOfContentsLevel: tableOfContentsStyleLevel(identity) ?? null
53
55
  };
@@ -84,19 +86,26 @@ function listAttrsFromResolvedStyle(resolved, numbering) {
84
86
  numId,
85
87
  ilvl
86
88
  }, numbering);
87
- const level = numbering?.getLevel(numId, ilvl);
88
89
  attrs.numPrFromStyle = paragraphNumberingAttr(paragraphNumberingReference({
89
90
  numId,
90
91
  ilvl
91
92
  }));
92
- const ppr = resolved.paragraphFormatting;
93
- if (level?.pPr) {
94
- if (ppr?.indentLeft === void 0 && level.pPr.indentLeft !== void 0) attrs.indentLeft = level.pPr.indentLeft;
95
- if (!(ppr?.indentFirstLine !== void 0 || ppr?.hangingIndent !== void 0) && numberingLevelHasMarkerSlot(level)) {
96
- if (level.pPr.indentFirstLine !== void 0) attrs.indentFirstLine = level.pPr.indentFirstLine;
97
- if (level.pPr.hangingIndent !== void 0) attrs.hangingIndent = level.pPr.hangingIndent;
98
- }
99
- }
93
+ Object.assign(attrs, listIndentationProvenancePatch({
94
+ direct: void 0,
95
+ styleFormatting: resolved.paragraphFormatting,
96
+ numberingSource: "style",
97
+ numPr: {
98
+ numId,
99
+ ilvl
100
+ },
101
+ numbering
102
+ }));
103
+ for (const key of [
104
+ "indentLeft",
105
+ "indentRight",
106
+ "indentFirstLine"
107
+ ]) if (attrs[key] == null) Reflect.deleteProperty(attrs, key);
108
+ if (attrs.indentFirstLine === void 0 && resolved.paragraphFormatting?.hangingIndent === void 0) Reflect.deleteProperty(attrs, "hangingIndent");
100
109
  return attrs;
101
110
  }
102
111
  /** Project one resolved numbering level into the complete editor attr group. */
@@ -115,9 +124,9 @@ function listAttrsFromNumbering(numPr, numbering) {
115
124
  /**
116
125
  * The numbering level's indentation a directly numbered paragraph reads as its
117
126
  * own where it states none: the load path folds the level's `w:ind` into the
118
- * paragraph (a direct `w:ind` wins per group, left vs first line/hanging), so
119
- * a paragraph a command numbers carries it too, and the save writes it where a
120
- * reopen reads it back.
127
+ * paragraph (a direct `w:ind` wins per group, left vs first line/hanging).
128
+ * Keep this projection private: callers use the paired provenance helper so
129
+ * effective level values cannot be mistaken for authored indentation.
121
130
  */
122
131
  function listLevelIndentAttrPatch(stated, numPr, numbering) {
123
132
  const level = numbering?.getLevel(numPr.numId, numPr.ilvl);
@@ -130,6 +139,33 @@ function listLevelIndentAttrPatch(stated, numPr, numbering) {
130
139
  }
131
140
  return patch;
132
141
  }
142
+ /** Project effective indentation and both inheritance layers together. */
143
+ function listIndentationProvenancePatch({ direct, styleFormatting, numberingSource, numPr, numbering }) {
144
+ const style = {
145
+ ...styleResolvedParagraphFormatting(styleFormatting),
146
+ ...styleFormatting?.hangingIndent === void 0 ? {} : { hangingIndent: styleFormatting.hangingIndent }
147
+ };
148
+ const level = numPr === void 0 ? {} : listLevelIndentAttrPatch(numberingSource === "style" ? paragraphIndentationFromFormatting(style) : void 0, numPr, numbering);
149
+ if (level.indentLeft === 0 && style.indentLeft === void 0) Reflect.deleteProperty(level, "indentLeft");
150
+ if (level.indentFirstLine === 0 && style.indentFirstLine === void 0 && style.hangingIndent === void 0) {
151
+ Reflect.deleteProperty(level, "indentFirstLine");
152
+ Reflect.deleteProperty(level, "hangingIndent");
153
+ }
154
+ const resolved = {
155
+ ...style,
156
+ ...typeof level.indentLeft === "number" ? { indentLeft: level.indentLeft } : {},
157
+ ...typeof level.indentFirstLine === "number" ? { indentFirstLine: level.indentFirstLine } : {},
158
+ ...typeof level.hangingIndent === "boolean" ? { hangingIndent: level.hangingIndent } : {}
159
+ };
160
+ return {
161
+ ...paragraphIndentationAttrPatch({
162
+ direct,
163
+ inherited: paragraphIndentationFromFormatting(resolved)
164
+ }),
165
+ _resolvedFormatting: Object.keys(resolved).length === 0 ? null : resolved,
166
+ _styleResolvedFormatting: Object.keys(style).length === 0 ? null : style
167
+ };
168
+ }
133
169
  /**
134
170
  * The indentation a paragraph leaving its list keeps: the level's indentation
135
171
  * it only read from its numbering goes with the numbering, back to what its
@@ -138,28 +174,33 @@ function listLevelIndentAttrPatch(stated, numPr, numbering) {
138
174
  */
139
175
  function listLevelIndentRemovalPatch(attrs, numbering) {
140
176
  if (attrs.numPr?.kind !== "reference") return {};
141
- const level = numbering?.getLevel(attrs.numPr.numId, attrs.numPr.ilvl ?? 0);
142
- if (!level?.pPr) return {};
143
- const resolved = attrs.numPrFromStyle != null ? void 0 : attrs._resolvedFormatting;
144
- const patch = {};
145
- if (level.pPr.indentLeft !== void 0 && attrs.indentLeft === level.pPr.indentLeft) patch.indentLeft = resolved?.indentLeft ?? null;
146
- if (level.pPr.indentFirstLine !== void 0 && attrs.indentFirstLine === level.pPr.indentFirstLine && attrs.hangingIndent === (level.pPr.hangingIndent ?? false)) {
147
- patch.indentFirstLine = resolved?.indentFirstLine ?? null;
148
- patch.hangingIndent = resolved?.hangingIndent ?? false;
149
- }
150
- return patch;
177
+ const direct = directParagraphIndentation(attrs);
178
+ return {
179
+ ...listIndentationProvenancePatch({
180
+ direct,
181
+ styleFormatting: attrs._styleResolvedFormatting,
182
+ numberingSource: "paragraph",
183
+ numPr: void 0,
184
+ numbering
185
+ }),
186
+ _originalFormatting: withDirectParagraphIndentation(attrs._originalFormatting, direct) ?? null
187
+ };
151
188
  }
152
189
  /** Recompute every level-dependent attr when a paragraph changes list level. */
153
190
  function listLevelAttrPatch(attrs, numPr, numbering) {
154
- const level = numbering?.getLevel(numPr.numId, numPr.ilvl);
155
- const hasMarkerSlot = level ? numberingLevelHasMarkerSlot(level) : false;
191
+ const direct = directParagraphIndentation(attrs);
156
192
  return {
157
193
  ...listAttrsFromNumbering(numPr, numbering),
158
194
  listImplicitChildLevelAdvances: attrs.listImplicitChildLevelAdvances ?? null,
159
- indentLeft: level?.pPr?.indentLeft ?? null,
160
- indentFirstLine: hasMarkerSlot ? level?.pPr?.indentFirstLine ?? null : null,
161
- hangingIndent: hasMarkerSlot ? level?.pPr?.hangingIndent ?? null : null
195
+ ...listIndentationProvenancePatch({
196
+ direct,
197
+ styleFormatting: attrs._styleResolvedFormatting,
198
+ numberingSource: attrs.numPrFromStyle == null ? "paragraph" : "style",
199
+ numPr,
200
+ numbering
201
+ }),
202
+ _originalFormatting: withDirectParagraphIndentation(attrs._originalFormatting, direct) ?? null
162
203
  };
163
204
  }
164
205
  //#endregion
165
- export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listLevelAttrPatch, listLevelIndentAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
206
+ export { listAttrsFromNumbering, listAttrsFromResolvedStyle, listIndentationProvenancePatch, listLevelAttrPatch, listLevelIndentRemovalPatch, paragraphAttrsFromResolvedStyle };
@@ -13,6 +13,10 @@ type TextInput = {
13
13
  to: number;
14
14
  };
15
15
  declare const dispatchEditorTextInput: <TView extends TextInputDispatchTarget<TView>>(view: TView, input: string | TextInput) => void;
16
+ declare const getEditorInputTargetRange: (view: EditorView, event: InputEvent) => {
17
+ from: number;
18
+ to: number;
19
+ } | null;
16
20
  /** Shared DOM boundary for editor runtimes and standalone suggestion views. */
17
21
  declare const handleEditorBeforeInput: (view: EditorView, event: InputEvent) => boolean;
18
22
  /**
@@ -23,4 +27,4 @@ declare const afterNativeCompositionFlush: (callback: () => void) => void;
23
27
  /** Route committed text through the model before the browser mutates mark spans. */
24
28
  declare const createTextInputPlugin: () => Plugin<any>;
25
29
  //#endregion
26
- export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, handleEditorBeforeInput };
30
+ export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, getEditorInputTargetRange, handleEditorBeforeInput };
@@ -19,7 +19,7 @@ const dispatchEditorTextInput = (view, input) => {
19
19
  };
20
20
  if (!view.someProp("handleTextInput", (handler) => handler(view, from, to, text, defaultTransaction))) view.dispatch(defaultTransaction());
21
21
  };
22
- const replacementSelection = (view, event) => {
22
+ const getEditorInputTargetRange = (view, event) => {
23
23
  if (typeof event.getTargetRanges !== "function") return null;
24
24
  const ranges = event.getTargetRanges();
25
25
  if (ranges.length !== 1) return null;
@@ -39,7 +39,7 @@ const handleEditorBeforeInput = (view, event) => {
39
39
  if (event.inputType !== "insertText" && event.inputType !== "insertReplacementText") return false;
40
40
  const text = event.data ?? (event.dataTransfer?.types.includes("text/plain") ? event.dataTransfer.getData("text/plain") : null);
41
41
  if (text === null) return false;
42
- const selection = event.inputType === "insertReplacementText" ? replacementSelection(view, event) : view.state.selection;
42
+ const selection = event.inputType === "insertReplacementText" ? getEditorInputTargetRange(view, event) : view.state.selection;
43
43
  if (!selection) return false;
44
44
  event.preventDefault();
45
45
  dispatchEditorTextInput(view, {
@@ -78,4 +78,4 @@ const createTextInputPlugin = () => {
78
78
  } } });
79
79
  };
80
80
  //#endregion
81
- export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, handleEditorBeforeInput };
81
+ export { afterNativeCompositionFlush, createTextInputPlugin, dispatchEditorTextInput, getEditorInputTargetRange, handleEditorBeforeInput };
@@ -13,5 +13,9 @@ type EnclosingInsertionAncestorsOptions = {
13
13
  };
14
14
  /** The deletion's ancestor path, with the insertion it sits in as the outermost layer. */
15
15
  declare const enclosingInsertionAncestors: ({ insertionMark, ancestors, node }: EnclosingInsertionAncestorsOptions) => readonly TrackedRevisionAncestor[];
16
+ /** The authored revision layers already owned by a mark, outermost first. */
17
+ declare const trackedRevisionPathOf: (mark: Mark) => readonly TrackedRevisionAncestor[];
18
+ /** Promote a surviving existing layer; callers cannot supply a fresh identity. */
19
+ declare const retainedTrackedRevisionMark: (mark: Mark, keepLayer: (layer: TrackedRevisionAncestor) => boolean) => Mark | null;
16
20
  //#endregion
17
- export { enclosingInsertionAncestors, inlineWrapperStackOf, trackedRevisionLayerOf };
21
+ export { enclosingInsertionAncestors, inlineWrapperStackOf, retainedTrackedRevisionMark, trackedRevisionLayerOf, trackedRevisionPathOf };
@@ -1,5 +1,6 @@
1
1
  import { expectInlineWrapperMarkAttrs, expectTrackedChangeMarkAttrs } from "./attrs/index.js";
2
2
  import { INLINE_WRAPPER_MARK_NAME } from "./extensions/marks/InlineWrapperExtension.js";
3
+ import { panic } from "better-result";
3
4
  //#region src/prosemirror/trackedRevisionPath.ts
4
5
  /** The wrappers `node` sits inside, outermost first; empty when it sits in none. */
5
6
  const inlineWrapperStackOf = (node) => {
@@ -29,5 +30,42 @@ const enclosingInsertionAncestors = ({ insertionMark, ancestors, node }) => {
29
30
  if (ancestors.some(({ revisionId }) => revisionId === attrs.revisionId)) return ancestors;
30
31
  return [trackedRevisionLayerOf(insertionMark, node), ...ancestors];
31
32
  };
33
+ const revisionLayerOf = (mark) => {
34
+ const attrs = expectTrackedChangeMarkAttrs(mark);
35
+ let type;
36
+ if (mark.type.name === "insertion") type = attrs.moveKind === "moveTo" ? "moveTo" : "insertion";
37
+ else type = attrs.moveKind === "moveFrom" ? "moveFrom" : "deletion";
38
+ return {
39
+ type,
40
+ revisionId: attrs.revisionId,
41
+ author: attrs.author,
42
+ ...attrs.date ? { date: attrs.date } : {},
43
+ ...attrs.utcDate ? { utcDate: attrs.utcDate } : {},
44
+ ...attrs.initials ? { initials: attrs.initials } : {},
45
+ outerWrapperCount: attrs._docxOuterWrapperCount ?? 0
46
+ };
47
+ };
48
+ /** The authored revision layers already owned by a mark, outermost first. */
49
+ const trackedRevisionPathOf = (mark) => [...expectTrackedChangeMarkAttrs(mark)._docxRevisionAncestors ?? [], revisionLayerOf(mark)];
50
+ /** Promote a surviving existing layer; callers cannot supply a fresh identity. */
51
+ const retainedTrackedRevisionMark = (mark, keepLayer) => {
52
+ const remaining = trackedRevisionPathOf(mark).filter(keepLayer);
53
+ const active = remaining.at(-1);
54
+ if (!active) return null;
55
+ const name = active.type === "insertion" || active.type === "moveTo" ? "insertion" : "deletion";
56
+ const type = mark.type.schema.marks[name];
57
+ if (!type) panic("A nested tracked revision has no editor mark type");
58
+ return type.create({
59
+ revisionId: active.revisionId,
60
+ author: active.author,
61
+ date: active.date ?? null,
62
+ utcDate: active.utcDate ?? null,
63
+ initials: active.initials ?? null,
64
+ moveKind: active.type === "moveTo" || active.type === "moveFrom" ? active.type : null,
65
+ _historicalFormatting: active.type === "deletion" || active.type === "moveFrom" ? true : null,
66
+ _docxOuterWrapperCount: active.outerWrapperCount,
67
+ _docxRevisionAncestors: remaining.length > 1 ? remaining.slice(0, -1) : null
68
+ });
69
+ };
32
70
  //#endregion
33
- export { enclosingInsertionAncestors, inlineWrapperStackOf, trackedRevisionLayerOf };
71
+ export { enclosingInsertionAncestors, inlineWrapperStackOf, retainedTrackedRevisionMark, trackedRevisionLayerOf, trackedRevisionPathOf };
@@ -2,7 +2,7 @@ import { readNoteMarkerAttrs } from "../internal/noteMarkerAttrs.js";
2
2
  import { readBlockCustomXmlAttrs, readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunIdentityMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs } from "./attrs/index.js";
3
3
  import { readBookmarkBoundaryAttrs } from "./bookmarkBoundaryAttrs.js";
4
4
  import { readCommentReferenceAttrs } from "./commentReferenceAttrs.js";
5
- import { INLINE_WRAPPER_MARK_NAME } from "./extensions/marks/InlineWrapperExtension.js";
5
+ import { fieldRequiresStructuredContent } from "./fieldRepresentation.js";
6
6
  import { readMoveRangeBoundaryAttrs } from "./moveRangeBoundaryAttrs.js";
7
7
  import { readRangeAnchorAttrs } from "./rangeAnchorAttrs.js";
8
8
  import { readTextBoxAnchorAttrs } from "./textBoxAnchorAttrs.js";
@@ -249,8 +249,6 @@ const validateNodeAttrs = (node, path, issues) => {
249
249
  if (fieldAttrs.ok) {
250
250
  const hasStructuredHyperlink = node.content.content.some((child) => child.marks.some((mark) => mark.type.name === "hyperlink"));
251
251
  const hasPageBreakCarrier = node.content.content.some((child) => child.type.name === "pageBreakRun");
252
- const hasPreservedCapture = node.content.content.some((child) => child.type.name === "preservedXml");
253
- const hasInlineWrapper = node.content.content.some((child) => child.marks.some((mark) => mark.type.name === INLINE_WRAPPER_MARK_NAME));
254
252
  if (fieldAttrs.value.fieldKind === "complex" && !hasPageBreakCarrier) issues.push({
255
253
  path: `${path}.content`,
256
254
  message: "Complex fields cannot contain structured result children."
@@ -259,9 +257,9 @@ const validateNodeAttrs = (node, path, issues) => {
259
257
  path: `${path}.content`,
260
258
  message: "Complex field results cannot contain hyperlink content."
261
259
  });
262
- else if (!hasStructuredHyperlink && !hasPageBreakCarrier && !hasPreservedCapture && !hasInlineWrapper) issues.push({
260
+ else if (!fieldRequiresStructuredContent(node.content.content)) issues.push({
263
261
  path: `${path}.content`,
264
- message: "Structured simple fields require hyperlink, page-break, preserved or wrapper content."
262
+ message: "Structured simple fields require non-text, hyperlink, wrapper or tracked content."
265
263
  });
266
264
  node.forEach((child, _offset, index) => {
267
265
  const childPath = `${path}.content[${index}]`;
@@ -8,14 +8,20 @@ import * as Y from "yjs";
8
8
  */
9
9
  type AttrSchemaMigrationStep = (fragment: Y.XmlFragment) => number;
10
10
  /** Every attr-schema version this build reads, oldest first, with no gaps. */
11
- declare const FOLIO_YJS_ATTR_SCHEMA_VERSIONS: readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
11
+ declare const FOLIO_YJS_ATTR_SCHEMA_VERSIONS: readonly [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
12
12
  /** An attr-schema version this build can read. */
13
13
  type FolioYjsAttrSchemaVersion = (typeof FOLIO_YJS_ATTR_SCHEMA_VERSIONS)[number];
14
14
  /**
15
15
  * The attr-schema version this build writes. Derived against the migration map
16
16
  * so the constant and the map cannot disagree.
17
17
  */
18
- declare const FOLIO_YJS_ATTR_SCHEMA_VERSION = 11;
18
+ declare const FOLIO_YJS_ATTR_SCHEMA_VERSION = 12;
19
+ declare const FolioYjsNoteReferenceSchemaError_base: import("better-result").TaggedErrorClass<"FolioYjsNoteReferenceSchemaError">;
20
+ declare class FolioYjsNoteReferenceSchemaError extends FolioYjsNoteReferenceSchemaError_base<{
21
+ message: string;
22
+ schemaVersion: FolioYjsAttrSchemaVersion;
23
+ requiredSchemaVersion: FolioYjsAttrSchemaVersion;
24
+ }> {}
19
25
  /**
20
26
  * The steps that carry a snapshot written under `fromVersion` up to
21
27
  * {@link FOLIO_YJS_ATTR_SCHEMA_VERSION}, in order. Empty when the snapshot is
@@ -70,4 +76,4 @@ declare const writeYjsDocumentMetadata: (ydoc: Y.Doc, document: Node) => void;
70
76
  declare const readYjsParagraphSourceContract: (ydoc: Y.Doc) => string | null;
71
77
  declare const withParagraphSourceContract: (document: Node, contract: string) => Node;
72
78
  //#endregion
73
- export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
79
+ export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersion, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
@@ -1,4 +1,5 @@
1
1
  import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, getProseDocumentParagraphPropertySourceContract } from "../docx/paragraphPropertySource.js";
2
+ import { isNoteReferenceOccurrenceId } from "./noteReferenceOccurrenceId.js";
2
3
  import { mintSectionProperties, parseSectionBreakType } from "./sectionCarrier.js";
3
4
  import { Result, TaggedError, panic } from "better-result";
4
5
  import { DRAWING_RAW_XML_MODES, outlineLevelFromStatedValue, paragraphNumberingFromSlots } from "@stll/docx-core/model";
@@ -473,7 +474,8 @@ const FOLIO_YJS_ATTR_SCHEMA_VERSIONS = [
473
474
  8,
474
475
  9,
475
476
  10,
476
- 11
477
+ 11,
478
+ 12
477
479
  ];
478
480
  /**
479
481
  * The one place a persisted attr-shape change is decided.
@@ -497,13 +499,39 @@ const ATTR_SCHEMA_MIGRATIONS = {
497
499
  8: mintSectionPropertiesFromBreakType,
498
500
  9: dropUnstatedPlaceholderFlags,
499
501
  10: renamePageBreakRunOwnerMarkAttr,
500
- 11: "current"
502
+ 11: stampMarkerOnly,
503
+ 12: "current"
501
504
  };
502
505
  /**
503
506
  * The attr-schema version this build writes. Derived against the migration map
504
507
  * so the constant and the map cannot disagree.
505
508
  */
506
- const FOLIO_YJS_ATTR_SCHEMA_VERSION = 11;
509
+ const FOLIO_YJS_ATTR_SCHEMA_VERSION = 12;
510
+ var FolioYjsNoteReferenceSchemaError = class extends TaggedError("FolioYjsNoteReferenceSchemaError") {};
511
+ /** Check before any migration mutates the snapshot or any PM builder can drop text. */
512
+ const requireNoteOccurrenceAttribution = (fragment, schemaVersion) => {
513
+ const visit = (node) => {
514
+ for (const child of node.toArray()) {
515
+ if (typeof child === "string") continue;
516
+ if (!isXmlText(child)) {
517
+ if ("toArray" in child) visit(child);
518
+ continue;
519
+ }
520
+ for (const op of child.toDelta()) {
521
+ const attributes = op.attributes;
522
+ if (!isRecord(attributes) || attributes["footnoteRef"] == null) continue;
523
+ const reference = attributes["footnoteRef"];
524
+ if (isRecord(reference) && isNoteReferenceOccurrenceId(reference["occurrenceId"])) continue;
525
+ throw new FolioYjsNoteReferenceSchemaError({
526
+ schemaVersion,
527
+ requiredSchemaVersion: 12,
528
+ message: `Yjs schema ${schemaVersion} has unattributed note references; schema 12 requires occurrence identities. Rebuild the collaboration state from the saved DOCX.`
529
+ });
530
+ }
531
+ }
532
+ };
533
+ visit(fragment);
534
+ };
507
535
  /**
508
536
  * The steps that carry a snapshot written under `fromVersion` up to
509
537
  * {@link FOLIO_YJS_ATTR_SCHEMA_VERSION}, in order. Empty when the snapshot is
@@ -528,7 +556,8 @@ const attrSchemaMigrationSteps = (fromVersion) => FOLIO_YJS_ATTR_SCHEMA_VERSIONS
528
556
  * Returns how many elements the steps rewrote.
529
557
  */
530
558
  const applyAttrSchemaMigrations = (ydoc, fragment, fromVersion) => {
531
- if (fromVersion === 11) return 0;
559
+ requireNoteOccurrenceAttribution(fragment, fromVersion);
560
+ if (fromVersion === 12) return 0;
532
561
  let rewritten = 0;
533
562
  ydoc.transact(() => {
534
563
  for (const step of attrSchemaMigrationSteps(fromVersion)) rewritten += step(fragment);
@@ -538,7 +567,7 @@ const applyAttrSchemaMigrations = (ydoc, fragment, fromVersion) => {
538
567
  };
539
568
  /** Raised when a snapshot's attr-schema marker is ahead of the running code. */
540
569
  var FolioYjsAttrSchemaVersionError = class extends TaggedError("FolioYjsAttrSchemaVersionError") {};
541
- const isReadableVersion = (marker) => typeof marker === "number" && Number.isInteger(marker) && marker >= 0 && marker <= 11;
570
+ const isReadableVersion = (marker) => typeof marker === "number" && Number.isInteger(marker) && marker >= 0 && marker <= 12;
542
571
  /**
543
572
  * The attr-schema version a collaboration document was written under.
544
573
  *
@@ -556,7 +585,7 @@ const readYjsAttrSchemaVersion = (ydoc) => {
556
585
  return Result.err(new FolioYjsAttrSchemaVersionError({
557
586
  marker,
558
587
  message: "The collaboration snapshot was written by a newer Folio attr schema than this build reads.",
559
- supportedVersion: 11
588
+ supportedVersion: 12
560
589
  }));
561
590
  };
562
591
  const proseDocumentParagraphSourceContract = (document) => {
@@ -564,7 +593,7 @@ const proseDocumentParagraphSourceContract = (document) => {
564
593
  };
565
594
  /** Stamp the attr-schema version of the build that wrote the current fragment. */
566
595
  const writeYjsAttrSchemaVersion = (ydoc) => {
567
- ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(ATTR_SCHEMA_VERSION_KEY, 11);
596
+ ydoc.getMap(FOLIO_YJS_METADATA_MAP_NAME).set(ATTR_SCHEMA_VERSION_KEY, 12);
568
597
  };
569
598
  /**
570
599
  * Write both metadata bindings for a freshly seeded collaboration document.
@@ -589,4 +618,4 @@ const withParagraphSourceContract = (document, contract) => {
589
618
  }, document.content, document.marks);
590
619
  };
591
620
  //#endregion
592
- export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };
621
+ export { FOLIO_YJS_ATTR_SCHEMA_VERSION, FolioYjsAttrSchemaVersionError, FolioYjsNoteReferenceSchemaError, applyAttrSchemaMigrations, attrSchemaMigrationSteps, proseDocumentParagraphSourceContract, readYjsAttrSchemaVersion, readYjsParagraphSourceContract, withParagraphSourceContract, writeYjsAttrSchemaVersion, writeYjsDocumentMetadata };