@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,24 +1,6 @@
1
1
  import { CATALOGS as CATALOGS$1 } from "./messages/catalogs.gen.js";
2
+ import { FOLIO_LOCALES } from "./messages/locales.js";
2
3
  //#region src/i18n/messages.ts
3
- const FOLIO_LOCALES = [
4
- "en",
5
- "de",
6
- "fr",
7
- "es",
8
- "cs",
9
- "ar",
10
- "et",
11
- "he",
12
- "hi",
13
- "hu",
14
- "lt",
15
- "lv",
16
- "pl",
17
- "pt-BR",
18
- "sk",
19
- "tr",
20
- "zh-CN"
21
- ];
22
4
  const CATALOGS = CATALOGS$1;
23
5
  const FOLIO_LOCALE_SET = new Set(FOLIO_LOCALES);
24
6
  const isFolioLocale = (locale) => FOLIO_LOCALE_SET.has(locale);
@@ -0,0 +1,12 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/internal/acceptedBlockProjection.d.ts
3
+ /**
4
+ * Read a model story through the same structural resolver as Accept All and
5
+ * the editor's No Markup view. The authored model is never changed.
6
+ */
7
+ declare const projectAcceptedBlocks: (blocks: readonly document_d_exports.BlockContent[], pkg: document_d_exports.DocxPackage | undefined) => {
8
+ blocks: readonly document_d_exports.BlockContent[];
9
+ completeness: string;
10
+ } | null;
11
+ //#endregion
12
+ export { projectAcceptedBlocks };
@@ -0,0 +1,45 @@
1
+ import { getCachedNumberingMap } from "../docx/numberingParser.js";
2
+ import { proseDocToBlocks } from "../prosemirror/conversion/fromProseDoc.js";
3
+ import { headerFooterToProseDoc } from "../prosemirror/conversion/toProseDoc.js";
4
+ import { createStyleEngine } from "../style-engine/styleEngine.js";
5
+ import { resolveWholeStory } from "./wholeStoryRevisionResolution.js";
6
+ import { panic } from "better-result";
7
+ //#region src/internal/acceptedBlockProjection.ts
8
+ /** Inline revisions alone are already handled by the Markdown run renderer. */
9
+ const hasBlockRevision = (blocks) => blocks.some((block) => {
10
+ switch (block.type) {
11
+ case "paragraph": return block.pPrMark !== void 0;
12
+ case "table": return block.rows.some((row) => row.structuralChange !== void 0 || row.cells.some((cell) => cell.structuralChange !== void 0 || hasBlockRevision(cell.content)));
13
+ case "blockSdt":
14
+ case "blockCustomXml": return hasBlockRevision(block.content);
15
+ case "preservedBlock":
16
+ case "bookmarkStart":
17
+ case "bookmarkEnd": return false;
18
+ default: return panic("Unsupported block in accepted projection", { unsupported: block });
19
+ }
20
+ });
21
+ /**
22
+ * Read a model story through the same structural resolver as Accept All and
23
+ * the editor's No Markup view. The authored model is never changed.
24
+ */
25
+ const projectAcceptedBlocks = (blocks, pkg) => {
26
+ if (!hasBlockRevision(blocks)) return null;
27
+ const options = {
28
+ ...pkg?.styles !== void 0 && { styles: pkg.styles },
29
+ ...pkg?.theme !== void 0 && { theme: pkg.theme },
30
+ ...pkg?.numbering !== void 0 && { numbering: pkg.numbering }
31
+ };
32
+ const doc = headerFooterToProseDoc([...blocks], options);
33
+ const result = resolveWholeStory({
34
+ doc,
35
+ mode: "accept",
36
+ styleResolver: createStyleEngine(pkg?.styles),
37
+ numbering: pkg?.numbering ? getCachedNumberingMap(pkg.numbering) : null
38
+ });
39
+ return {
40
+ blocks: result.resolved.eq(doc) ? blocks : proseDocToBlocks(result.resolved, [...blocks], pkg?.styles),
41
+ completeness: result.failed ? "partial" : "complete"
42
+ };
43
+ };
44
+ //#endregion
45
+ export { projectAcceptedBlocks };
@@ -0,0 +1,8 @@
1
+ import { NoteMarkerAttrs } from "../prosemirror/schema/nodes.js";
2
+ import { ReadProseMirrorAttrsResult } from "./prosemirrorAttrBoundary.js";
3
+ import { Node } from "prosemirror-model";
4
+ //#region src/internal/noteMarkerAttrs.d.ts
5
+ declare const readNoteMarkerAttrs: (node: Node) => ReadProseMirrorAttrsResult<NoteMarkerAttrs>;
6
+ declare const expectNoteMarkerAttrs: (node: Node) => NoteMarkerAttrs;
7
+ //#endregion
8
+ export { expectNoteMarkerAttrs, readNoteMarkerAttrs };
@@ -0,0 +1,16 @@
1
+ import { attrsRecord, attrsResult, expectCachedNodeAttrs, expectNodeType } from "./prosemirrorAttrBoundary.js";
2
+ //#region src/internal/noteMarkerAttrs.ts
3
+ const noteMarkerAttrsCache = /* @__PURE__ */ new WeakMap();
4
+ const readNoteMarkerAttrs = (node) => {
5
+ const attrs = attrsRecord(node.attrs);
6
+ const issues = [];
7
+ expectNodeType(node, "noteMarker", issues);
8
+ if (attrs["kind"] !== "footnote" && attrs["kind"] !== "endnote") issues.push({
9
+ path: "noteMarker.attrs.kind",
10
+ message: "Expected footnote or endnote."
11
+ });
12
+ return attrsResult(attrs, issues);
13
+ };
14
+ const expectNoteMarkerAttrs = (node) => expectCachedNodeAttrs(node, noteMarkerAttrsCache, readNoteMarkerAttrs, "noteMarker attrs");
15
+ //#endregion
16
+ export { expectNoteMarkerAttrs, readNoteMarkerAttrs };
@@ -37,6 +37,7 @@ const buildPageBreakRunSourceDescendantIndex = (rootContent) => {
37
37
  case "footnoteRef":
38
38
  case "instrText":
39
39
  case "noBreakHyphen":
40
+ case "noteMarker":
40
41
  case "preservedXml":
41
42
  case "renderedPageBreak":
42
43
  case "softHyphen":
@@ -0,0 +1,21 @@
1
+ import { Node } from "prosemirror-model";
2
+ //#region src/internal/prosemirrorAttrBoundary.d.ts
3
+ type ProseMirrorAttrIssue = {
4
+ readonly path: string;
5
+ readonly message: string;
6
+ };
7
+ type ReadProseMirrorAttrsResult<T> = {
8
+ ok: true;
9
+ value: T;
10
+ } | {
11
+ ok: false;
12
+ issues: readonly ProseMirrorAttrIssue[];
13
+ };
14
+ declare const attrsRecord: (attrs: unknown) => Record<string, unknown>;
15
+ declare const isRecord: (value: unknown) => value is Record<string, unknown>;
16
+ declare const attrsResult: <T>(attrs: Record<string, unknown>, issues: ProseMirrorAttrIssue[]) => ReadProseMirrorAttrsResult<T>;
17
+ declare const expectAttrs: <T>(result: ReadProseMirrorAttrsResult<T>, label: string) => T;
18
+ declare function expectCachedNodeAttrs<T extends object>(node: Node, cache: WeakMap<Node, T>, reader: (node: Node) => ReadProseMirrorAttrsResult<T>, label: string): T;
19
+ declare const expectNodeType: (node: Node, expected: string, issues: ProseMirrorAttrIssue[]) => void;
20
+ //#endregion
21
+ export { ProseMirrorAttrIssue, ReadProseMirrorAttrsResult, attrsRecord, attrsResult, expectAttrs, expectCachedNodeAttrs, expectNodeType, isRecord };
@@ -0,0 +1,50 @@
1
+ import { panic } from "better-result";
2
+ //#region src/internal/prosemirrorAttrBoundary.ts
3
+ const attrsRecord = (attrs) => {
4
+ if (isRecord(attrs)) return attrs;
5
+ return {};
6
+ };
7
+ const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
8
+ const attrsResult = (attrs, issues) => {
9
+ if (issues.length > 0) return {
10
+ ok: false,
11
+ issues
12
+ };
13
+ let normalizedAttrs;
14
+ return {
15
+ ok: true,
16
+ get value() {
17
+ if (normalizedAttrs !== void 0) return normalizedAttrs;
18
+ const presentAttrs = {};
19
+ for (const key in attrs) {
20
+ if (!Object.hasOwn(attrs, key)) continue;
21
+ const value = attrs[key];
22
+ if (value !== null) presentAttrs[key] = value;
23
+ }
24
+ normalizedAttrs = presentAttrs;
25
+ return normalizedAttrs;
26
+ },
27
+ set value(value) {
28
+ normalizedAttrs = value;
29
+ }
30
+ };
31
+ };
32
+ const expectAttrs = (result, label) => {
33
+ if (result.ok) return result.value;
34
+ panic(`Invalid ProseMirror ${label}:\n${result.issues.map((issue) => `${issue.path}: ${issue.message}`).join("\n")}`);
35
+ };
36
+ function expectCachedNodeAttrs(node, cache, reader, label) {
37
+ const cached = cache.get(node);
38
+ if (cached) return cached;
39
+ const value = expectAttrs(reader(node), label);
40
+ cache.set(node, value);
41
+ return value;
42
+ }
43
+ const expectNodeType = (node, expected, issues) => {
44
+ if (node.type.name !== expected) issues.push({
45
+ path: "node.type.name",
46
+ message: `Expected ${expected}, got ${node.type.name}.`
47
+ });
48
+ };
49
+ //#endregion
50
+ export { attrsRecord, attrsResult, expectAttrs, expectCachedNodeAttrs, expectNodeType, isRecord };
@@ -6,6 +6,7 @@ import "./toFlowBlocks.js";
6
6
  type MeasureBlocksFn = (blocks: FlowBlock[], contentWidth: number) => Measure[];
7
7
  type ConvertFootnoteOptions = {
8
8
  styles?: document_d_exports.StyleDefinitions | null;
9
+ numbering?: document_d_exports.NumberingDefinitions;
9
10
  theme?: document_d_exports.Theme | null;
10
11
  defaultSize?: number;
11
12
  fontAlternates?: ToFlowBlocksOptions["fontAlternates"];
@@ -1,9 +1,8 @@
1
1
  import { measureParagraph } from "../../layout-engine/measure/measureParagraph.js";
2
2
  import { layoutTextBoxContent } from "../../layout-engine/measure/textBoxParagraphLayout.js";
3
3
  import { DEFAULT_TEXTBOX_MARGINS, FOOTNOTE_ENTRY_MARGIN_BOTTOM, FOOTNOTE_FALLBACK_LINE_HEIGHT, FOOTNOTE_SEPARATOR_HEIGHT, isFloatingImageRun, resolveTableWidthPx } from "../../layout-engine/types.js";
4
- import { expectPreservedXmlAttrs } from "../../prosemirror/attrs/index.js";
5
4
  import { footnoteToProseDoc } from "../../prosemirror/conversion/toProseDoc.js";
6
- import { collectNoteRefs, isNoteReferenceMarkXml } from "./noteReferences.js";
5
+ import { collectNoteRefs } from "./noteReferences.js";
7
6
  import { toFlowBlocks } from "./toFlowBlocks.js";
8
7
  //#region src/layout-bridge/convert/footnoteLayout.ts
9
8
  /** Default footnote font size in points */
@@ -203,6 +202,7 @@ function convertNoteStoryToFlowBlocks(content, options, referenceMarkText) {
203
202
  const proseOptions = {};
204
203
  if (options.styles) proseOptions.styles = options.styles;
205
204
  if (options.theme !== void 0) proseOptions.theme = options.theme;
205
+ if (options.numbering !== void 0) proseOptions.numbering = options.numbering;
206
206
  const pmDoc = footnoteToProseDoc(content, proseOptions);
207
207
  const flowOptions = {};
208
208
  if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
@@ -225,7 +225,7 @@ function containsNoteReferenceMark(doc) {
225
225
  let found = false;
226
226
  doc.descendants((node) => {
227
227
  if (found) return false;
228
- if (node.type.name === "preservedXml" && isNoteReferenceMarkXml(expectPreservedXmlAttrs(node).xml)) found = true;
228
+ if (node.type.name === "noteMarker") found = true;
229
229
  return !found;
230
230
  });
231
231
  return found;
@@ -41,6 +41,7 @@ declare function calculateHeaderFooterMarginPushBounds(blocks: FlowBlock[], meas
41
41
  declare function calculateHeaderFooterBodyTopClearance(blocks: FlowBlock[], flowHeight: number, metrics: HeaderFooterMetrics): number | undefined;
42
42
  type ConvertHeaderFooterOptions = {
43
43
  styles?: document_d_exports.StyleDefinitions | null;
44
+ numbering?: document_d_exports.NumberingDefinitions;
44
45
  theme?: document_d_exports.Theme | null;
45
46
  defaultSize?: number;
46
47
  fontAlternates?: ToFlowBlocksOptions["fontAlternates"];
@@ -340,6 +340,7 @@ function convertHeaderFooterToContent(headerFooter, contentWidth, metrics, optio
340
340
  const proseDocOptions = {};
341
341
  if (options.styles) proseDocOptions.styles = options.styles;
342
342
  if (options.theme !== void 0) proseDocOptions.theme = options.theme;
343
+ if (options.numbering !== void 0) proseDocOptions.numbering = options.numbering;
343
344
  const pmDoc = headerFooter.watermarkBlockIndex === void 0 ? headerFooterToProseDoc(headerFooter.content, proseDocOptions) : headerFooterToProseDocWithDetachedWatermarkHost(headerFooter, proseDocOptions);
344
345
  const flowOptions = {};
345
346
  if (options.defaultSize !== void 0) flowOptions.defaultSize = options.defaultSize;
@@ -8,7 +8,5 @@ declare function collectNoteRefs(blocks: readonly FlowBlock[], idKey: "footnoteR
8
8
  noteId: number;
9
9
  pmPos: number;
10
10
  }[];
11
- /** Whether captured run-child markup is a note story's `w:footnoteRef`/`w:endnoteRef`. */
12
- declare function isNoteReferenceMarkXml(xml: string): boolean;
13
11
  //#endregion
14
- export { collectNoteRefs, isNoteReferenceMarkXml };
12
+ export { collectNoteRefs };
@@ -1,5 +1,4 @@
1
1
  //#region src/layout-bridge/convert/noteReferences.ts
2
- const NOTE_REFERENCE_MARK_XML = /^<(?:[^\s:/>]+:)?(?:footnoteRef|endnoteRef)[\s/>]/u;
3
2
  /**
4
3
  * Runs with `idKey` set, in document order: the note references a block list
5
4
  * makes, through table cells (and tables within cells) and text boxes.
@@ -21,9 +20,5 @@ function collectNoteRefs(blocks, idKey) {
21
20
  walk(blocks);
22
21
  return refs;
23
22
  }
24
- /** Whether captured run-child markup is a note story's `w:footnoteRef`/`w:endnoteRef`. */
25
- function isNoteReferenceMarkXml(xml) {
26
- return NOTE_REFERENCE_MARK_XML.test(xml);
27
- }
28
23
  //#endregion
29
- export { collectNoteRefs, isNoteReferenceMarkXml };
24
+ export { collectNoteRefs };
@@ -3,7 +3,6 @@ import { expectFieldAttrs, expectImageAttrs, expectMathAttrs, expectParagraphAtt
3
3
  import { decodeOoxmlSymbolCharacter } from "../../utils/ooxmlSymbol.js";
4
4
  import { tableOfContentsStyleLevel } from "../../utils/tableOfContentsStyle.js";
5
5
  import { buildImageRun, constrainImageToPage, hasPaintableImageSource, hasRelationshipBackedImageBox } from "./imageConversion.js";
6
- import { isNoteReferenceMarkXml } from "./noteReferences.js";
7
6
  import { applyCharacterStyleToggleFormatting, markDefaultBlackTextColorSource, mergeRunFormatting } from "./runFormattingMerge.js";
8
7
  import { extractRunFormatting } from "./runMarkFormatting.js";
9
8
  import { paragraphRunDefaults } from "./textFormattingConversion.js";
@@ -135,9 +134,8 @@ function paragraphToRuns(node, startPos, _options, pageBreaks) {
135
134
  });
136
135
  return;
137
136
  }
138
- if (child.type.name === "preservedXml") {
139
- const { xml, text: capturedText } = expectPreservedXmlAttrs(child);
140
- const text = capturedText === "" && _options.noteReferenceMarkText !== void 0 && isNoteReferenceMarkXml(xml) ? _options.noteReferenceMarkText : capturedText;
137
+ if (child.type.name === "preservedXml" || child.type.name === "noteMarker") {
138
+ const text = child.type.name === "noteMarker" ? _options.noteReferenceMarkText ?? "" : expectPreservedXmlAttrs(child).text;
141
139
  if (text === "") return;
142
140
  const formatting = extractRunFormatting(effectiveMarks, theme, fontAlternates);
143
141
  applyCharacterStyleToggleFormatting({
@@ -1,7 +1,7 @@
1
1
  import { FlowBlock } from "../../layout-engine/types.js";
2
2
  import { formatCounter, resolveListTemplate } from "../../prosemirror/listMarker.js";
3
3
  import { ToFlowBlocksOptions, resetBlockIdCounter } from "./flowConversionShared.js";
4
- import { collectNoteRefs, isNoteReferenceMarkXml } from "./noteReferences.js";
4
+ import { collectNoteRefs } from "./noteReferences.js";
5
5
  import { convertBorderSpecToLayout } from "./flowBorders.js";
6
6
  import { Node } from "prosemirror-model";
7
7
  //#region src/layout-bridge/convert/toFlowBlocks.d.ts
@@ -21,4 +21,4 @@ declare const WORD_UNSPECIFIED_FONT_SIZE = 10;
21
21
  */
22
22
  declare function toFlowBlocks(doc: Node, options?: ToFlowBlocksOptions): FlowBlock[];
23
23
  //#endregion
24
- export { type ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
24
+ export { type ToFlowBlocksOptions, WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
@@ -12,7 +12,7 @@ import { mergeRunInParagraphs, reserveLeadingEmptyOutlineHeight, suppressFinalEm
12
12
  import { convertBorderSpecToLayout } from "./flowBorders.js";
13
13
  import { nextBlockId, resetBlockIdCounter, twipsToPixels } from "./flowConversionShared.js";
14
14
  import { convertImage } from "./imageConversion.js";
15
- import { collectNoteRefs, isNoteReferenceMarkXml } from "./noteReferences.js";
15
+ import { collectNoteRefs } from "./noteReferences.js";
16
16
  import { splitParagraphAtPageBreaks } from "./pageBreakSplitting.js";
17
17
  import { convertParagraph, drawsParagraphBorder } from "./paragraphConversion.js";
18
18
  import { groupParagraphFrames } from "./paragraphFrames.js";
@@ -417,4 +417,4 @@ function toFlowBlocks(doc, options = {}) {
417
417
  }), readFinalSectionStart(doc)), options.splitPageBreakAndParagraphMark === true, sectionBreaksWithoutMarker), nextBlockId);
418
418
  }
419
419
  //#endregion
420
- export { WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, isNoteReferenceMarkXml, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
420
+ export { WORD_UNSPECIFIED_FONT_SIZE, collectNoteRefs, convertBorderSpecToLayout, formatCounter, resetBlockIdCounter, resolveListTemplate, toFlowBlocks };
@@ -23,6 +23,7 @@ type DocumentLoaderHistory = {
23
23
  type DocumentLoaderCallbacks = {
24
24
  /** Editor history to reset/seed with the loaded document. */
25
25
  history: DocumentLoaderHistory;
26
+ getExperimentalSession?: () => "canonical" | undefined;
26
27
  /**
27
28
  * Receives the identity of the document that just landed in history. Every
28
29
  * load allocates a fresh identity, so the adapter can tell an external load
@@ -1,6 +1,8 @@
1
+ import { prepareCanonicalDocxInput } from "../docx/canonicalSessionInput.js";
1
2
  import { inspectDocxCompatibility } from "../docx/compatibility.js";
2
3
  import { parseDocx } from "../docx/parser.js";
3
4
  import { recordDocumentLoadPhase } from "../layout-engine/layoutInstrumentation.js";
5
+ import { CANONICAL_GAP, usesCanonicalSession } from "../types/canonicalCapabilities.js";
4
6
  import { resetAuthorColors } from "../utils/authorColors.js";
5
7
  import { loadFontsWithMapping } from "../utils/fontLoader.js";
6
8
  //#region src/managers/DocumentLoaderManager.ts
@@ -60,7 +62,13 @@ var DocumentLoaderManager = class {
60
62
  const parseStartedAt = performance.now();
61
63
  let doc;
62
64
  try {
63
- doc = await parseDocx(buffer, {
65
+ let input = buffer;
66
+ if (usesCanonicalSession(this.callbacks.getExperimentalSession?.(), CANONICAL_GAP.authorityRouting)) {
67
+ const prepared = await prepareCanonicalDocxInput(buffer);
68
+ if (prepared.isErr()) throw prepared.error;
69
+ input = prepared.value;
70
+ }
71
+ doc = await parseDocx(input, {
64
72
  detectVariables: false,
65
73
  preloadFonts: false,
66
74
  password: options.password
@@ -25,6 +25,8 @@ declare function escapeInline(text: string): string;
25
25
  * line.
26
26
  */
27
27
  declare function escapeTableCell(text: string): string;
28
+ /** Single-line Markdown blocks express inline breaks without their two-space syntax. */
29
+ declare const inlineBreaksToHtml: (text: string) => string;
28
30
  declare function escapeLinkUrl(url: string): string;
29
31
  /**
30
32
  * Alt text inside `![alt](url)`. Raw (un-escaped) text, so escape the backslash
@@ -33,4 +35,4 @@ declare function escapeLinkUrl(url: string): string;
33
35
  */
34
36
  declare function escapeAltText(text: string): string;
35
37
  //#endregion
36
- export { escapeAltText, escapeInline, escapeLinkUrl, escapeTableCell };
38
+ export { escapeAltText, escapeInline, escapeLinkUrl, escapeTableCell, inlineBreaksToHtml };
@@ -30,8 +30,15 @@ function escapeInline(text) {
30
30
  * line.
31
31
  */
32
32
  function escapeTableCell(text) {
33
- return text.replace(/\|/gu, "&#124;").replace(/\r?\n/gu, "<br>");
33
+ return inlineBreaksToHtml(text.replace(/\|/gu, "&#124;"));
34
34
  }
35
+ /** Single-line Markdown blocks express inline breaks without their two-space syntax. */
36
+ const inlineBreaksToHtml = (text) => text.split(/\r?\n/u).map((line, index, lines) => {
37
+ if (index === lines.length - 1) return line;
38
+ let end = line.length;
39
+ while (end > 0 && line.at(end - 1) === " ") end--;
40
+ return line.slice(0, end);
41
+ }).join("<br>");
35
42
  /**
36
43
  * Hyperlink URLs in inline form need parens balanced; we URL-encode the
37
44
  * problematic characters rather than escape, so the link still resolves.
@@ -55,4 +62,4 @@ function escapeAltText(text) {
55
62
  return text.replace(/(?<ch>[\\[\]])/gu, "\\$<ch>").replace(/\r?\n/gu, " ");
56
63
  }
57
64
  //#endregion
58
- export { escapeAltText, escapeInline, escapeLinkUrl, escapeTableCell };
65
+ export { escapeAltText, escapeInline, escapeLinkUrl, escapeTableCell, inlineBreaksToHtml };
@@ -1,6 +1,7 @@
1
1
  import { ALT_CHUNK_READER_DIAGNOSTIC, isAltChunkMarkup } from "../docx/altChunk.js";
2
2
  import { OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC, isOpaqueNestedRowMarkup, opaqueRevisionCarrierName } from "../docx/opaqueCarrier.js";
3
- import { cloneParagraphWithoutPropertySource } from "../docx/paragraphPropertySource.js";
3
+ import { projectAcceptedBlocks } from "../internal/acceptedBlockProjection.js";
4
+ import { pushWarning } from "./internals.js";
4
5
  import { renderParagraphBlock } from "./renderParagraph.js";
5
6
  import { renderTable } from "./renderTable.js";
6
7
  import { panic } from "better-result";
@@ -10,128 +11,14 @@ import { panic } from "better-result";
10
11
  * markdown for each block, suppressing redundant blank lines between list items
11
12
  * of the same list. Ported from eigenpal/docx-editor PR #595.
12
13
  */
13
- /**
14
- * In `trackedChanges: "clean"` mode every change is accepted, as the editor's
15
- * accept-all resolves the story (`internal/wholeStoryRevisionResolution.ts`).
16
- *
17
- * A paragraph whose mark is pending deletion loses its break on accept and
18
- * runs on into the paragraph after it, which is the paragraph left: its mark
19
- * ends the joined text, and a paragraph's properties (style, list) live on its
20
- * mark. A run of consecutive deletions collapses into that last paragraph.
21
- *
22
- * With a table right after it, its words run on into the table's first cell
23
- * and lead that cell's first paragraph (`prosemirror/tableRunIn.ts`), unless
24
- * it ends a section, keeps nothing once accepted, or that cell is pending.
25
- * Otherwise a paragraph that cannot join keeps its place, or goes when it
26
- * keeps nothing and something follows it.
27
- */
28
- function mergeAcceptedParagraphBreaks(blocks) {
29
- const reversed = [];
30
- let survivor = null;
31
- let tableFollows = false;
32
- let followed = false;
33
- const flush = () => {
34
- if (survivor) reversed.push(survivor);
35
- survivor = null;
36
- };
37
- for (let index = blocks.length - 1; index >= 0; index--) {
38
- const block = blocks[index];
39
- if (!block) continue;
40
- if (block.type !== "paragraph") {
41
- flush();
42
- reversed.push(block);
43
- tableFollows = block.type === "table";
44
- followed ||= tableFollows;
45
- continue;
46
- }
47
- const goes = block.pPrMark?.kind === "del" || block.pPrMark?.kind === "moveFrom";
48
- if (goes && survivor) {
49
- survivor = cloneParagraphWithoutPropertySource(survivor, { content: [...block.content, ...survivor.content] });
50
- continue;
51
- }
52
- const table = reversed.at(-1);
53
- if (goes && tableFollows && table?.type === "table") {
54
- const ranIn = tableWithParagraphRunIn(table, block);
55
- if (ranIn) {
56
- reversed[reversed.length - 1] = ranIn;
57
- continue;
58
- }
59
- }
60
- flush();
61
- tableFollows = false;
62
- if (goes && holdsNothingOnAccept(block) && followed && index + reversed.length > 0) continue;
63
- survivor = block;
64
- followed = true;
65
- }
66
- flush();
67
- return reversed.reverse();
68
- }
69
- /**
70
- * Whether the cell a paragraph's words would run into is itself pending (its
71
- * row or the cell, through nested tables' first cells), as
72
- * `prosemirror/tableRunIn.ts` reads it.
73
- */
74
- const runInCellPending = (table) => {
75
- const row = table.rows[0];
76
- const cell = row?.cells[0];
77
- if (!row || !cell) return false;
78
- if (row.structuralChange !== void 0 || cell.structuralChange !== void 0) return true;
79
- const first = cell.content[0];
80
- return first?.type === "table" && runInCellPending(first);
81
- };
82
- /**
83
- * `table` with `paragraph`'s words leading its first cell's first paragraph,
84
- * descending into nested tables, or null when the paragraph keeps its place.
85
- */
86
- const tableWithParagraphRunIn = (table, paragraph) => {
87
- if (paragraph.sectionProperties !== void 0 || holdsNothingOnAccept(paragraph)) return null;
88
- if (runInCellPending(table)) return null;
89
- const runIn = (current) => {
90
- const [row, ...rows] = current.rows;
91
- const [cell, ...cells] = row?.cells ?? [];
92
- const [first, ...rest] = cell?.content ?? [];
93
- if (!row || !cell || !first) return null;
94
- let led = null;
95
- if (first.type === "paragraph") led = cloneParagraphWithoutPropertySource(first, { content: [...paragraph.content, ...first.content] });
96
- else if (first.type === "table") led = runIn(first);
97
- if (!led) return null;
98
- return {
99
- ...current,
100
- rows: [{
101
- ...row,
102
- cells: [{
103
- ...cell,
104
- content: [led, ...rest]
105
- }, ...cells]
106
- }, ...rows]
107
- };
108
- };
109
- return runIn(table);
110
- };
111
- /** Paragraph content that shows nothing: range boundaries and anchors. */
112
- const ZERO_WIDTH_CONTENT = /* @__PURE__ */ new Set([
113
- "bookmarkStart",
114
- "bookmarkEnd",
115
- "commentRangeStart",
116
- "commentRangeEnd",
117
- "commentReference",
118
- "moveFromRangeStart",
119
- "moveFromRangeEnd",
120
- "moveToRangeStart",
121
- "moveToRangeEnd"
122
- ]);
123
- /** Whether an item shows nothing once every change is accepted. */
124
- const showsNothingOnAccept = (item) => {
125
- if (item.type === "deletion" || item.type === "moveFrom" || ZERO_WIDTH_CONTENT.has(item.type)) return true;
126
- if (item.type === "insertion" || item.type === "moveTo") return item.content.every(showsNothingOnAccept);
127
- return item.type === "run" && item.content.every((content) => content.type === "renderedPageBreak");
128
- };
129
- /** Whether a paragraph keeps no visible content once every change is accepted. */
130
- const holdsNothingOnAccept = (paragraph) => paragraph.content.every(showsNothingOnAccept);
131
14
  function renderBlocks(ctx, pkg, blocks) {
15
+ const outerListIndentWidths = ctx.listIndentWidths;
16
+ ctx.listIndentWidths = [];
132
17
  const out = [];
133
18
  let prevWasListItem = false;
134
- const ordered = ctx.opts.trackedChanges === "clean" ? mergeAcceptedParagraphBreaks(blocks) : blocks;
19
+ const projection = ctx.opts.trackedChanges === "clean" ? projectAcceptedBlocks(blocks, pkg) : null;
20
+ if (projection?.completeness === "partial") pushWarning(ctx, "Some tracked structural changes could not be resolved.");
21
+ const ordered = projection?.blocks ?? blocks;
135
22
  for (const block of ordered) switch (block.type) {
136
23
  case "paragraph": {
137
24
  const { markdown: md, isListItem } = renderParagraphBlock(ctx, pkg, block);
@@ -146,7 +33,9 @@ function renderBlocks(ctx, pkg, blocks) {
146
33
  break;
147
34
  }
148
35
  case "table": {
36
+ ctx.listIndentWidths = [];
149
37
  const md = renderTable(ctx, pkg, block);
38
+ ctx.listIndentWidths = [];
150
39
  if (md) {
151
40
  if (out.length) out.push("");
152
41
  out.push(md);
@@ -156,22 +45,32 @@ function renderBlocks(ctx, pkg, blocks) {
156
45
  }
157
46
  case "blockSdt":
158
47
  case "blockCustomXml": {
48
+ ctx.listIndentWidths = [];
159
49
  const nested = renderBlocks(ctx, pkg, block.content);
160
50
  if (nested) {
161
51
  if (out.length) out.push("");
162
52
  out.push(nested);
163
53
  }
54
+ ctx.listIndentWidths = [];
55
+ prevWasListItem = false;
164
56
  break;
165
57
  }
166
- case "preservedBlock":
58
+ case "preservedBlock": {
59
+ const previousLength = out.length;
167
60
  if (isAltChunkMarkup(block.xml)) out.push(block.readerText === void 0 ? ALT_CHUNK_READER_DIAGNOSTIC : `${ALT_CHUNK_READER_DIAGNOSTIC}\n\n${block.readerText}`);
168
61
  else if (opaqueRevisionCarrierName(block.xml) !== void 0) out.push(OPAQUE_REVISION_CARRIER_READER_DIAGNOSTIC);
169
62
  else if (isOpaqueNestedRowMarkup(block.xml)) out.push("[Unsupported nested w:tr content]");
63
+ if (out.length !== previousLength) {
64
+ ctx.listIndentWidths = [];
65
+ prevWasListItem = false;
66
+ }
170
67
  break;
68
+ }
171
69
  case "bookmarkStart":
172
70
  case "bookmarkEnd": break;
173
71
  default: panic(`Unsupported block content in markdown: ${JSON.stringify(block)}`);
174
72
  }
73
+ ctx.listIndentWidths = outerListIndentWidths;
175
74
  return out.join("\n");
176
75
  }
177
76
  //#endregion