@stll/folio-core 0.54.2 → 0.56.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 (267) hide show
  1. package/dist/ai-edits/apply.js +185 -33
  2. package/dist/ai-edits/headless.js +3 -2
  3. package/dist/ai-edits/types.d.ts +7 -1
  4. package/dist/compare/compare.js +1 -0
  5. package/dist/compare/content-types.d.ts +3 -15
  6. package/dist/compare/reproducible-package.d.ts +0 -17
  7. package/dist/compare/reproducible-package.js +12 -18
  8. package/dist/controller/canonicalClipboard.d.ts +23 -0
  9. package/dist/controller/canonicalClipboard.js +476 -0
  10. package/dist/controller/canonicalClipboardResources.d.ts +21 -0
  11. package/dist/controller/canonicalClipboardResources.js +382 -0
  12. package/dist/controller/canonicalComposition.d.ts +53 -0
  13. package/dist/controller/canonicalComposition.js +296 -0
  14. package/dist/controller/canonicalInlineProjection.d.ts +113 -0
  15. package/dist/controller/canonicalInlineProjection.js +393 -0
  16. package/dist/controller/canonicalInput.d.ts +54 -0
  17. package/dist/controller/canonicalInput.js +377 -0
  18. package/dist/controller/canonicalInputTimer.d.ts +7 -0
  19. package/dist/controller/canonicalInputTimer.js +11 -0
  20. package/dist/controller/canonicalOperations.d.ts +22 -0
  21. package/dist/controller/canonicalOperations.js +85 -0
  22. package/dist/controller/canonicalPublicOperations.d.ts +48 -0
  23. package/dist/controller/canonicalPublicOperations.js +556 -0
  24. package/dist/controller/canonicalReview.d.ts +12 -0
  25. package/dist/controller/canonicalReview.js +19 -0
  26. package/dist/controller/canonicalSession.d.ts +167 -0
  27. package/dist/controller/canonicalSession.js +1186 -0
  28. package/dist/controller/canonicalStoryEditor.d.ts +36 -0
  29. package/dist/controller/canonicalStoryEditor.js +87 -0
  30. package/dist/controller/canonicalStructure.d.ts +16 -0
  31. package/dist/controller/canonicalStructure.js +322 -0
  32. package/dist/controller/canonicalTocSelection.d.ts +11 -0
  33. package/dist/controller/canonicalTocSelection.js +43 -0
  34. package/dist/controller/folioEditor.d.ts +3 -10
  35. package/dist/controller/folioEditor.js +14 -4
  36. package/dist/controller/headerFooterEditorManager.d.ts +5 -0
  37. package/dist/controller/headerFooterEditorManager.js +72 -3
  38. package/dist/controller/hiddenEditorApi.d.ts +45 -0
  39. package/dist/controller/hiddenEditorApi.js +29 -8
  40. package/dist/controller/hiddenEditorManager.d.ts +13 -2
  41. package/dist/controller/hiddenEditorManager.js +639 -31
  42. package/dist/controller/layoutPipeline.d.ts +1 -1
  43. package/dist/controller/layoutPipeline.js +2 -0
  44. package/dist/controller/noteEditorManager.d.ts +5 -0
  45. package/dist/controller/noteEditorManager.js +114 -15
  46. package/dist/document-operations.d.ts +8 -1
  47. package/dist/document-operations.js +6 -4
  48. package/dist/docx/attributeRemainder.js +1 -0
  49. package/dist/docx/blockPlainText.d.ts +1 -1
  50. package/dist/docx/blockPlainText.js +11 -3
  51. package/dist/docx/canonicalResourceSave.d.ts +16 -0
  52. package/dist/docx/canonicalResourceSave.js +27 -0
  53. package/dist/docx/canonicalSave.d.ts +29 -0
  54. package/dist/docx/canonicalSave.js +101 -0
  55. package/dist/docx/canonicalSessionInput.d.ts +11 -0
  56. package/dist/docx/canonicalSessionInput.js +27 -0
  57. package/dist/docx/canonicalStoryRepack.d.ts +10 -0
  58. package/dist/docx/canonicalStoryRepack.js +74 -0
  59. package/dist/docx/contentTypeRegistry.d.ts +8 -0
  60. package/dist/docx/contentTypeRegistry.js +64 -0
  61. package/dist/docx/documentParser.d.ts +1 -13
  62. package/dist/docx/documentParser.js +1 -47
  63. package/dist/docx/ensureParaIds.d.ts +7 -1
  64. package/dist/docx/ensureParaIds.js +173 -215
  65. package/dist/docx/foldedListNumberFields.d.ts +85 -0
  66. package/dist/docx/foldedListNumberFields.js +267 -0
  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 +39 -1
  72. package/dist/docx/headerFooterVerbatim.js +173 -2
  73. package/dist/docx/imageParser.d.ts +13 -1
  74. package/dist/docx/imageParser.js +20 -11
  75. package/dist/docx/metadataPrivacy.js +6 -1
  76. package/dist/docx/noteIds.d.ts +5 -0
  77. package/dist/docx/noteIds.js +6 -2
  78. package/dist/docx/noteReferenceMark.d.ts +3 -1
  79. package/dist/docx/noteReferenceMark.js +15 -14
  80. package/dist/docx/numberingParser.d.ts +3 -1
  81. package/dist/docx/numberingParser.js +17 -3
  82. package/dist/docx/packageParts.d.ts +3 -1
  83. package/dist/docx/packageParts.js +74 -19
  84. package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
  85. package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
  86. package/dist/docx/paragraphParser.js +101 -53
  87. package/dist/docx/paragraphPropertySource.d.ts +15 -1
  88. package/dist/docx/paragraphPropertySource.js +77 -22
  89. package/dist/docx/parser.js +3 -1
  90. package/dist/docx/removeHeaderFooterParts.js +17 -6
  91. package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
  92. package/dist/docx/reviewHistoryNamespace.js +4 -0
  93. package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
  94. package/dist/docx/reviewResolutionProvenance.js +153 -0
  95. package/dist/docx/rezip.d.ts +54 -6
  96. package/dist/docx/rezip.js +835 -257
  97. package/dist/docx/runConsolidator.d.ts +2 -58
  98. package/dist/docx/runConsolidator.js +3 -175
  99. package/dist/docx/runParser.d.ts +2 -1
  100. package/dist/docx/runParser.js +156 -116
  101. package/dist/docx/saveDiagnostics.d.ts +22 -0
  102. package/dist/docx/saveDiagnostics.js +0 -0
  103. package/dist/docx/selectiveSave.d.ts +3 -1
  104. package/dist/docx/selectiveSave.js +36 -4
  105. package/dist/docx/selectiveXmlPatch.d.ts +16 -8
  106. package/dist/docx/selectiveXmlPatch.js +81 -7
  107. package/dist/docx/serializer/documentSerializer.d.ts +9 -2
  108. package/dist/docx/serializer/documentSerializer.js +29 -10
  109. package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
  110. package/dist/docx/serializer/headerFooterSerializer.js +19 -11
  111. package/dist/docx/serializer/noteSerializer.d.ts +2 -2
  112. package/dist/docx/serializer/noteSerializer.js +24 -8
  113. package/dist/docx/serializer/paragraphSerializer.js +41 -4
  114. package/dist/docx/serializer/partNamespaces.js +2 -1
  115. package/dist/docx/serializer/runSerializer.js +3 -1
  116. package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
  117. package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
  118. package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
  119. package/dist/docx/settingsParser.d.ts +1 -2
  120. package/dist/docx/settingsParser.js +5 -6
  121. package/dist/docx/storyBlockReplay.d.ts +31 -0
  122. package/dist/docx/storyBlockReplay.js +471 -0
  123. package/dist/docx/storyPlainText.d.ts +20 -0
  124. package/dist/docx/storyPlainText.js +23 -0
  125. package/dist/docx/streamingXmlParser.d.ts +22 -1
  126. package/dist/docx/streamingXmlParser.js +49 -3
  127. package/dist/docx/structuralXmlPatch.js +18 -23
  128. package/dist/docx/styleParser.d.ts +5 -1
  129. package/dist/docx/styleParser.js +1 -1
  130. package/dist/docx/tableParser.d.ts +1 -8
  131. package/dist/docx/tableParser.js +1 -28
  132. package/dist/docx/textBoxParser.d.ts +1 -5
  133. package/dist/docx/textBoxParser.js +1 -20
  134. package/dist/docx/unzip.js +6 -1
  135. package/dist/docx/verbatimCapture.d.ts +3 -1
  136. package/dist/docx/verbatimCapture.js +49 -6
  137. package/dist/i18n/messages/ar.gen.d.ts +5 -0
  138. package/dist/i18n/messages/ar.gen.js +656 -0
  139. package/dist/i18n/messages/cs.gen.d.ts +5 -0
  140. package/dist/i18n/messages/cs.gen.js +656 -0
  141. package/dist/i18n/messages/de.gen.d.ts +5 -0
  142. package/dist/i18n/messages/de.gen.js +656 -0
  143. package/dist/i18n/messages/en.gen.d.ts +5 -0
  144. package/dist/i18n/messages/en.gen.js +656 -0
  145. package/dist/i18n/messages/es.gen.d.ts +5 -0
  146. package/dist/i18n/messages/es.gen.js +656 -0
  147. package/dist/i18n/messages/et.gen.d.ts +5 -0
  148. package/dist/i18n/messages/et.gen.js +656 -0
  149. package/dist/i18n/messages/fr.gen.d.ts +5 -0
  150. package/dist/i18n/messages/fr.gen.js +656 -0
  151. package/dist/i18n/messages/he.gen.d.ts +5 -0
  152. package/dist/i18n/messages/he.gen.js +656 -0
  153. package/dist/i18n/messages/hi.gen.d.ts +5 -0
  154. package/dist/i18n/messages/hi.gen.js +656 -0
  155. package/dist/i18n/messages/hu.gen.d.ts +5 -0
  156. package/dist/i18n/messages/hu.gen.js +656 -0
  157. package/dist/i18n/messages/locales.d.ts +5 -0
  158. package/dist/i18n/messages/locales.js +22 -0
  159. package/dist/i18n/messages/lt.gen.d.ts +5 -0
  160. package/dist/i18n/messages/lt.gen.js +656 -0
  161. package/dist/i18n/messages/lv.gen.d.ts +5 -0
  162. package/dist/i18n/messages/lv.gen.js +656 -0
  163. package/dist/i18n/messages/pl.gen.d.ts +5 -0
  164. package/dist/i18n/messages/pl.gen.js +656 -0
  165. package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
  166. package/dist/i18n/messages/pt-BR.gen.js +656 -0
  167. package/dist/i18n/messages/sk.gen.d.ts +5 -0
  168. package/dist/i18n/messages/sk.gen.js +656 -0
  169. package/dist/i18n/messages/tr.gen.d.ts +5 -0
  170. package/dist/i18n/messages/tr.gen.js +656 -0
  171. package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
  172. package/dist/i18n/messages/zh-CN.gen.js +656 -0
  173. package/dist/i18n/messages.d.ts +2 -3
  174. package/dist/i18n/messages.js +1 -19
  175. package/dist/internal/acceptedBlockProjection.d.ts +12 -0
  176. package/dist/internal/acceptedBlockProjection.js +45 -0
  177. package/dist/internal/noteMarkerAttrs.d.ts +8 -0
  178. package/dist/internal/noteMarkerAttrs.js +16 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
  180. package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
  181. package/dist/internal/prosemirrorAttrBoundary.js +50 -0
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
  186. package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
  187. package/dist/layout-bridge/convert/noteReferences.js +1 -6
  188. package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
  189. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
  190. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
  191. package/dist/managers/DocumentLoaderManager.d.ts +1 -0
  192. package/dist/managers/DocumentLoaderManager.js +9 -1
  193. package/dist/markdown/escape.d.ts +3 -1
  194. package/dist/markdown/escape.js +9 -2
  195. package/dist/markdown/renderBlock.js +20 -121
  196. package/dist/markdown/renderParagraph.js +13 -15
  197. package/dist/markdown/renderRuns.d.ts +7 -1
  198. package/dist/markdown/renderRuns.js +35 -15
  199. package/dist/markdown/renderTable.js +2 -0
  200. package/dist/markdown/types.d.ts +3 -9
  201. package/dist/prosemirror/attrs/index.d.ts +2 -12
  202. package/dist/prosemirror/attrs/index.js +22 -48
  203. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
  204. package/dist/prosemirror/canonicalCommands.d.ts +121 -0
  205. package/dist/prosemirror/canonicalCommands.js +35 -0
  206. package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
  207. package/dist/prosemirror/canonicalSelectionRange.js +15 -0
  208. package/dist/prosemirror/clipboardIntent.d.ts +7 -0
  209. package/dist/prosemirror/clipboardIntent.js +9 -0
  210. package/dist/prosemirror/commands/pageBreak.js +15 -1
  211. package/dist/prosemirror/commands/pastePlainText.js +2 -1
  212. package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
  213. package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
  214. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
  215. package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
  216. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
  217. package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
  218. package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
  219. package/dist/prosemirror/conversion/toProseDoc.js +55 -14
  220. package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
  221. package/dist/prosemirror/executeEditorCommand.js +26 -0
  222. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  223. package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
  224. package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
  226. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
  227. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
  228. package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
  229. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  230. package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
  231. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
  232. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
  233. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
  234. package/dist/prosemirror/insertOperations.js +2 -1
  235. package/dist/prosemirror/listMarker.d.ts +1 -0
  236. package/dist/prosemirror/listMarker.js +16 -7
  237. package/dist/prosemirror/listNumbering.js +26 -5
  238. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  239. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  240. package/dist/prosemirror/markupViewNotes.js +3 -2
  241. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
  242. package/dist/prosemirror/noteReferenceReview.js +5 -3
  243. package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
  244. package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
  245. package/dist/prosemirror/plugins/suggestionMode.js +57 -7
  246. package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
  247. package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
  248. package/dist/prosemirror/runFormattingFromMarks.js +15 -1
  249. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
  250. package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
  251. package/dist/prosemirror/schema/marks.d.ts +2 -0
  252. package/dist/prosemirror/schema/nodes.d.ts +10 -2
  253. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
  254. package/dist/prosemirror/textInput.js +5 -1
  255. package/dist/prosemirror/trackedRevisionPath.js +2 -1
  256. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
  257. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
  258. package/dist/prosemirror/validation.js +4 -0
  259. package/dist/types/canonicalCapabilities.d.ts +215 -0
  260. package/dist/types/canonicalCapabilities.js +212 -0
  261. package/dist/types/canonicalSave.d.ts +11 -0
  262. package/dist/types/canonicalSave.js +0 -0
  263. package/dist/types/content.d.ts +2 -2
  264. package/dist/types/docxSerialization.d.ts +14 -0
  265. package/dist/types/docxSerialization.js +7 -0
  266. package/dist/utils/createDocument.js +2 -2
  267. package/package.json +16 -4
@@ -1,5 +1,6 @@
1
1
  import { isQuoteStyle, resolveHeadingLevel } from "../docx/builtInStyles.js";
2
2
  import { listLabelAttrsFromRendering } from "../prosemirror/listLabels.js";
3
+ import { inlineBreaksToHtml } from "./escape.js";
3
4
  import { renderParagraphInline } from "./renderRuns.js";
4
5
  //#region src/markdown/renderParagraph.ts
5
6
  /**
@@ -36,13 +37,15 @@ function renderParagraphBlock(ctx, pkg, para) {
36
37
  const styleId = para.formatting?.styleId;
37
38
  const headingLevel = markdownHeadingLevel(ctx, para);
38
39
  if (headingLevel !== void 0) {
39
- if (!inline) return {
40
+ ctx.listIndentWidths = [];
41
+ if (!inline || !inline.trim() && label === void 0) return {
40
42
  markdown: "",
41
43
  isListItem: false
42
44
  };
43
45
  const hashes = "#".repeat(Math.min(MAX_MARKDOWN_HEADING_LEVEL, headingLevel + 1));
46
+ const headingInline = inlineBreaksToHtml(inline);
44
47
  return {
45
- markdown: label ? `${hashes} ${label} ${inline}` : `${hashes} ${inline}`,
48
+ markdown: label ? `${hashes} ${label} ${headingInline}` : `${hashes} ${headingInline}`,
46
49
  isListItem: false
47
50
  };
48
51
  }
@@ -50,6 +53,7 @@ function renderParagraphBlock(ctx, pkg, para) {
50
53
  markdown: renderListItem(ctx, para.listRendering, label, inline),
51
54
  isListItem: true
52
55
  };
56
+ ctx.listIndentWidths = [];
53
57
  if (isQuoteStyle(styleId, ctx.builtInStyles)) return {
54
58
  markdown: inline.split("\n").map((line) => `> ${line}`).join("\n"),
55
59
  isListItem: false
@@ -86,21 +90,12 @@ function escapeLeadingBlockMarker(text) {
86
90
  return text.replace(/^(?<ws>[ \t]*)(?<marker>[#>])/gmu, "$<ws>\\$<marker>").replace(/^(?<ws>[ \t]*)(?<marker>[-+*])(?<after>[ \t])/gmu, "$<ws>\\$<marker>$<after>").replace(/^(?<ws>[ \t]*)(?<num>\d{1,9})(?<marker>[.)])(?<after>[ \t])/gmu, "$<ws>$<num>\\$<marker>$<after>");
87
91
  }
88
92
  /**
89
- * A markdown list marker's width when no ancestor at that level has rendered
90
- * yet (e.g. a DOCX paragraph numbered at a level its list skipped over). Two
91
- * spaces is the old fixed-indent behaviour, kept as a fallback rather than a
92
- * guess of zero.
93
- */
94
- const DEFAULT_LIST_INDENT_WIDTH = 2;
95
- /**
96
- * The indent a level's item needs: the combined marker width of every
97
- * shallower level's most recently rendered item (see
98
- * `RenderContext.listIndentWidths`), so a child sits inside its parent's
99
- * content column per CommonMark's list-nesting rule, not a fixed guess.
93
+ * Only emitted Markdown ancestors contribute columns. OOXML levels may skip
94
+ * ancestors or resume after prose; inventing those columns creates code blocks.
100
95
  */
101
96
  function listIndentWidth(ctx, level) {
102
97
  let width = 0;
103
- for (let ancestor = 0; ancestor < level; ancestor++) width += ctx.listIndentWidths[ancestor] ?? DEFAULT_LIST_INDENT_WIDTH;
98
+ for (let ancestor = 0; ancestor < level; ancestor++) width += ctx.listIndentWidths[ancestor] ?? 0;
104
99
  return width;
105
100
  }
106
101
  /**
@@ -116,9 +111,12 @@ function listIndentWidth(ctx, level) {
116
111
  * a following, deeper item can indent correctly under it.
117
112
  */
118
113
  function renderListItem(ctx, list, label, inline) {
114
+ const nativeMarker = list.isBullet || /^\d{1,9}[.)]$/u.test(label);
115
+ if (!nativeMarker) ctx.listIndentWidths = [];
116
+ ctx.listIndentWidths.length = list.level;
119
117
  const indent = " ".repeat(listIndentWidth(ctx, list.level));
120
118
  const marker = list.isBullet ? "- " : `${label} `;
121
- ctx.listIndentWidths[list.level] = marker.length;
119
+ if (nativeMarker) ctx.listIndentWidths[list.level] = marker.length;
122
120
  return `${indent}${marker}${inline}`.trimEnd();
123
121
  }
124
122
  //#endregion
@@ -1,6 +1,12 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { RenderContext } from "./types.js";
3
3
  //#region src/markdown/renderRuns.d.ts
4
+ /**
5
+ * Inline marks we recognize. Order matters: we open from outermost to innermost
6
+ * so the output reads cleanly (`***bold italic***`), not the reverse.
7
+ */
8
+ type MarkKey = "bold" | "italic" | "code" | "strike";
9
+ declare function applyMarks(text: string, marks: readonly MarkKey[]): string;
4
10
  /**
5
11
  * The character beside a run's delimiters: `""` at the paragraph's edge,
6
12
  * `undefined` when it cannot be told (read as a letter, the strictest case).
@@ -16,4 +22,4 @@ type RunNeighbors = {
16
22
  */
17
23
  declare function renderParagraphInline(ctx: RenderContext, pkg: document_d_exports.DocxPackage | undefined, content: readonly document_d_exports.ParagraphContent[], paraId: string | undefined, edges?: RunNeighbors): string;
18
24
  //#endregion
19
- export { renderParagraphInline };
25
+ export { applyMarks, renderParagraphInline };
@@ -40,22 +40,32 @@ function marksFor(run) {
40
40
  if (ascii && MONOSPACE_FONTS.has(ascii)) out.push("code");
41
41
  return out;
42
42
  }
43
+ const splitEdgeWhitespace = (text) => {
44
+ const start = text.length - text.trimStart().length;
45
+ const end = text.trimEnd().length;
46
+ return {
47
+ leading: text.slice(0, start),
48
+ core: text.slice(start, Math.max(start, end)),
49
+ trailing: text.slice(Math.max(start, end))
50
+ };
51
+ };
43
52
  function applyMarks(text, marks) {
44
- if (!text) return text;
53
+ const { leading, core, trailing } = splitEdgeWhitespace(text);
54
+ if (!core || marks.length === 0) return text;
45
55
  if (marks.includes("code")) {
46
- const literal = text.replace(/\\(?<char>[\\`*[\]_<~])/gu, "$<char>");
56
+ const literal = core.replace(/\\(?<char>[\\`*[\]_<~])/gu, "$<char>");
47
57
  let longestRun = 0;
48
58
  for (const m of literal.matchAll(/`+/gu)) longestRun = Math.max(longestRun, m[0].length);
49
59
  const fence = "`".repeat(longestRun + 1);
50
60
  const pad = literal.startsWith("`") || literal.endsWith("`") ? " " : "";
51
- return `${fence}${pad}${literal}${pad}${fence}`;
61
+ return `${leading}${fence}${pad}${literal}${pad}${fence}${trailing}`;
52
62
  }
53
- let out = text;
63
+ let out = core;
54
64
  for (const m of marks) {
55
65
  const d = MARK_DELIMS[m];
56
66
  out = `${d}${out}${d}`;
57
67
  }
58
- return out;
68
+ return `${leading}${out}${trailing}`;
59
69
  }
60
70
  const UNKNOWN_NEIGHBORS = {
61
71
  before: void 0,
@@ -91,8 +101,8 @@ const punctuationFor = (mark) => (ch) => {
91
101
  if (mark !== "strike" && ch === "*") return false;
92
102
  return /[\p{P}\p{S}]/u.test(ch);
93
103
  };
94
- /** One escape pair (`\*`) or one code point of escaped inline text. */
95
- const INLINE_UNIT = /\\[\s\S]|[\s\S]/gu;
104
+ /** Escape pairs and generated note references are indivisible inline units. */
105
+ const INLINE_UNIT = /\\[\s\S]|\[\^e?\d+\]|[\s\S]/gu;
96
106
  /**
97
107
  * Wrap `inner` in `mark` so a CommonMark reader reads it back. A delimiter
98
108
  * opens only before a character that is not blank, and before punctuation
@@ -213,6 +223,7 @@ function renderRunContent(ctx, pkg, content, paraId) {
213
223
  if (ctx.opts.footnotes === "strip") break;
214
224
  out += numberNoteReference(ctx, item.type === "endnoteRef" ? "endnote" : "footnote", item.id).marker;
215
225
  break;
226
+ case "noteMarker": break;
216
227
  case "drawing": {
217
228
  const ref = resolveRelationshipIdOfType(pkg?.relationships, item.image.rId, RELATIONSHIP_TYPES.image);
218
229
  const media = ref.status === "resolved" ? pkg?.media?.get(ref.relationship.target) : void 0;
@@ -249,11 +260,8 @@ function pieceOf(ctx, pkg, run, paraId) {
249
260
  text: inner,
250
261
  marks: new Set(marks)
251
262
  };
252
- const leadLen = inner.length - inner.trimStart().length;
253
- const trailLen = inner.length - inner.trimEnd().length;
254
- const core = inner.slice(leadLen, inner.length - trailLen);
255
263
  return {
256
- text: core ? `${inner.slice(0, leadLen)}${applyMarks(core, marks)}${inner.slice(inner.length - trailLen)}` : inner,
264
+ text: inner.split("\n").map((line) => applyMarks(line, marks)).join("\n"),
257
265
  marks: /* @__PURE__ */ new Set()
258
266
  };
259
267
  }
@@ -345,6 +353,8 @@ function renderHyperlink(ctx, pkg, link, paraId) {
345
353
  after: "]"
346
354
  } : UNKNOWN_NEIGHBORS);
347
355
  if (!inner) return "";
356
+ const { leading, core, trailing } = splitEdgeWhitespace(inner);
357
+ if (!core) return inner;
348
358
  const href = link.href ?? (link.anchor ? `#${link.anchor}` : "");
349
359
  if (!href) {
350
360
  pushWarning(ctx, "hyperlink missing href and anchor; rendered as plain text");
@@ -356,9 +366,9 @@ function renderHyperlink(ctx, pkg, link, paraId) {
356
366
  href,
357
367
  refNumber
358
368
  });
359
- return `[${inner}][${refNumber}]`;
369
+ return `${leading}[${core}][${refNumber}]${trailing}`;
360
370
  }
361
- return `[${inner}](${escapeLinkUrl(href)})`;
371
+ return `${leading}[${core}](${escapeLinkUrl(href)})${trailing}`;
362
372
  }
363
373
  function renderTrackedWrapper(ctx, pkg, wrapper, paraId) {
364
374
  const renderChild = (child) => {
@@ -418,6 +428,16 @@ function renderTrackedWrapper(ctx, pkg, wrapper, paraId) {
418
428
  default: return wrapMoveTo(ctx, wrapper.info, inner);
419
429
  }
420
430
  }
431
+ /** Clean revisions have no inline boundary; group their runs with surrounding runs. */
432
+ const cleanRevisionContent = (content) => content.flatMap((item) => {
433
+ switch (item.type) {
434
+ case "insertion":
435
+ case "moveTo": return cleanRevisionContent(item.content);
436
+ case "deletion":
437
+ case "moveFrom": return [];
438
+ default: return [item];
439
+ }
440
+ });
421
441
  /**
422
442
  * Render the full inline content of a paragraph, tracking comment-range
423
443
  * boundaries to apply the configured wrapper.
@@ -428,7 +448,7 @@ function renderParagraphInline(ctx, pkg, content, paraId, edges = {
428
448
  }) {
429
449
  let out = "";
430
450
  const openComments = [];
431
- const items = content.filter((item) => !SILENT_MARKERS.has(item.type) && !(ctx.opts.comments === "strip" && COMMENT_MARKERS.has(item.type)));
451
+ const items = (ctx.opts.trackedChanges === "clean" ? cleanRevisionContent(content) : content).filter((item) => !SILENT_MARKERS.has(item.type) && !(ctx.opts.comments === "strip" && COMMENT_MARKERS.has(item.type)));
432
452
  const around = (index) => {
433
453
  const next = items[index + 1];
434
454
  return {
@@ -556,4 +576,4 @@ function applyCommentWrapping(ctx, slot, current) {
556
576
  }, inner);
557
577
  }
558
578
  //#endregion
559
- export { renderParagraphInline };
579
+ export { applyMarks, renderParagraphInline };
@@ -62,6 +62,7 @@ function renderGfmRow(ctx, pkg, row) {
62
62
  return out;
63
63
  }
64
64
  function renderGfmCell(ctx, pkg, cell) {
65
+ ctx.listIndentWidths = [];
65
66
  const blocks = [];
66
67
  const renderBlocks = (content) => {
67
68
  for (const item of content) switch (item.type) {
@@ -278,6 +279,7 @@ function renderHtmlRun(ctx, pkg, run, paraId) {
278
279
  text += `<sup>[${token}]</sup>`;
279
280
  break;
280
281
  }
282
+ case "noteMarker": break;
281
283
  default: break;
282
284
  }
283
285
  if (!text) return "";
@@ -141,15 +141,9 @@ type RenderContext = {
141
141
  /** The document's styles indexed by the built-in they are; classifies headings and quotes. */
142
142
  builtInStyles: BuiltInStyleIndex;
143
143
  /**
144
- * The rendered width (marker text + one trailing space) of the most
145
- * recently emitted list item at each level, indexed by `ListRendering.level`.
146
- * A nested item's indent is the sum of every shallower level's width here,
147
- * not a fixed two spaces: CommonMark only keeps a child nested under its
148
- * parent when the child starts at or past the column where the parent's
149
- * content begins, and a marker like `10. ` or `1. ` is wider than `- `.
150
- * Document order visits a parent before its children, so by the time a
151
- * level-N item renders, levels `0..N-1` already hold the current ancestor
152
- * chain's widths.
144
+ * Active native Markdown ancestor marker widths, indexed by OOXML level.
145
+ * Missing levels contribute no columns. Prose, headings and container
146
+ * boundaries clear the chain; a shallower item truncates descendants.
153
147
  */
154
148
  listIndentWidths: number[];
155
149
  };
@@ -1,19 +1,9 @@
1
1
  import { CharacterSpacingAttrs, CharacterStyleAttrs, CommentAttrs, EmphasisMarkAttrs, FontFamilyAttrs, FontSizeAttrs, FootnoteRefAttrs, HighlightAttrs, HyperlinkAttrs, InlineWrapperAttrs, InlineWrapperLayer, LanguageAttrs, RunFormattingOverrideAttrs, RunIdentityMarkAttrs, RunPropertyChangeMarkAttrs, RunShadingAttrs, StrikeAttrs, TextColorAttrs, TextEffectAttrs, TrackedChangeMarkAttrs, TrackedRevisionAncestor, UnderlineAttrs } from "../schema/marks.js";
2
2
  import { BlockCustomXmlAttrs, BlockSdtAttrs, FieldAttrs, HardBreakAttrs, ImageAttrs, MathAttrs, PageBreakRunAttrs, ParagraphAttrs, PreservedBlockAttrs, PreservedXmlAttrs, SdtAttrs, ShapeAttrs, SymbolAttrs, TabAttrs, TableAttrs, TableCellAttrs, TableRowAttrs, TextBoxAttrs } from "../schema/nodes.js";
3
3
  import "../schema/index.js";
4
+ import { ProseMirrorAttrIssue, ReadProseMirrorAttrsResult } from "../../internal/prosemirrorAttrBoundary.js";
4
5
  import { Mark, Node } from "prosemirror-model";
5
6
  //#region src/prosemirror/attrs/index.d.ts
6
- type ProseMirrorAttrIssue = {
7
- readonly path: string;
8
- readonly message: string;
9
- };
10
- type ReadProseMirrorAttrsResult<T> = {
11
- ok: true;
12
- value: T;
13
- } | {
14
- ok: false;
15
- issues: readonly ProseMirrorAttrIssue[];
16
- };
17
7
  declare const readParagraphAttrs: (node: Node) => ReadProseMirrorAttrsResult<Readonly<ParagraphAttrs>>;
18
8
  declare const expectParagraphAttrs: (node: Node) => Readonly<ParagraphAttrs>;
19
9
  declare const readHardBreakAttrs: (node: Node) => ReadProseMirrorAttrsResult<HardBreakAttrs>;
@@ -123,4 +113,4 @@ declare const mergeTableRowAttrs: (node: Node, patch: NodeAttrPatch<TableRowAttr
123
113
  */
124
114
  declare const mergeTableCellAttrs: (node: Node, patch: NodeAttrPatch<TableCellAttrs>) => TableCellAttrs;
125
115
  //#endregion
126
- export { ProseMirrorAttrIssue, ReadProseMirrorAttrsResult, expectBlockCustomXmlAttrs, expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectInlineWrapperMarkAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectPageBreakRunAttrs, expectParagraphAttrs, expectPreservedBlockAttrs, expectPreservedXmlAttrs, expectRunFormattingOverrideMarkAttrs, expectRunIdentityMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs, isTrackedRevisionAncestorArray, isValidEmptyFieldResultRuns, isValidFieldCode, mergeImageAttrs, mergeParagraphAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs, readBlockCustomXmlAttrs, readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readInlineWrapperStack, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunIdentityMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs };
116
+ export { type ProseMirrorAttrIssue, type ReadProseMirrorAttrsResult, expectBlockCustomXmlAttrs, expectBlockSdtAttrs, expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectCommentMarkAttrs, expectEmphasisMarkAttrs, expectFieldAttrs, expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectFootnoteRefMarkAttrs, expectHardBreakAttrs, expectHighlightMarkAttrs, expectHyperlinkMarkAttrs, expectImageAttrs, expectInlineWrapperMarkAttrs, expectLanguageMarkAttrs, expectMathAttrs, expectPageBreakRunAttrs, expectParagraphAttrs, expectPreservedBlockAttrs, expectPreservedXmlAttrs, expectRunFormattingOverrideMarkAttrs, expectRunIdentityMarkAttrs, expectRunPropertyChangeMarkAttrs, expectRunShadingMarkAttrs, expectSdtAttrs, expectShapeAttrs, expectStrikeMarkAttrs, expectSymbolAttrs, expectTabAttrs, expectTableAttrs, expectTableCellAttrs, expectTableRowAttrs, expectTextBoxAttrs, expectTextColorMarkAttrs, expectTextEffectMarkAttrs, expectTrackedChangeMarkAttrs, expectUnderlineMarkAttrs, isTrackedRevisionAncestorArray, isValidEmptyFieldResultRuns, isValidFieldCode, mergeImageAttrs, mergeParagraphAttrs, mergeTableAttrs, mergeTableCellAttrs, mergeTableRowAttrs, readBlockCustomXmlAttrs, readBlockSdtAttrs, readCharacterSpacingMarkAttrs, readCharacterStyleMarkAttrs, readCommentMarkAttrs, readEmphasisMarkAttrs, readFieldAttrs, readFontFamilyMarkAttrs, readFontSizeMarkAttrs, readFootnoteRefMarkAttrs, readHardBreakAttrs, readHighlightMarkAttrs, readHyperlinkMarkAttrs, readImageAttrs, readInlineWrapperMarkAttrs, readInlineWrapperStack, readLanguageMarkAttrs, readMathAttrs, readPageBreakRunAttrs, readParagraphAttrs, readPreservedBlockAttrs, readPreservedXmlAttrs, readRunFormattingOverrideMarkAttrs, readRunIdentityMarkAttrs, readRunPropertyChangeMarkAttrs, readRunShadingMarkAttrs, readSdtAttrs, readShapeAttrs, readStrikeMarkAttrs, readSymbolAttrs, readTabAttrs, readTableAttrs, readTableCellAttrs, readTableRowAttrs, readTextBoxAttrs, readTextColorMarkAttrs, readTextEffectMarkAttrs, readTrackedChangeMarkAttrs, readUnderlineMarkAttrs };
@@ -1,7 +1,10 @@
1
1
  import { isSerializablePreservedAttribute } from "../../docx/attributeRemainder.js";
2
2
  import { DRAWING_ANCHOR_FLAG_KEYS } from "../../docx/drawingAnchor.js";
3
+ import { isFoldedListNumber } from "../../docx/foldedListNumberFields.js";
3
4
  import { GRAPHIC_FRAME_LOCK_KEYS } from "../../docx/graphicFrameLocks.js";
4
5
  import { allowsDirectDrawingEdit, isDrawingRawXmlMode } from "../../docx/imageRawXml.js";
6
+ import { isParagraphMarkResolutionJoin, isResolutionJoins } from "../../docx/reviewResolutionProvenance.js";
7
+ import { attrsRecord, attrsResult, expectAttrs, expectCachedNodeAttrs, expectNodeType, isRecord } from "../../internal/prosemirrorAttrBoundary.js";
5
8
  import { COUNTER_FORMAT_VALUES, EMPHASIS_MARK_VALUES, FIELD_TYPE_VALUES, FONT_HINT_VALUES, FONT_THEME_VALUES, HIGHLIGHT_COLOR_VALUES, IMAGE_HORIZONTAL_ALIGNMENT_VALUES, IMAGE_HORIZONTAL_RELATIVE_TO_VALUES, IMAGE_VERTICAL_ALIGNMENT_VALUES, IMAGE_VERTICAL_RELATIVE_TO_VALUES, IMAGE_WRAP_TEXT_VALUES, IMAGE_WRAP_TYPE_VALUES, LINE_SPACING_RULE_VALUES, OUTLINE_STYLE_ATTR_VALUES, PARAGRAPH_ALIGNMENT_VALUES, POSITIONAL_TAB_ALIGNMENT_VALUES, POSITIONAL_TAB_LEADER_VALUES, POSITIONAL_TAB_RELATIVE_TO_VALUES, SDT_LOCK_VALUES, SDT_TYPE_VALUES, SHADING_PATTERN_VALUES, TABLE_CELL_VERTICAL_ALIGNMENT_VALUES, TABLE_JUSTIFICATION_VALUES, TABLE_ROW_HEIGHT_RULE_VALUES, TABLE_WIDTH_TYPE_VALUES, TAB_LEADER_VALUES, TAB_STOP_ALIGNMENT_VALUES, TEXT_DIRECTION_VALUES, TEXT_EFFECT_VALUES, UNDERLINE_STYLE_VALUES } from "../../types/documentEnumValues.js";
6
9
  import { canonicalJson } from "../../utils/canonicalJson.js";
7
10
  import { normalizeHorizontalScalePercent } from "../../utils/horizontalScale.js";
@@ -10,7 +13,6 @@ import { outlineLevelFromAttrValue } from "../outlineLevelAttr.js";
10
13
  import { isParagraphDirection } from "../paragraphDirection.js";
11
14
  import { COMPLEX_SCRIPT_RUN_PROPERTY_KEYS, RUN_FORMATTING_BOOLEAN_PROPERTIES, RUN_FORMATTING_VALUE_PROPERTIES, TRACKED_CHANGE_PROVENANCE_VALUES } from "../schema/marks.js";
12
15
  import { PRESERVED_XML_LEVELS, TEXT_BOX_TEXT_BODY_CONTENT_STATE_TYPES } from "../schema/nodes.js";
13
- import { panic } from "better-result";
14
16
  import { DRAWING_RAW_XML_MODES, THEME_COLORS, isOoxmlSymbolCharacter } from "@stll/docx-core/model";
15
17
  import { isSafePreservedChildXml, isWithinPreservedMarkupBudget } from "@stll/docx-core/schema";
16
18
  //#region src/prosemirror/attrs/index.ts
@@ -216,6 +218,11 @@ const readParagraphAttrsUncached = (node) => {
216
218
  const attrs = attrsRecord(node.attrs);
217
219
  const issues = [];
218
220
  expectNodeType(node, "paragraph", issues);
221
+ const paragraphMark = attrs["pPrMark"];
222
+ if (isRecord(paragraphMark) && paragraphMark["resolutionJoin"] !== void 0 && !isParagraphMarkResolutionJoin(paragraphMark["resolutionJoin"])) issues.push({
223
+ path: "paragraph.attrs.pPrMark.resolutionJoin",
224
+ message: "Expected a non-negative bounded paragraph cut depth."
225
+ });
219
226
  optionalString(attrs, "paraId", "paragraph.attrs.paraId", issues);
220
227
  optionalString(attrs, "_docxParagraphSourceToken", "paragraph.attrs._docxParagraphSourceToken", issues);
221
228
  optionalString(attrs, "textId", "paragraph.attrs.textId", issues);
@@ -243,6 +250,7 @@ const readParagraphAttrsUncached = (node) => {
243
250
  optionalBoolean(attrs, "listIsLegal", "paragraph.attrs.listIsLegal", issues);
244
251
  optionalString(attrs, "listMarker", "paragraph.attrs.listMarker", issues);
245
252
  optionalString(attrs, "listMarkerTemplate", "paragraph.attrs.listMarkerTemplate", issues);
253
+ optionalString(attrs, "listFoldedMarkerSuffix", "paragraph.attrs.listFoldedMarkerSuffix", issues);
246
254
  optionalBoolean(attrs, "listMarkerHidden", "paragraph.attrs.listMarkerHidden", issues);
247
255
  optionalTextFormatting(attrs, "listMarkerFormatting", "paragraph.attrs.listMarkerFormatting", issues);
248
256
  optionalOneOf(attrs, "listMarkerAlignment", "paragraph.attrs.listMarkerAlignment", issues, [
@@ -362,6 +370,11 @@ const readPreservedXmlAttrs = (node) => {
362
370
  expectNodeType(node, "preservedXml", issues);
363
371
  requiredString(attrs, "xml", "preservedXml.attrs.xml", issues);
364
372
  requiredString(attrs, "text", "preservedXml.attrs.text", issues);
373
+ const folded = attrs["foldedListNumber"];
374
+ if (folded !== void 0 && folded !== null && !isFoldedListNumber(folded)) issues.push({
375
+ path: "preservedXml.attrs.foldedListNumber",
376
+ message: "Expected a folded list-number field or tab."
377
+ });
365
378
  if (!PRESERVED_XML_LEVEL_VALUES.has(attrs["level"])) issues.push({
366
379
  path: "preservedXml.attrs.level",
367
380
  message: `Expected one of ${[...PRESERVED_XML_LEVEL_VALUES].join(", ")}.`
@@ -580,6 +593,7 @@ const isFieldCodeContent = (value) => {
580
593
  case "symbol": return typeof value["font"] === "string" && typeof value["char"] === "string";
581
594
  case "footnoteRef":
582
595
  case "endnoteRef": return typeof value["id"] === "number";
596
+ case "noteMarker": return value["kind"] === "footnote" || value["kind"] === "endnote";
583
597
  case "drawing": return isRecord(value["image"]);
584
598
  case "shape": return isRecord(value["shape"]);
585
599
  case "tab":
@@ -953,7 +967,7 @@ const readCommentMarkAttrs = (mark) => {
953
967
  return attrsResult(attrs, issues);
954
968
  };
955
969
  const expectCommentMarkAttrs = (mark) => expectCachedMarkAttrs(mark, commentAttrsCache, readCommentMarkAttrs, "comment attrs");
956
- const isTrackedRevisionAncestorArray = (value) => Array.isArray(value) && value.length > 0 && value.every((ancestor) => isRecord(ancestor) && TRACKED_REVISION_ANCESTOR_TYPES.some((type) => type === ancestor["type"]) && typeof ancestor["revisionId"] === "number" && Number.isSafeInteger(ancestor["revisionId"]) && ancestor["revisionId"] >= 0 && typeof ancestor["author"] === "string" && (ancestor["date"] === void 0 || typeof ancestor["date"] === "string") && (ancestor["utcDate"] === void 0 || typeof ancestor["utcDate"] === "string") && (ancestor["initials"] === void 0 || typeof ancestor["initials"] === "string") && typeof ancestor["outerWrapperCount"] === "number" && Number.isSafeInteger(ancestor["outerWrapperCount"]) && ancestor["outerWrapperCount"] >= 0);
970
+ const isTrackedRevisionAncestorArray = (value) => Array.isArray(value) && value.length > 0 && value.every((ancestor) => isRecord(ancestor) && TRACKED_REVISION_ANCESTOR_TYPES.some((type) => type === ancestor["type"]) && typeof ancestor["revisionId"] === "number" && Number.isSafeInteger(ancestor["revisionId"]) && ancestor["revisionId"] >= 0 && typeof ancestor["author"] === "string" && (ancestor["date"] === void 0 || typeof ancestor["date"] === "string") && (ancestor["utcDate"] === void 0 || typeof ancestor["utcDate"] === "string") && (ancestor["initials"] === void 0 || typeof ancestor["initials"] === "string") && typeof ancestor["outerWrapperCount"] === "number" && Number.isSafeInteger(ancestor["outerWrapperCount"]) && ancestor["outerWrapperCount"] >= 0 && (ancestor["resolutionJoins"] === void 0 || isResolutionJoins(ancestor["resolutionJoins"])));
957
971
  const readTrackedChangeMarkAttrs = (mark) => {
958
972
  const attrs = attrsRecord(mark.attrs);
959
973
  const issues = [];
@@ -969,6 +983,11 @@ const readTrackedChangeMarkAttrs = (mark) => {
969
983
  message: "Expected a non-negative safe integer."
970
984
  });
971
985
  const ancestors = attrs["_docxRevisionAncestors"];
986
+ const resolutionJoins = attrs["_docxResolutionJoins"];
987
+ if (resolutionJoins !== void 0 && resolutionJoins !== null && !isResolutionJoins(resolutionJoins)) issues.push({
988
+ path: `${mark.type.name}.attrs._docxResolutionJoins`,
989
+ message: "Expected valid tracked-resolution provenance."
990
+ });
972
991
  if (ancestors !== void 0 && ancestors !== null && !isTrackedRevisionAncestorArray(ancestors)) issues.push({
973
992
  path: `${mark.type.name}.attrs._docxRevisionAncestors`,
974
993
  message: "Expected a non-empty array of valid revision ancestors."
@@ -1310,46 +1329,6 @@ const mergeTableCellAttrs = (node, patch) => {
1310
1329
  }
1311
1330
  };
1312
1331
  };
1313
- const attrsRecord = (attrs) => {
1314
- if (isRecord(attrs)) return attrs;
1315
- return {};
1316
- };
1317
- const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
1318
- const attrsResult = (attrs, issues) => {
1319
- if (issues.length > 0) return {
1320
- ok: false,
1321
- issues
1322
- };
1323
- let normalizedAttrs;
1324
- return {
1325
- ok: true,
1326
- get value() {
1327
- if (normalizedAttrs !== void 0) return normalizedAttrs;
1328
- const presentAttrs = {};
1329
- for (const key in attrs) {
1330
- if (!Object.hasOwn(attrs, key)) continue;
1331
- const value = attrs[key];
1332
- if (value !== null) presentAttrs[key] = value;
1333
- }
1334
- normalizedAttrs = presentAttrs;
1335
- return normalizedAttrs;
1336
- },
1337
- set value(value) {
1338
- normalizedAttrs = value;
1339
- }
1340
- };
1341
- };
1342
- const expectAttrs = (result, label) => {
1343
- if (result.ok) return result.value;
1344
- panic(`Invalid ProseMirror ${label}:\n${result.issues.map((issue) => `${issue.path}: ${issue.message}`).join("\n")}`);
1345
- };
1346
- function expectCachedNodeAttrs(node, cache, reader, label) {
1347
- const cached = cache.get(node);
1348
- if (cached) return cached;
1349
- const value = expectAttrs(reader(node), label);
1350
- cache.set(node, value);
1351
- return value;
1352
- }
1353
1332
  function expectCachedMarkAttrs(mark, cache, reader, label) {
1354
1333
  const cached = cache.get(mark);
1355
1334
  if (cached) return cached;
@@ -1357,12 +1336,6 @@ function expectCachedMarkAttrs(mark, cache, reader, label) {
1357
1336
  cache.set(mark, value);
1358
1337
  return value;
1359
1338
  }
1360
- const expectNodeType = (node, expected, issues) => {
1361
- if (node.type.name !== expected) issues.push({
1362
- path: "node.type.name",
1363
- message: `Expected ${expected}, got ${node.type.name}.`
1364
- });
1365
- };
1366
1339
  const expectNodeTypeOneOf = (node, expected, issues) => {
1367
1340
  if (!expected.includes(node.type.name)) issues.push({
1368
1341
  path: "node.type.name",
@@ -2408,6 +2381,7 @@ const validateParagraphFormatting = (value, path, issues) => {
2408
2381
  optionalOneOf(value, "listNumFmt", `${path}.listNumFmt`, issues, COUNTER_FORMAT_VALUES);
2409
2382
  optionalString(value, "listMarker", `${path}.listMarker`, issues);
2410
2383
  optionalString(value, "listMarkerTemplate", `${path}.listMarkerTemplate`, issues);
2384
+ optionalString(value, "listFoldedMarkerSuffix", `${path}.listFoldedMarkerSuffix`, issues);
2411
2385
  optionalTextFormatting(value, "listMarkerFormatting", `${path}.listMarkerFormatting`, issues);
2412
2386
  optionalOneOf(value, "listMarkerAlignment", `${path}.listMarkerAlignment`, issues, [
2413
2387
  "left",
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { BookmarkBoundaryAttrs } from "./schema/nodes.js";
3
- import { ReadProseMirrorAttrsResult } from "./attrs/index.js";
3
+ import { ReadProseMirrorAttrsResult } from "../internal/prosemirrorAttrBoundary.js";
4
+ import "./attrs/index.js";
4
5
  import { Node } from "prosemirror-model";
5
6
  //#region src/prosemirror/bookmarkBoundaryAttrs.d.ts
6
7
  declare const isDisplacedByCustomXml: (value: unknown) => value is document_d_exports.DisplacedByCustomXml;
@@ -0,0 +1,121 @@
1
+ import { Node } from "prosemirror-model";
2
+ import { Command, EditorState } from "prosemirror-state";
3
+ import { ParagraphPropsPatch, RunPropsPatch } from "@stll/docx-core/ops";
4
+ //#region src/prosemirror/canonicalCommands.d.ts
5
+ /** Command meaning before canonical positions are resolved by the session. */
6
+ type CanonicalCommandIntent = {
7
+ type: "generateTOC";
8
+ at: number;
9
+ title: string;
10
+ } | {
11
+ type: "setHyperlink";
12
+ from: number;
13
+ to: number;
14
+ href: string;
15
+ tooltip?: string;
16
+ } | {
17
+ type: "removeHyperlink";
18
+ from: number;
19
+ to: number;
20
+ hyperlinkStyleId?: string;
21
+ } | {
22
+ type: "insertHyperlink";
23
+ from: number;
24
+ to: number;
25
+ text: string;
26
+ href: string;
27
+ tooltip?: string;
28
+ } | {
29
+ type: "formatRun";
30
+ from: number;
31
+ to: number;
32
+ patch: RunPropsPatch;
33
+ } | {
34
+ type: "formatParagraph";
35
+ at: number;
36
+ patch: ParagraphPropsPatch;
37
+ } | {
38
+ type: "toggleList";
39
+ kind: "bullet" | "decimal";
40
+ } | {
41
+ type: "changeListLevel";
42
+ direction: "increase" | "decrease";
43
+ } | {
44
+ type: "removeList";
45
+ } | {
46
+ type: "restartNumbering";
47
+ start?: number;
48
+ } | {
49
+ type: "continueNumbering";
50
+ } | {
51
+ type: "insertBreak";
52
+ from: number;
53
+ to: number;
54
+ breakType: "page" | "textWrapping";
55
+ };
56
+ type CanonicalCommandDescriptor = (state: EditorState) => readonly CanonicalCommandIntent[];
57
+ /** Registration leaves execution and side-effect-free command probes unchanged. */
58
+ declare const withCanonicalCommand: (command: Command, descriptor: CanonicalCommandDescriptor) => Command;
59
+ declare const getCanonicalCommandIntents: (command: Command, state: EditorState) => readonly CanonicalCommandIntent[] | undefined;
60
+ declare const canonicalRunFormatting: (state: EditorState, patch: RunPropsPatch) => readonly [{
61
+ readonly patch: import("@stll/docx-core/ops").FormattingPatch<{
62
+ bold?: boolean | undefined;
63
+ boldCs?: boolean | undefined;
64
+ italic?: boolean | undefined;
65
+ italicCs?: boolean | undefined;
66
+ underline?: {
67
+ style: import("@stll/docx-core/model").UnderlineStyle;
68
+ color?: import("@stll/docx-core/model").ColorValue;
69
+ } | undefined;
70
+ strike?: boolean | undefined;
71
+ doubleStrike?: boolean | undefined;
72
+ vertAlign?: "baseline" | "superscript" | "subscript" | undefined;
73
+ smallCaps?: boolean | undefined;
74
+ allCaps?: boolean | undefined;
75
+ hidden?: boolean | undefined;
76
+ noProof?: boolean | undefined;
77
+ color?: import("@stll/docx-core/model").ColorValue | undefined;
78
+ highlight?: "black" | "blue" | "cyan" | "darkBlue" | "darkCyan" | "darkGray" | "darkGreen" | "darkMagenta" | "darkRed" | "darkYellow" | "green" | "lightGray" | "magenta" | "none" | "red" | "white" | "yellow" | undefined;
79
+ shading?: import("@stll/docx-core/model").ShadingProperties | undefined;
80
+ fontSize?: number | undefined;
81
+ fontSizeCs?: number | undefined;
82
+ fontFamily?: {
83
+ ascii?: string;
84
+ hAnsi?: string;
85
+ eastAsia?: string;
86
+ cs?: string;
87
+ hint?: "default" | "eastAsia" | "cs";
88
+ asciiTheme?: "majorAscii" | "majorHAnsi" | "majorEastAsia" | "majorBidi" | "minorAscii" | "minorHAnsi" | "minorEastAsia" | "minorBidi";
89
+ hAnsiTheme?: string;
90
+ eastAsiaTheme?: string;
91
+ csTheme?: string;
92
+ } | undefined;
93
+ language?: {
94
+ val?: string;
95
+ eastAsia?: string;
96
+ bidi?: string;
97
+ } | undefined;
98
+ spacing?: number | undefined;
99
+ position?: number | undefined;
100
+ scale?: number | undefined;
101
+ kerning?: number | undefined;
102
+ effect?: import("@stll/docx-core/model").TextEffect | undefined;
103
+ emphasisMark?: import("@stll/docx-core/model").EmphasisMark | undefined;
104
+ emboss?: boolean | undefined;
105
+ imprint?: boolean | undefined;
106
+ outline?: boolean | undefined;
107
+ shadow?: boolean | undefined;
108
+ rtl?: boolean | undefined;
109
+ cs?: boolean | undefined;
110
+ styleId?: string | undefined;
111
+ preserved?: import("@stll/docx-core/model").PreservedMarkup | undefined;
112
+ }>;
113
+ readonly from: number;
114
+ readonly to: number;
115
+ readonly type: "formatRun";
116
+ }];
117
+ declare const withCanonicalParagraphFormatting: (command: Command, patch: ParagraphPropsPatch | ((paragraph: Node) => ParagraphPropsPatch)) => Command;
118
+ /** Commands that read the selection start apply that same patch across selected paragraphs. */
119
+ declare const withCanonicalStartParagraphFormatting: (command: Command, patch: (paragraph: Node) => ParagraphPropsPatch) => Command;
120
+ //#endregion
121
+ export { CanonicalCommandIntent, canonicalRunFormatting, getCanonicalCommandIntents, withCanonicalCommand, withCanonicalParagraphFormatting, withCanonicalStartParagraphFormatting };
@@ -0,0 +1,35 @@
1
+ import { canonicalSelectionRange } from "./canonicalSelectionRange.js";
2
+ //#region src/prosemirror/canonicalCommands.ts
3
+ const descriptors = /* @__PURE__ */ new WeakMap();
4
+ /** Registration leaves execution and side-effect-free command probes unchanged. */
5
+ const withCanonicalCommand = (command, descriptor) => {
6
+ descriptors.set(command, descriptor);
7
+ return command;
8
+ };
9
+ const getCanonicalCommandIntents = (command, state) => descriptors.get(command)?.(state);
10
+ const canonicalRunFormatting = (state, patch) => [{
11
+ type: "formatRun",
12
+ ...canonicalSelectionRange(state),
13
+ patch
14
+ }];
15
+ const canonicalParagraphFormatting = (state, patch) => {
16
+ const intents = [];
17
+ state.doc.nodesBetween(state.selection.from, state.selection.to, (node, position) => {
18
+ if (node.type.name !== "paragraph") return;
19
+ intents.push({
20
+ type: "formatParagraph",
21
+ at: position + 1,
22
+ patch: typeof patch === "function" ? patch(node) : patch
23
+ });
24
+ });
25
+ return intents;
26
+ };
27
+ const withCanonicalParagraphFormatting = (command, patch) => withCanonicalCommand(command, (state) => canonicalParagraphFormatting(state, patch));
28
+ /** Commands that read the selection start apply that same patch across selected paragraphs. */
29
+ const withCanonicalStartParagraphFormatting = (command, patch) => withCanonicalCommand(command, (state) => {
30
+ const paragraph = state.selection.$from.parent;
31
+ if (paragraph.type.name !== "paragraph") return [];
32
+ return canonicalParagraphFormatting(state, patch(paragraph));
33
+ });
34
+ //#endregion
35
+ export { canonicalRunFormatting, getCanonicalCommandIntents, withCanonicalCommand, withCanonicalParagraphFormatting, withCanonicalStartParagraphFormatting };
@@ -0,0 +1,9 @@
1
+ import { EditorState } from "prosemirror-state";
2
+ //#region src/prosemirror/canonicalSelectionRange.d.ts
3
+ /** Whole-document selection addresses paragraph content rather than document edges. */
4
+ declare const canonicalSelectionRange: ({ doc, selection }: EditorState) => {
5
+ from: number;
6
+ to: number;
7
+ };
8
+ //#endregion
9
+ export { canonicalSelectionRange };
@@ -0,0 +1,15 @@
1
+ import { AllSelection, Selection } from "prosemirror-state";
2
+ //#region src/prosemirror/canonicalSelectionRange.ts
3
+ /** Whole-document selection addresses paragraph content rather than document edges. */
4
+ const canonicalSelectionRange = ({ doc, selection }) => {
5
+ if (selection instanceof AllSelection) return {
6
+ from: Selection.atStart(doc).from,
7
+ to: Selection.atEnd(doc).to
8
+ };
9
+ return {
10
+ from: selection.from,
11
+ to: selection.to
12
+ };
13
+ };
14
+ //#endregion
15
+ export { canonicalSelectionRange };
@@ -0,0 +1,7 @@
1
+ import { Slice } from "prosemirror-model";
2
+ import { EditorView } from "prosemirror-view";
3
+ //#region src/prosemirror/clipboardIntent.d.ts
4
+ declare const registerClipboardIntentHandler: (view: EditorView, handler: (slice: Slice, plain: boolean) => boolean) => void;
5
+ declare const dispatchClipboardIntent: (view: EditorView, slice: Slice) => boolean | undefined;
6
+ //#endregion
7
+ export { dispatchClipboardIntent, registerClipboardIntentHandler };
@@ -0,0 +1,9 @@
1
+ //#region src/prosemirror/clipboardIntent.ts
2
+ /** Async clipboard reads resolve against the current owning session and selection. */
3
+ const handlers = /* @__PURE__ */ new WeakMap();
4
+ const registerClipboardIntentHandler = (view, handler) => {
5
+ handlers.set(view, handler);
6
+ };
7
+ const dispatchClipboardIntent = (view, slice) => handlers.get(view)?.(slice, true);
8
+ //#endregion
9
+ export { dispatchClipboardIntent, registerClipboardIntentHandler };