@stll/folio-core 0.53.0 → 0.54.1

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 (155) hide show
  1. package/dist/ai-edits/apply.js +415 -166
  2. package/dist/ai-edits/batch-claims.d.ts +21 -6
  3. package/dist/ai-edits/batch-claims.js +47 -16
  4. package/dist/ai-edits/headless.d.ts +20 -0
  5. package/dist/ai-edits/headless.js +140 -11
  6. package/dist/ai-edits/pending-suggestions.js +1 -1
  7. package/dist/ai-edits/read.d.ts +5 -3
  8. package/dist/ai-edits/read.js +97 -47
  9. package/dist/ai-edits/revisionStretches.d.ts +17 -0
  10. package/dist/ai-edits/revisionStretches.js +80 -0
  11. package/dist/ai-edits/snapshot.js +3 -2
  12. package/dist/ai-edits/table-cell-mutations.d.ts +3 -1
  13. package/dist/ai-edits/table-cell-mutations.js +2 -1
  14. package/dist/ai-edits/table-row-column-mutations.d.ts +6 -1
  15. package/dist/ai-edits/table-row-column-mutations.js +27 -10
  16. package/dist/compare/content-alignment.d.ts +5 -1
  17. package/dist/compare/content-alignment.js +39 -32
  18. package/dist/compare/inline-provenance.js +1 -1
  19. package/dist/controller/layoutPipeline.js +3 -2
  20. package/dist/docx/archiveInflation.d.ts +127 -0
  21. package/dist/docx/archiveInflation.js +181 -0
  22. package/dist/docx/metadataPrivacy.js +24 -1
  23. package/dist/docx/noteReferenceMark.d.ts +15 -0
  24. package/dist/docx/noteReferenceMark.js +48 -0
  25. package/dist/docx/paragraphParser.js +5 -3
  26. package/dist/docx/paragraphPropertySource.d.ts +1 -1
  27. package/dist/docx/paragraphPropertySource.js +4 -2
  28. package/dist/docx/parser.js +2 -2
  29. package/dist/docx/rezip.js +4 -2
  30. package/dist/docx/selectiveXmlPatch.d.ts +3 -1
  31. package/dist/docx/selectiveXmlPatch.js +81 -3
  32. package/dist/docx/server/boundedArchive.d.ts +8 -13
  33. package/dist/docx/server/boundedArchive.js +70 -59
  34. package/dist/docx/server/extractDocxText.d.ts +8 -2
  35. package/dist/docx/server/extractDocxText.js +2 -2
  36. package/dist/docx/server/validateDocxConformance.d.ts +1 -1
  37. package/dist/docx/server/validateDocxConformance.js +1 -0
  38. package/dist/docx/unzip.d.ts +19 -2
  39. package/dist/docx/unzip.js +135 -24
  40. package/dist/docx/verticalMergeProjection.d.ts +17 -0
  41. package/dist/docx/verticalMergeProjection.js +120 -0
  42. package/dist/fonts/embeddedFonts.js +1 -1
  43. package/dist/i18n/messages/catalogs.gen.d.ts +34 -34
  44. package/dist/i18n/messages/catalogs.gen.js +34 -34
  45. package/dist/i18n/messages/messages.gen.d.ts +2 -2
  46. package/dist/internal/wholeStoryRevisionResolution.js +95 -25
  47. package/dist/layout-engine/measure/measureParagraph.js +2 -2
  48. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
  49. package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
  50. package/dist/markdown/escape.d.ts +2 -2
  51. package/dist/markdown/escape.js +4 -5
  52. package/dist/markdown/renderBlock.js +91 -25
  53. package/dist/markdown/renderRuns.d.ts +10 -1
  54. package/dist/markdown/renderRuns.js +320 -59
  55. package/dist/prosemirror/clearRunColor.d.ts +6 -0
  56. package/dist/prosemirror/clearRunColor.js +46 -0
  57. package/dist/prosemirror/commands/comments.js +62 -22
  58. package/dist/prosemirror/commands/formatPainter.js +1 -1
  59. package/dist/prosemirror/commands/hyperlink.js +2 -1
  60. package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
  61. package/dist/prosemirror/commands/propertyChangeScope.js +28 -4
  62. package/dist/prosemirror/commands/resolveAllTableChanges.js +40 -41
  63. package/dist/prosemirror/commands/resolveParagraphProperties.js +33 -8
  64. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +7 -1
  65. package/dist/prosemirror/commands/tableCellMergeResolution.js +39 -20
  66. package/dist/prosemirror/commands/tableMergeFoldDecisions.d.ts +61 -0
  67. package/dist/prosemirror/commands/tableMergeFoldDecisions.js +79 -0
  68. package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
  69. package/dist/prosemirror/containerFinalParagraph.js +7 -6
  70. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  71. package/dist/prosemirror/conversion/fromProseDoc.js +12 -590
  72. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -13
  73. package/dist/prosemirror/conversion/toProseDoc.js +28 -262
  74. package/dist/prosemirror/documentSchema.d.ts +8 -0
  75. package/dist/prosemirror/documentSchema.js +18 -0
  76. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  77. package/dist/prosemirror/extensions/core/ParagraphExtension.js +104 -63
  78. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -1
  79. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
  80. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
  81. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
  82. package/dist/prosemirror/extensions/features/ListExtension.js +10 -9
  83. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
  84. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -4
  85. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +14 -8
  86. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
  87. package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
  88. package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
  89. package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
  90. package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
  91. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -6
  92. package/dist/prosemirror/extensions/marks/markUtils.js +17 -8
  93. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +3 -1
  94. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +12 -1
  95. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
  96. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
  97. package/dist/prosemirror/extensions/nodes/TableExtension.js +104 -210
  98. package/dist/prosemirror/extensions/types.d.ts +7 -0
  99. package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
  100. package/dist/prosemirror/hyperlinkRemoval.js +129 -0
  101. package/dist/prosemirror/index.d.ts +2 -1
  102. package/dist/prosemirror/index.js +2 -1
  103. package/dist/prosemirror/listNumbering.d.ts +3 -21
  104. package/dist/prosemirror/listNumbering.js +24 -39
  105. package/dist/prosemirror/listRendering.d.ts +29 -0
  106. package/dist/prosemirror/listRendering.js +26 -0
  107. package/dist/prosemirror/markupViewNotes.d.ts +8 -0
  108. package/dist/prosemirror/markupViewNotes.js +49 -0
  109. package/dist/prosemirror/markupViewProjection.d.ts +3 -1
  110. package/dist/prosemirror/markupViewProjection.js +7 -2
  111. package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
  112. package/dist/prosemirror/noteReferenceReview.js +332 -0
  113. package/dist/prosemirror/paragraphIndentation.js +5 -2
  114. package/dist/prosemirror/paragraphMarkJoin.d.ts +6 -4
  115. package/dist/prosemirror/paragraphMarkJoin.js +21 -19
  116. package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
  117. package/dist/prosemirror/paragraphPropertyCarry.js +155 -0
  118. package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
  119. package/dist/prosemirror/plugins/documentStyleState.js +32 -0
  120. package/dist/prosemirror/plugins/documentStyles.d.ts +2 -21
  121. package/dist/prosemirror/plugins/documentStyles.js +66 -29
  122. package/dist/prosemirror/plugins/index.d.ts +2 -1
  123. package/dist/prosemirror/plugins/index.js +2 -1
  124. package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
  125. package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
  126. package/dist/prosemirror/plugins/suggestionMode.d.ts +12 -2
  127. package/dist/prosemirror/plugins/suggestionMode.js +387 -28
  128. package/dist/prosemirror/plugins/templateDirectives.d.ts +6 -0
  129. package/dist/prosemirror/plugins/templateDirectives.js +21 -7
  130. package/dist/prosemirror/plugins/templatePreviewValues.js +14 -21
  131. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +22 -2
  132. package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
  133. package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
  134. package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
  135. package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
  136. package/dist/prosemirror/runFormattingFromMarks.js +567 -0
  137. package/dist/prosemirror/runFormattingReconciliation.js +10 -9
  138. package/dist/prosemirror/schema/nodes.d.ts +2 -0
  139. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
  140. package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
  141. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
  142. package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
  143. package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
  144. package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
  145. package/dist/prosemirror/tableCellPaste.d.ts +74 -0
  146. package/dist/prosemirror/tableCellPaste.js +525 -0
  147. package/dist/prosemirror/tableGridMutation.d.ts +53 -14
  148. package/dist/prosemirror/tableGridMutation.js +166 -18
  149. package/dist/prosemirror/tableRunIn.d.ts +51 -0
  150. package/dist/prosemirror/tableRunIn.js +165 -0
  151. package/dist/prosemirror/textInput.js +11 -2
  152. package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
  153. package/dist/prosemirror/trackedRevisionPath.js +32 -0
  154. package/dist/server.d.ts +2 -2
  155. package/package.json +6 -6
@@ -0,0 +1,129 @@
1
+ import { BUILT_IN_STYLE_NAME } from "../docx/builtInStyles.js";
2
+ import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "./plugins/documentStyleState.js";
3
+ import { isSuggestionModeActive, makeRevisionInfo, suggestRangeDeletion } from "./plugins/suggestionMode.js";
4
+ import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "./runFormattingReconciliation.js";
5
+ import { paragraphRunStyleContextAt } from "./runStyleFormatting.js";
6
+ //#region src/prosemirror/hyperlinkRemoval.ts
7
+ /** Contiguous stretches of linked, not yet deleted, text in [`from`, `to`) of `doc`. */
8
+ const linkedRanges = (doc, from, to) => {
9
+ const ranges = [];
10
+ doc.nodesBetween(from, to, (node, position) => {
11
+ if (!node.isText || !node.marks.some(({ type }) => type.name === "hyperlink") || node.marks.some(({ type }) => type.name === "deletion")) return true;
12
+ const start = Math.max(position, from);
13
+ const end = Math.min(position + node.nodeSize, to);
14
+ if (start >= end) return true;
15
+ const piece = {
16
+ from: start,
17
+ to: end,
18
+ node: node.cut(start - position, end - position)
19
+ };
20
+ const last = ranges.at(-1);
21
+ if (last && last.to === start) {
22
+ last.to = end;
23
+ last.pieces.push(piece);
24
+ } else ranges.push({
25
+ from: start,
26
+ to: end,
27
+ pieces: [piece]
28
+ });
29
+ return true;
30
+ });
31
+ return ranges;
32
+ };
33
+ /** A piece's marks once the Hyperlink character style is taken off it. */
34
+ const withoutHyperlinkStyle = (state, doc, piece) => {
35
+ const styleResolver = getDocumentStyleResolver(state);
36
+ const builtInStyles = getDocumentBuiltInStyles(state);
37
+ const context = paragraphRunStyleContextAt({
38
+ doc,
39
+ pos: piece.from,
40
+ styleResolver
41
+ });
42
+ const previousFormatting = readAuthoredRunFormatting({
43
+ context,
44
+ marks: piece.node.marks,
45
+ styleResolver
46
+ });
47
+ const styleId = previousFormatting.styleId;
48
+ if (!(styleId !== void 0 && (builtInStyles.builtInNameOf(styleId) === BUILT_IN_STYLE_NAME.hyperlink || styleId === "Hyperlink"))) return {
49
+ marks: piece.node.marks,
50
+ previousFormatting: null
51
+ };
52
+ const { styleId: _removed, ...formatting } = previousFormatting;
53
+ return {
54
+ marks: reconcileRunFormattingMarks({
55
+ authoredFormatting: formatting,
56
+ context,
57
+ node: piece.node,
58
+ styleResolver
59
+ }),
60
+ previousFormatting
61
+ };
62
+ };
63
+ /** Replace the marks of the text at [`from`, `to`) of `tr.doc` with `marks`. */
64
+ const setTextMarks = (tr, from, to, current, marks) => {
65
+ for (const mark of current) if (!mark.isInSet(marks)) tr.removeMark(from, to, mark);
66
+ for (const mark of marks) if (!mark.isInSet(current)) tr.addMark(from, to, mark);
67
+ };
68
+ /**
69
+ * Remove the hyperlinks from [`from`, `to`) of `tr.doc`: directly, or, with
70
+ * suggestions on, as a tracked replacement of the linked text by plain text.
71
+ */
72
+ const removeHyperlinkInRange = (state, tr, from, to) => {
73
+ const { schema } = state;
74
+ const hyperlinkType = schema.marks["hyperlink"];
75
+ if (!hyperlinkType) return tr;
76
+ const insertionType = schema.marks["insertion"];
77
+ const deletionType = schema.marks["deletion"];
78
+ const propertyChangeType = schema.marks["runPropertyChange"];
79
+ const tracked = isSuggestionModeActive(state) && insertionType !== void 0 && deletionType !== void 0 && propertyChangeType !== void 0;
80
+ const revisionAttrs = () => {
81
+ const revision = makeRevisionInfo(state);
82
+ return revision ? {
83
+ id: revision.id,
84
+ author: revision.author,
85
+ date: revision.date
86
+ } : null;
87
+ };
88
+ const insertionInfo = tracked ? revisionAttrs() : null;
89
+ const insertion = insertionType && insertionInfo ? insertionType.create({
90
+ revisionId: insertionInfo.id,
91
+ author: insertionInfo.author,
92
+ date: insertionInfo.date
93
+ }) : null;
94
+ const propertyChange = (previousFormatting) => {
95
+ const info = revisionAttrs();
96
+ if (!propertyChangeType || !info) return null;
97
+ const change = {
98
+ type: "runPropertyChange",
99
+ info,
100
+ previousFormatting
101
+ };
102
+ return propertyChangeType.create({ changes: [change] });
103
+ };
104
+ const hasPendingPropertyChange = (marks) => marks.some(({ type }) => type === propertyChangeType);
105
+ for (const range of linkedRanges(tr.doc, from, to).toReversed()) {
106
+ const unlinked = range.pieces.map((piece) => ({
107
+ piece,
108
+ ...withoutHyperlinkStyle(state, tr.doc, piece)
109
+ }));
110
+ if (!insertion || !deletionType) {
111
+ for (const { piece, marks } of unlinked) setTextMarks(tr, piece.from, piece.to, piece.node.marks, marks.filter(({ type }) => type !== hyperlinkType));
112
+ continue;
113
+ }
114
+ const plain = unlinked.map(({ piece, marks, previousFormatting }) => {
115
+ const change = previousFormatting && !hasPendingPropertyChange(marks) ? propertyChange(previousFormatting) : null;
116
+ const kept = marks.filter(({ type }) => type !== hyperlinkType && type !== insertionType && type !== deletionType);
117
+ return piece.node.mark(insertion.addToSet(change ? change.addToSet(kept) : kept));
118
+ });
119
+ tr.insert(range.to, plain);
120
+ for (const { piece, marks, previousFormatting } of unlinked.toReversed()) {
121
+ const change = previousFormatting && !hasPendingPropertyChange(piece.node.marks) ? propertyChange(previousFormatting) : null;
122
+ setTextMarks(tr, piece.from, piece.to, piece.node.marks, change ? change.addToSet(marks) : marks);
123
+ }
124
+ suggestRangeDeletion(state, tr, range.from, range.to);
125
+ }
126
+ return tr;
127
+ };
128
+ //#endregion
129
+ export { removeHyperlinkInRange };
@@ -25,7 +25,8 @@ import { SelectionChangeCallback, SelectionContext, createSelectionTrackerPlugin
25
25
  import { ensureParaIdsInState } from "./extensions/features/ParaIdAllocatorExtension.js";
26
26
  import "./styles/index.js";
27
27
  import { SelectionState, extractSelectionState } from "./selectionState.js";
28
- import { createDocumentStylesPlugin, documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./plugins/documentStyles.js";
28
+ import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./plugins/documentStyleState.js";
29
+ import { createDocumentStylesPlugin } from "./plugins/documentStyles.js";
29
30
  import "./plugins/index.js";
30
31
  import { insertPageBreakInView, insertTableInView, insertTableOfContentsInView } from "./insertOperations.js";
31
32
  import { TextSelection } from "prosemirror-state";
@@ -15,7 +15,8 @@ import { getTableContext, isInTable as isInTableCell } from "./extensions/nodes/
15
15
  import { insertPageBreakInView, insertTableInView, insertTableOfContentsInView } from "./insertOperations.js";
16
16
  import { NO_LIST_NUMBERING_MENU, listNumberingMenuState } from "./listNumbering.js";
17
17
  import { NO_LIST_STATE, isInListState, listStateLevel, resolveListState, sameListState } from "./listState.js";
18
- import { createDocumentStylesPlugin, documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./plugins/documentStyles.js";
18
+ import { documentStylesKey, getDocumentBuiltInStyles, getDocumentStyleResolver } from "./plugins/documentStyleState.js";
19
+ import { createDocumentStylesPlugin } from "./plugins/documentStyles.js";
19
20
  import { createSelectionTrackerPlugin, extractSelectionContext, getSelectionContext, selectionTrackerKey } from "./plugins/selectionTracker.js";
20
21
  import { schema, singletonManager } from "./schema/index.js";
21
22
  import { extractSelectionState } from "./selectionState.js";
@@ -1,5 +1,5 @@
1
1
  import { ListKind, ListLevelFormat } from "../docx/listNumberingInstances.js";
2
- import { ParagraphAttrs, ParagraphPropertyChangeAttrs } from "./schema/nodes.js";
2
+ import { ParagraphAttrs } from "./schema/nodes.js";
3
3
  import { NumberingMap } from "../docx/numberingParser.js";
4
4
  import { Node, ResolvedPos } from "prosemirror-model";
5
5
  import { Command, EditorState, Transaction } from "prosemirror-state";
@@ -15,24 +15,6 @@ type ListRequest = {
15
15
  /** The value a new list's first item shows. */
16
16
  start?: number | undefined;
17
17
  };
18
- type PreviousFormatting = NonNullable<ParagraphPropertyChangeAttrs["previousFormatting"]>;
19
- /**
20
- * The list rendering a paragraph takes when a `w:pPrChange` is rejected. A
21
- * reject restores the recorded numbering, but the rendering attrs sit outside
22
- * the scope it restores wholesale, so a record that does not state them (one
23
- * written by an operation, or read from a file) would leave the rendering of
24
- * the numbering it undoes: a paragraph restored to no numbering still showed
25
- * the marker it was given. When the reject changes the numbering, the
26
- * rendering is recomputed from the restored numbering; otherwise it stays.
27
- */
28
- type RejectedListRenderingOptions = {
29
- /** The paragraph's attrs before the reject. */
30
- current: Pick<ParagraphAttrs, "numPr">;
31
- /** The previous state the rejected record restores. */
32
- previousFormatting: PreviousFormatting | null | undefined;
33
- numbering: NumberingMap | null;
34
- };
35
- declare const rejectedListRenderingPatch: ({ current, previousFormatting, numbering }: RejectedListRenderingOptions) => Record<string, unknown>;
36
18
  /** Where the paragraphs a command numbers go. */
37
19
  type ListTarget = {
38
20
  numId: number;
@@ -56,7 +38,7 @@ type ResolveListTargetOptions = {
56
38
  */
57
39
  declare const resolveListTarget: ({ numbering, $from, $to, requests }: ResolveListTargetOptions) => ListTarget | null;
58
40
  /** A paragraph's attrs as an item of `numId` at `ilvl`, resolved in `numbering`. */
59
- declare const listItemAttrs: (attrs: Record<string, unknown>, { numId, ilvl }: {
41
+ declare const listItemAttrs: (attrs: Readonly<ParagraphAttrs>, { numId, ilvl }: {
60
42
  numId: number;
61
43
  ilvl: number;
62
44
  }, numbering: NumberingMap) => Record<string, unknown>;
@@ -107,4 +89,4 @@ declare const NO_LIST_NUMBERING_MENU: {
107
89
  */
108
90
  declare const listNumberingMenuState: (state: EditorState) => ListNumberingMenuState;
109
91
  //#endregion
110
- export { ListNumberingMenuState, ListRequest, NO_LIST_NUMBERING_MENU, RejectedListRenderingOptions, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, rejectedListRenderingPatch, resolveListTarget, restartNumbering, setNumberingValue };
92
+ export { ListNumberingMenuState, ListRequest, NO_LIST_NUMBERING_MENU, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, resolveListTarget, restartNumbering, setNumberingValue };
@@ -1,13 +1,15 @@
1
1
  import { mintListInstance, restartListInstance } from "../docx/listNumberingInstances.js";
2
2
  import { createNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
3
- import { paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering } from "../docx/numberingReference.js";
3
+ import { paragraphNumberingLevel, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
4
4
  import { expectParagraphAttrs } from "./attrs/index.js";
5
5
  import { paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
6
- import { CLEARED_LIST_RENDERING_ATTRS } from "./listMarker.js";
6
+ import { listRenderingFor, recordsListRendering } from "./listRendering.js";
7
7
  import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
8
+ import { directParagraphIndentation } from "./paragraphIndentation.js";
8
9
  import { getDocumentNumbering } from "./plugins/documentNumbering.js";
10
+ import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
9
11
  import { SUGGESTION_META, makeRevisionInfo } from "./plugins/suggestionMode.js";
10
- import { listAttrsFromNumbering } from "./styles/resolvedStyleAttrs.js";
12
+ import { listAttrsFromNumbering, listLevelIndentAttrPatch } from "./styles/resolvedStyleAttrs.js";
11
13
  //#region src/prosemirror/listNumbering.ts
12
14
  const PARAGRAPH_NODE = "paragraph";
13
15
  /**
@@ -19,45 +21,18 @@ const PARAGRAPH_NODE = "paragraph";
19
21
  */
20
22
  const listChangeSnapshot = (node, attrs) => {
21
23
  const previousFormatting = paragraphPropertiesSnapshot(node.type.create(attrs, node.content, node.marks));
22
- previousFormatting["numPr"] = attrs["numPr"] ?? null;
24
+ previousFormatting["numPr"] ??= null;
23
25
  for (const key of LIST_RENDERING_ATTR_KEYS) previousFormatting[key] = attrs[key] ?? null;
24
26
  return previousFormatting;
25
27
  };
26
- /**
27
- * The original state a pending record describes, completed with the list
28
- * attrs it may not state. A record written by a list command states them all.
29
- * One written for another property (or read from a file) states the scope
30
- * only: its numbering is the original's, and an absent one means the original
31
- * had none, so the rendering is recomputed from it rather than copied from
32
- * the live paragraph, whose list may since have changed.
33
- */
34
- const originalListFormatting = (record, numbering) => {
28
+ const originalListFormatting = ({ record, numbering, styleResolver }) => {
35
29
  const original = { ...record };
36
30
  if (recordsListRendering(record)) return original;
37
- Object.assign(original, listRenderingFor(record.numPr, numbering));
31
+ const inherited = styleResolver?.resolveParagraphStyle(record.styleId ?? void 0).paragraphFormatting?.numPr;
32
+ Object.assign(original, listRenderingFor(record.numPr ?? inherited, numbering));
38
33
  original["numPr"] = record.numPr ?? null;
39
34
  return original;
40
35
  };
41
- /** Whether a `w:pPrChange` record states the list rendering it had (a list command's does). */
42
- const recordsListRendering = (record) => LIST_RENDERING_ATTR_KEYS.some((key) => Object.hasOwn(record, key));
43
- /** Every list-rendering attr for `numPr`: its level's, or all cleared when it numbers nothing. */
44
- const listRenderingFor = (numPr, numbering) => {
45
- const numId = paragraphNumberingReferenceId(numPr ?? void 0);
46
- const rendering = numId === void 0 ? CLEARED_LIST_RENDERING_ATTRS : listAttrsFromNumbering({
47
- numId,
48
- ilvl: paragraphNumberingLevel(numPr ?? void 0) ?? 0
49
- }, numbering);
50
- const attrs = {};
51
- for (const key of LIST_RENDERING_ATTR_KEYS) attrs[key] = rendering[key] ?? null;
52
- return attrs;
53
- };
54
- const rejectedListRenderingPatch = ({ current, previousFormatting, numbering }) => {
55
- const record = previousFormatting ?? {};
56
- if (recordsListRendering(record)) return {};
57
- const restored = record.numPr ?? void 0;
58
- if (sameStatedParagraphNumbering(restored, current.numPr ?? void 0)) return {};
59
- return listRenderingFor(restored, numbering);
60
- };
61
36
  const canonicalJson = (value) => JSON.stringify(value, (_key, nested) => nested !== null && typeof nested === "object" && !Array.isArray(nested) ? Object.fromEntries(Object.entries(nested).filter(([, entry]) => entry !== null && entry !== void 0).toSorted(([left], [right]) => left.localeCompare(right))) : nested);
62
37
  /**
63
38
  * `next` with the list change recorded as a tracked paragraph-property change.
@@ -73,12 +48,16 @@ const canonicalJson = (value) => JSON.stringify(value, (_key, nested) => nested
73
48
  * the file) keeps its author, id and date: the change joins that revision
74
49
  * rather than re-attributing it, and it is never dropped.
75
50
  */
76
- const trackListChange = ({ current, next, rev, numbering }) => {
51
+ const trackListChange = ({ current, next, rev, numbering, styleResolver }) => {
77
52
  const currentAttrs = expectParagraphAttrs(current);
78
53
  const existing = currentAttrs._propertyChanges ?? [];
79
54
  const pending = existing.find(({ info }) => info.provenance !== "suggested");
80
55
  const retained = existing.filter((change) => change !== pending);
81
- const previousFormatting = pending?.previousFormatting ? originalListFormatting(pending.previousFormatting, numbering) : listChangeSnapshot(current, currentAttrs);
56
+ const previousFormatting = pending?.previousFormatting ? originalListFormatting({
57
+ record: pending.previousFormatting,
58
+ numbering,
59
+ styleResolver
60
+ }) : listChangeSnapshot(current, currentAttrs);
82
61
  const ownPending = pending !== void 0 && pending.info.author === rev.author;
83
62
  if (ownPending && canonicalJson(previousFormatting) === canonicalJson(listChangeSnapshot(current, next))) return {
84
63
  ...next,
@@ -203,6 +182,10 @@ const listItemAttrs = (attrs, { numId, ilvl }, numbering) => ({
203
182
  numId,
204
183
  ilvl
205
184
  }, numbering),
185
+ ...listLevelIndentAttrPatch(directParagraphIndentation(attrs), {
186
+ numId,
187
+ ilvl
188
+ }, numbering),
206
189
  listImplicitChildLevelAdvances: attrs["listImplicitChildLevelAdvances"] ?? null,
207
190
  listMarkerSecondSlotOffsetTwips: attrs["listMarkerSecondSlotOffsetTwips"] ?? null
208
191
  });
@@ -213,12 +196,14 @@ const listItemAttrs = (attrs, { numId, ilvl }, numbering) => ({
213
196
  const applyParagraphUpdates = ({ tr, state, updates }) => {
214
197
  const rev = makeRevisionInfo(state);
215
198
  const numbering = getDocumentNumbering(state);
199
+ const styleResolver = getDocumentStyleResolver(state);
216
200
  for (const { pos, node, next } of updates) {
217
201
  const attrs = rev ? trackListChange({
218
202
  current: node,
219
203
  next,
220
204
  rev,
221
- numbering
205
+ numbering,
206
+ styleResolver
222
207
  }) : next;
223
208
  tr.setNodeMarkup(pos, void 0, attrs);
224
209
  }
@@ -261,7 +246,7 @@ const moveItems = ({ state, items, numId, numbering }) => {
261
246
  updates: items.map(({ pos, node, membership }) => ({
262
247
  pos,
263
248
  node,
264
- next: listItemAttrs(node.attrs, {
249
+ next: listItemAttrs(expectParagraphAttrs(node), {
265
250
  numId,
266
251
  ilvl: membership.ilvl
267
252
  }, numbering)
@@ -342,4 +327,4 @@ const listNumberingMenuState = (state) => restartNumbering(state) ? {
342
327
  canContinue: continueNumbering(state)
343
328
  } : NO_LIST_NUMBERING_MENU;
344
329
  //#endregion
345
- export { NO_LIST_NUMBERING_MENU, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, rejectedListRenderingPatch, resolveListTarget, restartNumbering, setNumberingValue };
330
+ export { NO_LIST_NUMBERING_MENU, applyParagraphUpdates, continueNumbering, listItemAttrs, listNumberingMenuState, resolveListTarget, restartNumbering, setNumberingValue };
@@ -0,0 +1,29 @@
1
+ import { ParagraphAttrs, ParagraphPropertyChangeAttrs } from "./schema/nodes.js";
2
+ import { NumberingMap } from "../docx/numberingParser.js";
3
+ import { ParagraphNumberingOverride } from "../docx/numberingReference.js";
4
+ //#region src/prosemirror/listRendering.d.ts
5
+ type PreviousFormatting = NonNullable<ParagraphPropertyChangeAttrs["previousFormatting"]>;
6
+ /** Whether a `w:pPrChange` record states the list rendering it had (a list command's does). */
7
+ declare const recordsListRendering: (record: PreviousFormatting) => boolean;
8
+ /** Every list-rendering attr for `numPr`: its level's, or all cleared when it numbers nothing. */
9
+ declare const listRenderingFor: (numPr: ParagraphNumberingOverride | null | undefined, numbering: NumberingMap | null) => Record<string, unknown>;
10
+ /**
11
+ * The list rendering a paragraph takes when a `w:pPrChange` is rejected. A
12
+ * reject restores the recorded numbering, but the rendering attrs sit outside
13
+ * the scope it restores wholesale, so a record that does not state them (one
14
+ * written by an operation, or read from a file) would leave the rendering of
15
+ * the numbering it undoes: a paragraph restored to no numbering still showed
16
+ * the marker it was given. When the reject changes the numbering, the
17
+ * rendering is recomputed from the restored numbering; otherwise it stays.
18
+ */
19
+ type RejectedListRenderingOptions = {
20
+ /** The paragraph's attrs before the reject. */
21
+ current: Pick<ParagraphAttrs, "numPr">;
22
+ /** The previous state the rejected record restores. */
23
+ previousFormatting: PreviousFormatting | null | undefined;
24
+ numbering: NumberingMap | null;
25
+ restoredNumbering: ParagraphAttrs["numPr"] | null;
26
+ };
27
+ declare const rejectedListRenderingPatch: ({ current, previousFormatting, numbering, restoredNumbering }: RejectedListRenderingOptions) => Record<string, unknown>;
28
+ //#endregion
29
+ export { RejectedListRenderingOptions, listRenderingFor, recordsListRendering, rejectedListRenderingPatch };
@@ -0,0 +1,26 @@
1
+ import { paragraphNumberingLevel, paragraphNumberingReferenceId, sameStatedParagraphNumbering } from "../docx/numberingReference.js";
2
+ import { CLEARED_LIST_RENDERING_ATTRS } from "./listMarker.js";
3
+ import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
4
+ import { listAttrsFromNumbering } from "./styles/resolvedStyleAttrs.js";
5
+ //#region src/prosemirror/listRendering.ts
6
+ /** Whether a `w:pPrChange` record states the list rendering it had (a list command's does). */
7
+ const recordsListRendering = (record) => LIST_RENDERING_ATTR_KEYS.some((key) => Object.hasOwn(record, key));
8
+ /** Every list-rendering attr for `numPr`: its level's, or all cleared when it numbers nothing. */
9
+ const listRenderingFor = (numPr, numbering) => {
10
+ const numId = paragraphNumberingReferenceId(numPr ?? void 0);
11
+ const rendering = numId === void 0 ? CLEARED_LIST_RENDERING_ATTRS : listAttrsFromNumbering({
12
+ numId,
13
+ ilvl: paragraphNumberingLevel(numPr ?? void 0) ?? 0
14
+ }, numbering);
15
+ const attrs = {};
16
+ for (const key of LIST_RENDERING_ATTR_KEYS) attrs[key] = rendering[key] ?? null;
17
+ return attrs;
18
+ };
19
+ const rejectedListRenderingPatch = ({ current, previousFormatting, numbering, restoredNumbering }) => {
20
+ if (recordsListRendering(previousFormatting ?? {})) return {};
21
+ const restored = restoredNumbering ?? void 0;
22
+ if (sameStatedParagraphNumbering(restored, current.numPr ?? void 0)) return {};
23
+ return listRenderingFor(restored, numbering);
24
+ };
25
+ //#endregion
26
+ export { listRenderingFor, recordsListRendering, rejectedListRenderingPatch };
@@ -0,0 +1,8 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { DisplayMode } from "../managers/EditorModeManager.js";
3
+ import { EditorState } from "prosemirror-state";
4
+ //#region src/prosemirror/markupViewNotes.d.ts
5
+ /** The footnotes or endnotes as `view` shows them. */
6
+ declare const markupViewNotes: <TNote extends document_d_exports.Footnote | document_d_exports.Endnote>(notes: TNote[] | undefined, view: DisplayMode, state: EditorState, document: document_d_exports.Document | null) => TNote[] | undefined;
7
+ //#endregion
8
+ export { markupViewNotes };
@@ -0,0 +1,49 @@
1
+ import { resolveWholeStory } from "../internal/wholeStoryRevisionResolution.js";
2
+ import { proseDocToBlocks } from "./conversion/fromProseDoc.js";
3
+ import { footnoteToProseDoc } from "./conversion/toProseDoc.js";
4
+ import { markupViewResolutionMode } from "./markupViewProjection.js";
5
+ import { getDocumentNumbering } from "./plugins/documentNumbering.js";
6
+ import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
7
+ //#region src/prosemirror/markupViewNotes.ts
8
+ const resolvedNotes = /* @__PURE__ */ new WeakMap();
9
+ const resolvedNote = (note, mode, state, document) => {
10
+ const styleResolver = getDocumentStyleResolver(state);
11
+ const cached = resolvedNotes.get(note)?.get(mode);
12
+ if (cached?.styleResolver === styleResolver) return cached.note;
13
+ const { styles, theme } = document.package;
14
+ const doc = footnoteToProseDoc(note.content, {
15
+ ...styles !== void 0 && { styles },
16
+ ...theme !== void 0 && { theme }
17
+ });
18
+ const result = resolveWholeStory({
19
+ doc,
20
+ mode,
21
+ styleResolver,
22
+ numbering: getDocumentNumbering(state)
23
+ });
24
+ const resolved = result.failed || result.resolved.eq(doc) ? note : {
25
+ ...note,
26
+ content: proseDocToBlocks(result.resolved, note.content, styles)
27
+ };
28
+ const byMode = resolvedNotes.get(note) ?? /* @__PURE__ */ new Map();
29
+ byMode.set(mode, {
30
+ styleResolver,
31
+ note: resolved
32
+ });
33
+ resolvedNotes.set(note, byMode);
34
+ return resolved;
35
+ };
36
+ /** The footnotes or endnotes as `view` shows them. */
37
+ const markupViewNotes = (notes, view, state, document) => {
38
+ const mode = markupViewResolutionMode(view);
39
+ if (!notes || !mode || !document) return notes;
40
+ let changed = false;
41
+ const shown = notes.map((note) => {
42
+ const resolved = resolvedNote(note, mode, state, document);
43
+ changed ||= resolved !== note;
44
+ return resolved;
45
+ });
46
+ return changed ? shown : notes;
47
+ };
48
+ //#endregion
49
+ export { markupViewNotes };
@@ -82,6 +82,8 @@ type MarkupViewProjection =
82
82
  * Cached per editor state: the resolver also reads its styles and numbering
83
83
  * plugins, which may change while the document node stays the same.
84
84
  */
85
+ /** How a view resolves the revisions it reads, or null when it shows them inline. */
86
+ declare const markupViewResolutionMode: (view: DisplayMode) => RevisionResolutionMode | null;
85
87
  declare const projectMarkupView: (state: EditorState, view: DisplayMode) => MarkupViewProjection;
86
88
  /**
87
89
  * Where a caret at editor `position` is painted in a view. A position the view
@@ -92,4 +94,4 @@ declare const projectMarkupView: (state: EditorState, view: DisplayMode) => Mark
92
94
  */
93
95
  declare const visibleCaretPosition: (projection: MarkupViewProjection, position: number) => number;
94
96
  //#endregion
95
- export { MarkupViewProjection, projectMarkupView, resolveStateStory, visibleCaretPosition };
97
+ export { MarkupViewProjection, markupViewResolutionMode, projectMarkupView, resolveStateStory, visibleCaretPosition };
@@ -2,7 +2,7 @@ import { indexedPositionMap } from "../internal/indexedPositionMap.js";
2
2
  import { finalRevisionParagraphRanges } from "../internal/revisionResolutionTracking.js";
3
3
  import { resolveWholeStory } from "../internal/wholeStoryRevisionResolution.js";
4
4
  import { getDocumentNumbering } from "./plugins/documentNumbering.js";
5
- import { getDocumentStyleResolver } from "./plugins/documentStyles.js";
5
+ import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
6
6
  import { Selection } from "prosemirror-state";
7
7
  //#region src/prosemirror/markupViewProjection.ts
8
8
  /** Resolve every revision in the state's story with the state's own styles and numbering. */
@@ -41,6 +41,11 @@ const projectionCache = /* @__PURE__ */ new WeakMap();
41
41
  * Cached per editor state: the resolver also reads its styles and numbering
42
42
  * plugins, which may change while the document node stays the same.
43
43
  */
44
+ /** How a view resolves the revisions it reads, or null when it shows them inline. */
45
+ const markupViewResolutionMode = (view) => {
46
+ const resolution = MARKUP_VIEW_RESOLUTIONS[view];
47
+ return resolution.type === "resolved" ? resolution.mode : null;
48
+ };
44
49
  const projectMarkupView = (state, view) => {
45
50
  const resolution = MARKUP_VIEW_RESOLUTIONS[view];
46
51
  if (resolution.type === "authored") return AUTHORED;
@@ -80,4 +85,4 @@ const visibleCaretPosition = (projection, position) => {
80
85
  return projection.toEditor(near.head, -1);
81
86
  };
82
87
  //#endregion
83
- export { projectMarkupView, resolveStateStory, visibleCaretPosition };
88
+ export { markupViewResolutionMode, projectMarkupView, resolveStateStory, visibleCaretPosition };
@@ -0,0 +1,77 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ import { Mark, Node } from "prosemirror-model";
3
+ import { Transform } from "prosemirror-transform";
4
+ //#region src/prosemirror/noteReferenceReview.d.ts
5
+ type NoteKind = "footnote" | "endnote";
6
+ /** `footnote:<id>` or `endnote:<id>`. */
7
+ type NoteKey = `${NoteKind}:${number}`;
8
+ /**
9
+ * The notes a story's text refers to, and whether each reference is pending
10
+ * deletion: a reference is deleted when every character of it is.
11
+ */
12
+ declare const noteReferenceStates: (doc: Node) => Map<NoteKey, "live" | "deleted">;
13
+ /** The notes whose reference a change took from pending deletion back to live. */
14
+ declare const noteReferencesRestored: (before: Node, after: Node) => NoteKey[];
15
+ /**
16
+ * The revisions that deleted a note along with its reference: its text and
17
+ * its paragraph marks, deleted by the reference deletion's author at its
18
+ * date. A deletion in the note made some other time is a change of its own,
19
+ * which resolving the reference leaves alone.
20
+ */
21
+ declare const noteDeletionRevisions: (doc: Node, reference: Mark) => number[];
22
+ /**
23
+ * The document with the named notes' deletions that went with their
24
+ * reference rejected: the notes whose reference's deletion was rejected get
25
+ * their text back. `before` is the body that still had those deletions.
26
+ */
27
+ declare const restoreNotes: (document: document_d_exports.Document, keys: Iterable<NoteKey>, before: Node) => document_d_exports.Document;
28
+ /** The deletion each pending-deleted note reference carries. */
29
+ declare const referenceDeletions: (doc: Node) => Map<NoteKey, Mark>;
30
+ /**
31
+ * Delete a note's text and its paragraph marks along with its reference: by
32
+ * the reference deletion's author at its date, so resolving the reference
33
+ * resolves them too (see {@link noteDeletionRevisions}).
34
+ */
35
+ declare const deleteNoteWithReference: <T extends Transform>(transform: T, reference: Mark) => T;
36
+ /**
37
+ * Keeps an editor's notes following their references across body edits. The
38
+ * editor reports the body as it was before the edits it has not yet written
39
+ * back, and reconciles the document it writes back:
40
+ *
41
+ * - a reference whose deletion is rejected gives its note back its text;
42
+ * - a reference deleted again, as undoing that reject does, takes the note's
43
+ * text with it: the note returns to what it was, or, when the note changed
44
+ * since, its text is deleted along with the reference.
45
+ */
46
+ type NoteReferenceFollower = {
47
+ /** The body before the edits the next {@link reconcile} writes back. */
48
+ noteBase: (before: Node) => void;
49
+ /** The document to write back, its notes following the body's references. */
50
+ reconcile: (document: document_d_exports.Document, body: Node) => document_d_exports.Document;
51
+ /**
52
+ * `document` with the note changes an earlier {@link reconcile} wrote back
53
+ * and the editor's document has not taken in yet: a save reads the editor
54
+ * right after a write-back, before the host hands the result back.
55
+ */
56
+ withPending: (document: document_d_exports.Document) => document_d_exports.Document;
57
+ /** Forget the pending base and what earlier restores replaced (a new document). */
58
+ reset: () => void;
59
+ };
60
+ declare const createNoteReferenceFollower: () => NoteReferenceFollower;
61
+ /** The notes model content refers to, live or pending deletion. */
62
+ declare const noteKeysReferencedIn: (content: unknown) => Set<NoteKey>;
63
+ /**
64
+ * The notes anything refers to, live or pending deletion: the main story, and
65
+ * the stories the body does not hold (headers, footers, comments, notes).
66
+ * References inside the `skipped` notes do not count: those notes are going.
67
+ */
68
+ declare const referencedNotes: (document: document_d_exports.Document, skipped?: ReadonlySet<string>) => Set<NoteKey>;
69
+ /**
70
+ * The document without the notes nothing refers to any more: a note goes
71
+ * with its reference, so accepting the reference's deletion leaves a note no
72
+ * reader can reach, and saving drops it, with the comments anchored only in
73
+ * it. Separators stay.
74
+ */
75
+ declare const withoutUnreferencedNotes: (document: document_d_exports.Document) => document_d_exports.Document;
76
+ //#endregion
77
+ export { NoteKey, NoteReferenceFollower, createNoteReferenceFollower, deleteNoteWithReference, noteDeletionRevisions, noteKeysReferencedIn, noteReferenceStates, noteReferencesRestored, referenceDeletions, referencedNotes, restoreNotes, withoutUnreferencedNotes };