@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
@@ -4,6 +4,7 @@ import { readParagraphNumberingAttr } from "../numberingAttr.js";
4
4
  import { directParagraphAlignment } from "../paragraphAlignment.js";
5
5
  import { directionFromBidi } from "../paragraphDirection.js";
6
6
  import { PARAGRAPH_FORMATTING_WRITE_BACK, STYLE_RESOLVED_PARAGRAPH_FIELDS } from "../paragraphFormattingProvenance.js";
7
+ import { directParagraphIndentation } from "../paragraphIndentation.js";
7
8
  import { directParagraphSpacing, paragraphSpacingAttrPatch, paragraphSpacingFromFormatting } from "../paragraphSpacing.js";
8
9
  import { sameFormattingValue } from "../runFormattingFromMarks.js";
9
10
  //#region src/prosemirror/commands/propertyChangeScope.ts
@@ -127,18 +128,14 @@ const paragraphPropertiesSnapshot = (node) => {
127
128
  const attrs = expectParagraphAttrs(node);
128
129
  const snapshot = {};
129
130
  for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) {
130
- if (key === "alignment" || PPR_SPACING_ATTR_KEYS.has(key) || key === "numPr" && isStyleSourcedParagraphNumbering(attrs.numPr, attrs.numPrFromStyle)) continue;
131
+ if (key === "alignment" || key === "indentLeft" || key === "indentRight" || key === "indentFirstLine" || key === "hangingIndent" || PPR_SPACING_ATTR_KEYS.has(key) || key === "numPr" && isStyleSourcedParagraphNumbering(attrs.numPr, attrs.numPrFromStyle)) continue;
131
132
  if (styleSuppliedParagraphValue(attrs, key)) continue;
132
- if (key === "hangingIndent" && styleSuppliedParagraphValue(attrs, "indentFirstLine")) continue;
133
- if (styleSuppliedParagraphValue(attrs, key)) continue;
134
- if (key === "hangingIndent" && styleSuppliedParagraphValue(attrs, "indentFirstLine")) continue;
135
133
  const value = attrs[key];
136
- if (key === "hangingIndent" && value === false && attrs._originalFormatting?.hangingIndent === void 0) continue;
137
134
  if (value !== null && value !== void 0) snapshot[key] = value;
138
135
  }
139
136
  const directAlignment = directParagraphAlignment(attrs);
140
137
  if (directAlignment !== void 0) snapshot["alignment"] = directAlignment;
141
- Object.assign(snapshot, directParagraphSpacing(attrs));
138
+ Object.assign(snapshot, directParagraphSpacing(attrs), directParagraphIndentation(attrs));
142
139
  return snapshot;
143
140
  };
144
141
  /**
@@ -2,8 +2,9 @@ import { resolveParagraphNumbering } from "../../docx/numberingReference.js";
2
2
  import { expectParagraphAttrs } from "../attrs/index.js";
3
3
  import { rejectedListRenderingPatch } from "../listRendering.js";
4
4
  import { paragraphNumberingAttr } from "../numberingAttr.js";
5
- import { styleResolvedParagraphFormatting } from "../paragraphFormattingProvenance.js";
5
+ import { paragraphIndentationFromFormatting } from "../paragraphIndentation.js";
6
6
  import { resolveParagraphDefaultTextFormatting } from "../styles/paragraphStyleCascade.js";
7
+ import { listIndentationProvenancePatch } from "../styles/resolvedStyleAttrs.js";
7
8
  import { paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges, sectionRejectProperties } from "./propertyChangeScope.js";
8
9
  //#region src/prosemirror/commands/resolveParagraphProperties.ts
9
10
  /** Resolve paragraph and section property records before resolving their inline content. */
@@ -27,24 +28,32 @@ const resolveParagraphChangeAttrs = ({ node, boundaryCovered, mode, revisionSet,
27
28
  const inheritedAlignment = currentAttrs.alignmentFromStyle;
28
29
  const restoredStyleId = rejection.previousFormatting?.styleId ?? void 0;
29
30
  const sameStyle = restoredStyleId === (currentAttrs.styleId ?? void 0);
30
- let previousFormattingFromStyle;
31
- let resolvedFromStyle = sameStyle ? currentAttrs._resolvedFormatting : void 0;
32
- if (styleResolver) {
33
- previousFormattingFromStyle = styleResolver.resolveParagraphStyle(restoredStyleId).paragraphFormatting;
34
- if (!sameStyle) {
35
- resolvedFromStyle = styleResolvedParagraphFormatting(previousFormattingFromStyle);
36
- nextAttrs["_resolvedFormatting"] = resolvedFromStyle;
37
- }
38
- } else if (inheritedAlignment !== void 0) previousFormattingFromStyle = { alignment: inheritedAlignment };
39
- const inheritedFormatting = previousFormattingFromStyle === void 0 && resolvedFromStyle === void 0 ? void 0 : {
31
+ let previousFormattingFromStyle = sameStyle ? currentAttrs._styleResolvedFormatting : void 0;
32
+ if (styleResolver) previousFormattingFromStyle = styleResolver.resolveParagraphStyle(restoredStyleId).paragraphFormatting;
33
+ else if (inheritedAlignment !== void 0) previousFormattingFromStyle = {
40
34
  ...previousFormattingFromStyle,
41
- ...resolvedFromStyle
35
+ alignment: inheritedAlignment
42
36
  };
43
37
  let styleNumbering = previousFormattingFromStyle?.numPr;
44
38
  if (!styleResolver && sameStyle) styleNumbering = currentAttrs.numPrFromStyle ?? void 0;
45
39
  const inheritedNumbering = styleNumbering == null ? null : paragraphNumberingAttr(resolveParagraphNumbering(styleNumbering));
46
40
  const recordedNumbering = rejection.previousFormatting?.numPr;
47
41
  const restoredNumbering = recordedNumbering ?? inheritedNumbering;
42
+ const restoredFormatting = paragraphRejectOriginalFormatting(rejection.previousFormatting, node.attrs["_originalFormatting"]);
43
+ const indentation = listIndentationProvenancePatch({
44
+ direct: paragraphIndentationFromFormatting(restoredFormatting ?? void 0),
45
+ styleFormatting: previousFormattingFromStyle,
46
+ numberingSource: recordedNumbering == null ? "style" : "paragraph",
47
+ numPr: restoredNumbering?.kind === "reference" ? {
48
+ numId: restoredNumbering.numId,
49
+ ilvl: restoredNumbering.ilvl ?? 0
50
+ } : void 0,
51
+ numbering
52
+ });
53
+ const inheritedFormatting = {
54
+ ...previousFormattingFromStyle,
55
+ ...indentation._resolvedFormatting
56
+ };
48
57
  Object.assign(nextAttrs, paragraphRejectAttrPatch(rejection.previousFormatting, inheritedFormatting), rejectedListRenderingPatch({
49
58
  current: expectParagraphAttrs(node),
50
59
  previousFormatting: rejection.previousFormatting,
@@ -54,7 +63,7 @@ const resolveParagraphChangeAttrs = ({ node, boundaryCovered, mode, revisionSet,
54
63
  numPr: restoredNumbering,
55
64
  numPrFromStyle: recordedNumbering == null ? inheritedNumbering : null
56
65
  });
57
- const restoredFormatting = paragraphRejectOriginalFormatting(rejection.previousFormatting, node.attrs["_originalFormatting"]);
66
+ Object.assign(nextAttrs, indentation);
58
67
  nextAttrs["_originalFormatting"] = restoredFormatting;
59
68
  if (styleResolver) nextAttrs["defaultTextFormatting"] = resolveParagraphDefaultTextFormatting(rejection.previousFormatting?.styleId, restoredFormatting ?? void 0, styleResolver) ?? null;
60
69
  }
@@ -1,6 +1,14 @@
1
+ import { addTrackedDeletionMark } from "./addTrackedDeletionMark.js";
1
2
  import { findTextInPmParagraph } from "./paraText.js";
2
3
  import { findParagraphByParaId } from "./utils/findParagraphByParaId.js";
3
4
  //#region src/prosemirror/commentOps.ts
5
+ /**
6
+ * Comment + tracked-change (proposeChange) PM transaction builders shared by
7
+ * the React and Vue adapters. They locate the target range, apply the mark(s),
8
+ * dispatch, and return a result. ID allocation lives in `commentIdAllocator.ts`
9
+ * and is injected. Adapter-specific state mutation, event emission, and sidebar
10
+ * UI stay in each adapter.
11
+ */
4
12
  /** Build a Comment object with a freshly-allocated ID. */
5
13
  function createComment(allocator, text, authorName, parentId) {
6
14
  return {
@@ -95,7 +103,13 @@ function applyProposedChange(view, options, allocator) {
95
103
  date
96
104
  });
97
105
  let tr = view.state.tr;
98
- if (!isInsertion) tr = tr.addMark(textFrom, textTo, deletionMark);
106
+ if (!isInsertion) addTrackedDeletionMark({
107
+ insertionPolicy: "preserve-pending",
108
+ tr,
109
+ from: textFrom,
110
+ to: textTo,
111
+ mark: deletionMark
112
+ });
99
113
  if (!isDeletion) tr = tr.insert(textTo, schema.text(options.replaceWith, [insertionMark]));
100
114
  view.dispatch(tr);
101
115
  return true;
@@ -16,11 +16,18 @@ import { Node } from "prosemirror-model";
16
16
  type ProjectionReuse = "none" | "matched";
17
17
  /** How the conversion treats records the editor did not change. */
18
18
  type FromProseDocOptions = {
19
+ /** The stylesheet authority used to construct the projection. */
20
+ stylesheetSource: {
21
+ type: "package";
22
+ } | {
23
+ type: "supplied";
24
+ styles: document_d_exports.StyleDefinitions;
25
+ };
19
26
  /** Defaults to `"none"`, the only value implemented. */
20
27
  reuse?: ProjectionReuse;
21
28
  };
22
29
  /** Convert a ProseMirror document to the document model. */
23
- declare function fromProseDoc(pmDoc: Node, baseDocument?: document_d_exports.Document, { reuse }?: FromProseDocOptions): document_d_exports.Document;
30
+ declare function fromProseDoc(pmDoc: Node, baseDocument: document_d_exports.Document | undefined, { stylesheetSource, reuse }: FromProseDocOptions): document_d_exports.Document;
24
31
  declare function tableAttrsToFormatting(attrs: TableAttrs): document_d_exports.TableFormatting | undefined;
25
32
  /**
26
33
  * Convert ProseMirror table row attrs to TableRowFormatting
@@ -1,10 +1,11 @@
1
1
  import { joinCommentRangesAcrossParagraphs } from "../../docx/commentRangeJoin.js";
2
2
  import { completeCommentReferences } from "../../docx/commentReferenceCompletion.js";
3
3
  import { normalizeFoldedListNumbers } from "../../docx/foldedListNumberFields.js";
4
+ import { getDocumentSourceBaseline } from "../../docx/headerFooterVerbatim.js";
4
5
  import { EDITED_PREVIEW_FINGERPRINT, imageRawXmlFingerprint } from "../../docx/imageRawXml.js";
5
6
  import { isInlineSdtContent, isSimpleFieldContent } from "../../docx/inlineWrapperContent.js";
6
7
  import { paragraphNumberingReferenceId as paragraphNumberingReferenceId$1, sameStatedParagraphNumbering as sameStatedParagraphNumbering$1 } from "../../docx/numberingReference.js";
7
- import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, inspectParagraphSourceIdentity, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
8
+ import { PROSE_PARAGRAPH_SOURCE_CONTRACT_ATTR, ParagraphPropertySourceValidationError, assignParagraphIndentationProjection, copyDocumentParagraphPropertySourceContract, copyDocumentParagraphPropertySources, copyParagraphPropertyCapture, copyParagraphPropertySource, decodeTableCellParagraphSourcePayload, getDocumentParagraphPropertySourceContract, getParagraphPropertySource, getParagraphPropertySourceCandidate, getParagraphPropertySourceToken, getParagraphPropertySourceTransferId, getProseDocumentParagraphPropertySourceContract, getProseParagraphPropertySourceToken, inspectParagraphSourceIdentity, isParagraphPropertySourceToken, linkParagraphPropertySourceCandidate, paragraphFormattingWithAuthoredIndentation, paragraphPropertySourceTokenMatchesContract, recreateProseNodeWithParagraphPropertySource, restoreTableCellsWithParagraphPropertySources, visitDocumentStoryParagraphs, visitTableCellParagraphPropertySourceBindings } from "../../docx/paragraphPropertySource.js";
8
9
  import { BLOCK_TREE_DESCENT, visitBlockTreeRecords, visitDocxParagraphs } from "../../docx/paragraphTraversal.js";
9
10
  import { refingerprintShapeAlternateContent } from "../../docx/shapeAlternateContent.js";
10
11
  import { DATE_UTC_ATTRIBUTE } from "../../docx/trackedChangeInfo.js";
@@ -33,15 +34,17 @@ import { inlineWrapperMember, inlineWrapperStackKey } from "../inlineWrapperStac
33
34
  import { completeNumberingForDoc } from "../listInstanceReferences.js";
34
35
  import { hasListRendering, listRenderingFromAttrs as listRenderingFromAttrs$1 } from "../listRenderingAttrs.js";
35
36
  import { expectMoveRangeBoundaryAttrs } from "../moveRangeBoundaryAttrs.js";
37
+ import { assertNoteReferenceOccurrences, coalesceNoteReferenceOccurrences } from "../noteReferenceOccurrences.js";
36
38
  import { resolveNumberedRefFields } from "../numberedRefFields.js";
37
39
  import { directParagraphAlignment } from "../paragraphAlignment.js";
38
40
  import { directionToAuthoredBidi } from "../paragraphDirection.js";
41
+ import { paragraphIndentationFromFormatting } from "../paragraphIndentation.js";
39
42
  import { directParagraphSpacing } from "../paragraphSpacing.js";
40
43
  import { expectRangeAnchorAttrs } from "../rangeAnchorAttrs.js";
41
44
  import { marksToTextFormatting, sameFormattingValue } from "../runFormattingFromMarks.js";
42
45
  import { RUN_FORMATTING_MARK_NAMES } from "../runFormattingMarkNames.js";
43
46
  import { RUN_IDENTITY_MARK_NAME } from "../runIdentity.js";
44
- import { paragraphFormattingForRun, paragraphRunStyleContext, resolveEffectiveRunStyleFormatting } from "../runStyleFormatting.js";
47
+ import { paragraphFormattingForRun, paragraphRunStyleContext, resolveEffectiveRunStyleFormatting, resolveParagraphInheritedRunFormatting } from "../runStyleFormatting.js";
45
48
  import { PRESERVED_XML_LEVELS } from "../schema/nodes.js";
46
49
  import { parseShapeGeometryAdjustments } from "../shapeGeometryAdjustments.js";
47
50
  import { expectTextBoxAnchorAttrs } from "../textBoxAnchorAttrs.js";
@@ -50,7 +53,7 @@ import { enclosingInsertionAncestors, inlineWrapperStackOf } from "../trackedRev
50
53
  import { assertValidProseMirrorDocument } from "../validation.js";
51
54
  import { hasSinkChildren } from "./preservedSinkCarriers.js";
52
55
  import { decodeSdtListItems, sdtPropertiesFromAttrs, sdtPropertiesMatchAttrs } from "./sdtAttrs.js";
53
- import { panic } from "better-result";
56
+ import { TaggedError, panic } from "better-result";
54
57
  import { DRAWING_RAW_XML_MODES, relationshipIdOf } from "@stll/docx-core/model";
55
58
  import { Fragment } from "prosemirror-model";
56
59
  //#region src/prosemirror/conversion/fromProseDoc.ts
@@ -161,6 +164,13 @@ const restoreParagraphPropertySource = (paragraph, baseParagraph) => {
161
164
  copyParagraphPropertySource(paragraph, baseParagraph);
162
165
  const baseFormatting = baseParagraph.formatting;
163
166
  if (!baseFormatting) return;
167
+ if (baseFormatting.indentLeft !== void 0 || baseFormatting.indentRight !== void 0 || baseFormatting.indentFirstLine !== void 0 || baseFormatting.hangingIndent !== void 0) {
168
+ const authored = paragraphFormattingWithAuthoredIndentation(baseParagraph);
169
+ if ((authored?.indentLeft !== baseFormatting.indentLeft || authored?.indentRight !== baseFormatting.indentRight || authored?.indentFirstLine !== baseFormatting.indentFirstLine || authored?.hangingIndent !== baseFormatting.hangingIndent) && canonicalJson(modelParagraphFormattingEmission(paragraph.formatting)) === canonicalJson(modelParagraphFormattingEmission(authored))) {
170
+ paragraph.formatting = { ...baseFormatting };
171
+ return;
172
+ }
173
+ }
164
174
  const { numPr, numPrFromStyle } = baseFormatting;
165
175
  if (!numPr || !numPrFromStyle || !isStyleSourcedParagraphNumbering(numPr, numPrFromStyle)) return;
166
176
  if (canonicalJson(modelParagraphFormattingEmission(paragraph.formatting)) !== canonicalJson(modelParagraphFormattingEmission(baseFormatting))) return;
@@ -261,8 +271,90 @@ const restoreLinkedParagraphPropertySources = (content) => {
261
271
  sources: new Set(targetsBySource.keys())
262
272
  };
263
273
  };
274
+ var SaveStylesheetSourceMismatch = class extends TaggedError("SaveStylesheetSourceMismatch") {};
275
+ const assertSuppliedStylesMatchSource = (styles, baseDocument) => {
276
+ if (!baseDocument?.originalBuffer) return;
277
+ const source = getDocumentSourceBaseline(baseDocument);
278
+ switch (source.type) {
279
+ case "missing":
280
+ case "mismatch": throw new SaveStylesheetSourceMismatch({
281
+ message: "The parsed package stylesheet source is unavailable.",
282
+ divergences: [{ type: "sourceUnavailable" }]
283
+ });
284
+ case "captured": {
285
+ const sourceStyles = source.resourceStyles;
286
+ if (!sourceStyles) return;
287
+ const suppliedById = new Map(styles.styles.map((style) => [style.styleId, style]));
288
+ const sourceById = new Map(sourceStyles.styles.map((style) => [style.styleId, style]));
289
+ const divergentIds = /* @__PURE__ */ new Set();
290
+ for (const style of sourceStyles.styles) if (canonicalJson(style) !== canonicalJson(suppliedById.get(style.styleId))) divergentIds.add(style.styleId);
291
+ for (const style of styles.styles) if (canonicalJson(style) !== canonicalJson(suppliedById.get(style.styleId))) divergentIds.add(style.styleId);
292
+ const persistedStyles = {
293
+ ...sourceStyles,
294
+ styles: [...sourceStyles.styles, ...styles.styles.filter(({ styleId }) => !sourceById.has(styleId))]
295
+ };
296
+ const suppliedResolver = createStyleEngine(styles);
297
+ const persistedResolver = createStyleEngine(persistedStyles);
298
+ for (const [supplied, persisted] of [
299
+ [suppliedResolver.getDefaultParagraphStyle(), persistedResolver.getDefaultParagraphStyle()],
300
+ [suppliedResolver.getDefaultCharacterStyle(), persistedResolver.getDefaultCharacterStyle()],
301
+ [suppliedResolver.getDefaultTableStyle(), persistedResolver.getDefaultTableStyle()]
302
+ ]) {
303
+ if (supplied?.styleId === persisted?.styleId) continue;
304
+ if (supplied) divergentIds.add(supplied.styleId);
305
+ if (persisted) divergentIds.add(persisted.styleId);
306
+ }
307
+ const divergences = [];
308
+ for (const styleId of divergentIds) divergences.push({
309
+ type: "style",
310
+ styleId
311
+ });
312
+ if (canonicalJson(styles.docDefaults) !== canonicalJson(sourceStyles.docDefaults)) divergences.push({ type: "docDefaults" });
313
+ if (divergences.length === 0) return;
314
+ throw new SaveStylesheetSourceMismatch({
315
+ message: `Supplied stylesheet differs from the parsed package: ${[...divergentIds, ...divergences.some(({ type }) => type === "docDefaults") ? ["docDefaults"] : []].join(", ")}.`,
316
+ divergences
317
+ });
318
+ }
319
+ default: return panic(`Unexpected stylesheet source baseline: ${JSON.stringify(source)}`);
320
+ }
321
+ };
322
+ const saveStylesheet = (source, baseDocument) => {
323
+ switch (source.type) {
324
+ case "package": return baseDocument?.package.styles;
325
+ case "supplied":
326
+ assertSuppliedStylesMatchSource(source.styles, baseDocument);
327
+ return source.styles;
328
+ default: return panic(`Unexpected stylesheet source: ${JSON.stringify(source)}`);
329
+ }
330
+ };
331
+ var MissingSaveStylesheet = class extends TaggedError("MissingSaveStylesheet") {};
332
+ const assertSaveStylesheetAvailable = ({ pmDoc, styles, baseDocument, stylesheetSource }) => {
333
+ if (styles !== void 0) return;
334
+ if (stylesheetSource.type === "package" && baseDocument !== void 0) return;
335
+ pmDoc.descendants((node) => {
336
+ if ((() => {
337
+ switch (node.type.name) {
338
+ case "paragraph": {
339
+ const attrs = expectParagraphAttrs(node);
340
+ return attrs.styleId ?? attrs._originalFormatting?.runProperties?.styleId;
341
+ }
342
+ case "table": return expectTableAttrs(node).styleId;
343
+ default: return;
344
+ }
345
+ })() != null || node.marks.some(({ type }) => type.name === "characterStyle")) throw new MissingSaveStylesheet({ message: "Saving style-dependent content requires its authoritative stylesheet." });
346
+ });
347
+ };
264
348
  /** Convert a ProseMirror document to the document model. */
265
- function fromProseDoc(pmDoc, baseDocument, { reuse = "none" } = {}) {
349
+ function fromProseDoc(pmDoc, baseDocument, { stylesheetSource, reuse = "none" }) {
350
+ const styles = saveStylesheet(stylesheetSource, baseDocument);
351
+ assertSaveStylesheetAvailable({
352
+ pmDoc,
353
+ styles,
354
+ baseDocument,
355
+ stylesheetSource
356
+ });
357
+ assertNoteReferenceOccurrences(pmDoc);
266
358
  switch (reuse) {
267
359
  case "none": break;
268
360
  case "matched": panic("fromProseDoc: reuse \"matched\" is not implemented");
@@ -274,7 +366,7 @@ function fromProseDoc(pmDoc, baseDocument, { reuse = "none" } = {}) {
274
366
  const proseContract = getProseDocumentParagraphPropertySourceContract(pmDoc);
275
367
  if (proseContractAttribute !== null && proseContractAttribute !== void 0 && proseContract === null || (baseContract ?? null) !== proseContract) throw sourceValidationError("contract_mismatch", "The ProseMirror document does not match its paragraph-property source document.");
276
368
  const tokenSources = baseContract && proseContract && baseDocument ? validateParagraphPropertySourceTokens(pmDoc, baseDocument, baseContract) : null;
277
- const blocks = extractBlocks(pmDoc, "resolve", baseDocument?.package.styles ? createStyleEngine(baseDocument.package.styles) : null);
369
+ const blocks = extractBlocks(pmDoc, "resolve", createStyleEngine(styles));
278
370
  joinCommentRangesAcrossParagraphs(blocks);
279
371
  completeCommentReferences(blocks);
280
372
  const linkedSources = restoreLinkedParagraphPropertySources(blocks);
@@ -292,6 +384,7 @@ function fromProseDoc(pmDoc, baseDocument, { reuse = "none" } = {}) {
292
384
  package: {
293
385
  ...baseDocument.package,
294
386
  document: documentBody,
387
+ ...styles ? { styles } : {},
295
388
  ...numbering ? { numbering } : {}
296
389
  }
297
390
  };
@@ -300,6 +393,7 @@ function fromProseDoc(pmDoc, baseDocument, { reuse = "none" } = {}) {
300
393
  }
301
394
  return { package: {
302
395
  document: documentBody,
396
+ ...styles ? { styles } : {},
303
397
  ...numbering ? { numbering } : {}
304
398
  } };
305
399
  }
@@ -314,12 +408,13 @@ const hasSuggestedInsertion = (marks) => marks.some((mark) => mark.type.name ===
314
408
  * Returns the input array unchanged when there is nothing to strip so callers
315
409
  * can skip rebuilding the node.
316
410
  */
317
- function stripSuggestedInlineMarks(marks, { baseParagraphFormatting, inheritedFormatting, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver }) {
411
+ function stripSuggestedInlineMarks(marks, readFormattingContext) {
318
412
  const hasSuggestedDeletion = marks.some((mark) => mark.type.name === "deletion" && isSuggestedMark(mark));
319
413
  const suggestedRunPropertyChange = marks.find((mark) => mark.type.name === "runPropertyChange" && isSuggestedMark(mark));
320
414
  if (!hasSuggestedDeletion && !suggestedRunPropertyChange) return marks;
321
415
  let next = marks.filter((mark) => !((mark.type.name === "deletion" || mark.type.name === "runPropertyChange") && isSuggestedMark(mark)));
322
416
  if (suggestedRunPropertyChange) {
417
+ const { baseParagraphFormatting, inheritedFormatting, paragraphMarkFormatting, paragraphMarkPrecedesStyle, styleResolver } = readFormattingContext();
323
418
  const previousFormatting = expectRunPropertyChangeMarkAttrs(suggestedRunPropertyChange).changes.at(0)?.previousFormatting;
324
419
  const characterStyleMark = marks.find(({ type }) => type.name === "characterStyle");
325
420
  const characterStyleAttrs = characterStyleMark ? expectCharacterStyleMarkAttrs(characterStyleMark) : void 0;
@@ -425,6 +520,21 @@ function isSuggestedInsertedNode(node) {
425
520
  }
426
521
  return false;
427
522
  }
523
+ const savedParagraphRunStyleContext = (paragraph, styleResolver) => {
524
+ const context = paragraphRunStyleContext(paragraph, styleResolver);
525
+ if (paragraph.content.size === 0) return context;
526
+ const attrs = expectParagraphAttrs(paragraph);
527
+ const source = resolveParagraphInheritedRunFormatting({
528
+ styleId: attrs.styleId,
529
+ styleResolver,
530
+ tableRunFormatting: attrs._tableRunFormatting,
531
+ paragraphMarkFormatting: attrs.styleId === void 0 ? context.paragraphMarkFormatting : void 0
532
+ });
533
+ return {
534
+ ...context,
535
+ paragraphFormatting: source.inheritedFormatting
536
+ };
537
+ };
428
538
  /**
429
539
  * Recursively rewrite a ProseMirror node tree, removing every suggested
430
540
  * tracked change. Returns `null` when the node itself must be dropped: a
@@ -432,32 +542,32 @@ function isSuggestedInsertedNode(node) {
432
542
  * Surviving block nodes are rebuilt with their suggested delete/merge markers
433
543
  * cleared and their children stripped.
434
544
  */
435
- function mapSuggestionStrippedNode(node, formattingContext = {
436
- baseParagraphFormatting: void 0,
437
- inheritedFormatting: void 0,
438
- paragraphMarkFormatting: void 0,
439
- paragraphMarkPrecedesStyle: false,
440
- styleResolver: null
441
- }) {
545
+ function mapSuggestionStrippedNode(node, readFormattingContext) {
442
546
  if (node.isInline) {
443
547
  if (hasSuggestedInsertion(node.marks)) return null;
444
- const marks = stripSuggestedInlineMarks(node.marks, formattingContext);
548
+ const marks = stripSuggestedInlineMarks(node.marks, readFormattingContext);
445
549
  return marks === node.marks ? node : node.mark(marks);
446
550
  }
447
551
  if (isSuggestedInsertedNode(node)) return null;
448
552
  const nextAttrs = stripSuggestedNodeAttrs(node);
449
553
  const children = [];
450
554
  let changed = nextAttrs !== null;
451
- const paragraphStyleContext = node.type.name === "paragraph" ? paragraphRunStyleContext(node, formattingContext.styleResolver) : void 0;
452
- const childFormattingContext = paragraphStyleContext ? {
453
- baseParagraphFormatting: paragraphStyleContext.baseParagraphFormatting,
454
- inheritedFormatting: paragraphStyleContext.paragraphFormatting,
455
- paragraphMarkFormatting: paragraphStyleContext.paragraphMarkFormatting,
456
- paragraphMarkPrecedesStyle: paragraphStyleContext.paragraphMarkPrecedesStyle,
457
- styleResolver: formattingContext.styleResolver
458
- } : formattingContext;
555
+ let resolvedChildContext;
556
+ const readChildFormattingContext = node.type.name === "paragraph" ? () => {
557
+ if (resolvedChildContext) return resolvedChildContext;
558
+ const { styleResolver } = readFormattingContext();
559
+ const paragraphStyleContext = savedParagraphRunStyleContext(node, styleResolver);
560
+ resolvedChildContext = {
561
+ baseParagraphFormatting: paragraphStyleContext.baseParagraphFormatting,
562
+ inheritedFormatting: paragraphStyleContext.paragraphFormatting,
563
+ paragraphMarkFormatting: paragraphStyleContext.paragraphMarkFormatting,
564
+ paragraphMarkPrecedesStyle: paragraphStyleContext.paragraphMarkPrecedesStyle,
565
+ styleResolver
566
+ };
567
+ return resolvedChildContext;
568
+ } : readFormattingContext;
459
569
  node.forEach((child) => {
460
- const mapped = mapSuggestionStrippedNode(child, childFormattingContext);
570
+ const mapped = mapSuggestionStrippedNode(child, readChildFormattingContext);
461
571
  if (mapped === null) {
462
572
  changed = true;
463
573
  return;
@@ -478,13 +588,13 @@ function mapSuggestionStrippedNode(node, formattingContext = {
478
588
  * {@link extractBlocks} for why this is the sole serialization boundary.
479
589
  */
480
590
  function stripSuggestedProvenance(doc, styleResolver) {
481
- return mapSuggestionStrippedNode(doc, {
591
+ return mapSuggestionStrippedNode(doc, () => ({
482
592
  baseParagraphFormatting: void 0,
483
593
  inheritedFormatting: void 0,
484
594
  paragraphMarkFormatting: void 0,
485
595
  paragraphMarkPrecedesStyle: false,
486
596
  styleResolver
487
- }) ?? doc;
597
+ })) ?? doc;
488
598
  }
489
599
  function materializeNumberedRefValues(doc) {
490
600
  const results = resolveNumberedRefFields(doc);
@@ -936,7 +1046,7 @@ function appendPageBreaks(paragraph, count) {
936
1046
  */
937
1047
  function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers, styleResolver = null) {
938
1048
  const attrs = expectParagraphAttrs(node);
939
- const paragraphStyleContext = paragraphRunStyleContext(node, styleResolver);
1049
+ const paragraphStyleContext = savedParagraphRunStyleContext(node, styleResolver);
940
1050
  let content = extractParagraphContent(node, documentCounts, attrs._emptyHyperlinks ?? void 0, textBoxAnchorMarkers, attrs.renderedPageBreakBefore === true, {
941
1051
  baseParagraphFormatting: paragraphStyleContext.baseParagraphFormatting,
942
1052
  inheritedFormatting: paragraphStyleContext.paragraphFormatting,
@@ -970,6 +1080,14 @@ function convertPMParagraph(node, documentCounts, textBoxAnchorMarkers, styleRes
970
1080
  if (attrs.reviewCarrier) paragraph.reviewCarrier = attrs.reviewCarrier;
971
1081
  const pFormatting = paragraphAttrsToFormatting(attrs);
972
1082
  if (pFormatting) paragraph.formatting = pFormatting;
1083
+ if (attrs.numPr?.kind === "reference") {
1084
+ const inheritedIndentation = paragraphIndentationFromFormatting(attrs._resolvedFormatting);
1085
+ if (inheritedIndentation) assignParagraphIndentationProjection({
1086
+ paragraph,
1087
+ authored: pFormatting,
1088
+ inherited: inheritedIndentation
1089
+ });
1090
+ }
973
1091
  const listRendering = listRenderingFromAttrs(attrs);
974
1092
  if (listRendering) paragraph.listRendering = listRendering;
975
1093
  normalizeFoldedListNumbers(paragraph);
@@ -1373,9 +1491,10 @@ const nestInlineWrapperGroups = (items, groups, hyperlinkIndices, revisionOuterW
1373
1491
  }
1374
1492
  return coalesced;
1375
1493
  };
1376
- function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false, inheritedFormattingOverride) {
1494
+ function extractParagraphContent(originalParagraph, _documentCounts, emptyHyperlinks, textBoxAnchorMarkers, skipLeadingRenderedPageBreak = false, inheritedFormattingOverride) {
1495
+ const paragraph = coalesceNoteReferenceOccurrences(originalParagraph);
1377
1496
  const content = [];
1378
- const paragraphStyleContext = paragraph.type.name === "paragraph" ? paragraphRunStyleContext(paragraph) : void 0;
1497
+ const paragraphStyleContext = inheritedFormattingOverride === void 0 && paragraph.type.name === "paragraph" ? savedParagraphRunStyleContext(paragraph) : void 0;
1379
1498
  const formattingContext = inheritedFormattingOverride ?? {
1380
1499
  baseParagraphFormatting: paragraphStyleContext?.baseParagraphFormatting,
1381
1500
  inheritedFormatting: paragraphStyleContext?.paragraphFormatting,
@@ -2463,7 +2582,7 @@ const synchronizeFieldDisplayText = (content, displayText, fallbackRun) => {
2463
2582
  visit(child);
2464
2583
  continue;
2465
2584
  }
2466
- if (child.type === "hyperlink" || child.type === "inlineWrapper") visitRunsIn(child.type === "hyperlink" ? child.children : child.content, visit);
2585
+ if (child.type === "hyperlink" || child.type === "inlineWrapper" || child.type === "insertion" || child.type === "deletion" || child.type === "moveFrom" || child.type === "moveTo") visitRunsIn(child.type === "hyperlink" ? child.children : child.content, visit);
2467
2586
  }
2468
2587
  };
2469
2588
  const visitRuns = (visit) => {
@@ -2578,6 +2697,7 @@ function createImageRun(node) {
2578
2697
  },
2579
2698
  wrap
2580
2699
  };
2700
+ if (attrs.pictureNames != null) image.pictureNames = { ...attrs.pictureNames };
2581
2701
  if (attrs.docPrName != null) image.docPrName = attrs.docPrName;
2582
2702
  if (attrs.alt != null) image.alt = attrs.alt;
2583
2703
  if (attrs.title != null) image.title = attrs.title;
@@ -3308,7 +3428,7 @@ function convertPMTextBox(node, styleResolver = null) {
3308
3428
  * Preserves all non-content parts of the original document
3309
3429
  */
3310
3430
  function updateDocumentContent(originalDocument, pmDoc) {
3311
- return fromProseDoc(pmDoc, originalDocument);
3431
+ return fromProseDoc(pmDoc, originalDocument, { stylesheetSource: { type: "package" } });
3312
3432
  }
3313
3433
  /**
3314
3434
  * Convert a ProseMirror document back to an array of `BlockContent` blocks