@stll/folio-core 0.42.0 → 0.44.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 (206) hide show
  1. package/dist/ai-edits/headless.js +6 -5
  2. package/dist/ai-edits/index.d.ts +2 -2
  3. package/dist/ai-edits/index.js +2 -2
  4. package/dist/ai-edits/snapshot.js +13 -9
  5. package/dist/compare/content-alignment.js +16 -1
  6. package/dist/compare/inline-atoms.js +1 -1
  7. package/dist/compare/style-resources.js +6 -0
  8. package/dist/compat/eigenpal.d.ts +2 -2
  9. package/dist/controller/layoutPipeline.d.ts +2 -1
  10. package/dist/controller/layoutPipeline.js +5 -2
  11. package/dist/controller/layoutSession.d.ts +2 -1
  12. package/dist/controller/layoutSession.js +1 -0
  13. package/dist/docx/appVersionNormalization.d.ts +0 -18
  14. package/dist/docx/blockContentParser.js +10 -1
  15. package/dist/docx/blockRangeMarkers.d.ts +36 -0
  16. package/dist/docx/blockRangeMarkers.js +59 -0
  17. package/dist/docx/bookmarkParser.d.ts +2 -20
  18. package/dist/docx/bookmarkParser.js +6 -30
  19. package/dist/docx/borderParser.d.ts +13 -0
  20. package/dist/docx/borderParser.js +71 -0
  21. package/dist/docx/builtInStyles.d.ts +165 -0
  22. package/dist/docx/builtInStyles.js +239 -0
  23. package/dist/docx/commentIdNormalization.d.ts +10 -0
  24. package/dist/docx/commentIdNormalization.js +33 -0
  25. package/dist/docx/commentParser.d.ts +2 -1
  26. package/dist/docx/commentParser.js +34 -7
  27. package/dist/docx/commentReferenceNormalization.d.ts +4 -1
  28. package/dist/docx/commentReferenceNormalization.js +23 -14
  29. package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
  30. package/dist/docx/danglingRelationshipReferences.js +30 -0
  31. package/dist/docx/defaultParagraphStyle.d.ts +39 -0
  32. package/dist/docx/defaultParagraphStyle.js +54 -0
  33. package/dist/docx/documentParser.d.ts +2 -1
  34. package/dist/docx/documentParser.js +2 -2
  35. package/dist/docx/drawingUtils.d.ts +8 -1
  36. package/dist/docx/drawingUtils.js +12 -3
  37. package/dist/docx/fieldParser.js +3 -5
  38. package/dist/docx/footnoteParser.d.ts +3 -2
  39. package/dist/docx/footnoteParser.js +19 -2
  40. package/dist/docx/groupDrawingParser.js +1 -1
  41. package/dist/docx/headerFooterRefParser.d.ts +15 -3
  42. package/dist/docx/headerFooterRefParser.js +51 -14
  43. package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
  44. package/dist/docx/headerFooterReferenceNormalization.js +5 -1
  45. package/dist/docx/hyperlinkParser.js +11 -15
  46. package/dist/docx/imageParser.d.ts +1 -1
  47. package/dist/docx/imageParser.js +22 -18
  48. package/dist/docx/imageRawXml.js +5 -5
  49. package/dist/docx/markupRangeMarker.d.ts +15 -0
  50. package/dist/docx/markupRangeMarker.js +44 -0
  51. package/dist/docx/noteReferenceStyles.d.ts +29 -0
  52. package/dist/docx/noteReferenceStyles.js +70 -0
  53. package/dist/docx/numberingParser.js +2 -1
  54. package/dist/docx/numberingReference.d.ts +21 -0
  55. package/dist/docx/numberingReference.js +21 -0
  56. package/dist/docx/numberingReferenceNormalization.d.ts +14 -2
  57. package/dist/docx/numberingReferenceNormalization.js +51 -9
  58. package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
  59. package/dist/docx/paragraphParser.js +69 -101
  60. package/dist/docx/paragraphPropertySource.js +1 -0
  61. package/dist/docx/paragraphTraversal.d.ts +37 -1
  62. package/dist/docx/paragraphTraversal.js +84 -1
  63. package/dist/docx/parseContext.d.ts +37 -0
  64. package/dist/docx/parseContext.js +67 -0
  65. package/dist/docx/parseWarningMessage.d.ts +6 -0
  66. package/dist/docx/parseWarningMessage.js +44 -0
  67. package/dist/docx/parser.js +86 -24
  68. package/dist/docx/relsParser.d.ts +28 -11
  69. package/dist/docx/relsParser.js +26 -13
  70. package/dist/docx/revisionIdNormalization.js +81 -7
  71. package/dist/docx/rezip.js +85 -27
  72. package/dist/docx/runConsolidator.js +1 -2
  73. package/dist/docx/runParser.d.ts +8 -1
  74. package/dist/docx/runParser.js +30 -48
  75. package/dist/docx/sectionParser.d.ts +2 -1
  76. package/dist/docx/sectionParser.js +21 -65
  77. package/dist/docx/serializer/borderSerializer.d.ts +1 -2
  78. package/dist/docx/serializer/commentSerializer.js +22 -9
  79. package/dist/docx/serializer/documentSerializer.d.ts +1 -5
  80. package/dist/docx/serializer/documentSerializer.js +6 -16
  81. package/dist/docx/serializer/headerFooterSerializer.js +5 -0
  82. package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
  83. package/dist/docx/serializer/markupRangeAttributes.js +24 -0
  84. package/dist/docx/serializer/noteSerializer.js +5 -0
  85. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
  86. package/dist/docx/serializer/paragraphSerializer.js +29 -35
  87. package/dist/docx/serializer/runSerializer.js +13 -7
  88. package/dist/docx/serializer/tableSerializer.js +28 -13
  89. package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
  90. package/dist/docx/server/build.js +8 -1
  91. package/dist/docx/server/createBilingualDocument.js +15 -22
  92. package/dist/docx/server/extractDocxText.js +3 -4
  93. package/dist/docx/shadingParser.d.ts +6 -0
  94. package/dist/docx/shadingParser.js +32 -0
  95. package/dist/docx/shapeParser.js +3 -3
  96. package/dist/docx/styleParser.js +15 -89
  97. package/dist/docx/styleReferenceResolution.d.ts +36 -0
  98. package/dist/docx/styleReferenceResolution.js +51 -0
  99. package/dist/docx/tableLook.d.ts +57 -0
  100. package/dist/docx/tableLook.js +63 -0
  101. package/dist/docx/tableParser.d.ts +7 -9
  102. package/dist/docx/tableParser.js +64 -110
  103. package/dist/docx/textBoxParser.js +4 -4
  104. package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
  105. package/dist/docx/trackedMoveRangeNormalization.js +11 -21
  106. package/dist/docx/transitionalSpelling.d.ts +13 -2
  107. package/dist/docx/transitionalSpelling.js +23 -1
  108. package/dist/docx/verbatimCapture.js +4 -11
  109. package/dist/docx/vmlImageParser.js +2 -2
  110. package/dist/docx/watermarkParser.js +2 -2
  111. package/dist/docx/xmlParser.d.ts +22 -32
  112. package/dist/docx/xmlParser.js +36 -21
  113. package/dist/index.d.ts +2 -2
  114. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +2 -0
  115. package/dist/internal/pageBreakRunSourceDescendantIndex.js +9 -6
  116. package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
  117. package/dist/internal/paragraphFormattingSerialization.js +26 -6
  118. package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
  119. package/dist/layout-bridge/convert/templatePreviewFlow.d.ts +19 -11
  120. package/dist/layout-bridge/convert/templatePreviewFlow.js +103 -38
  121. package/dist/layout-bridge/convert/toFlowBlocks.js +12 -3
  122. package/dist/layout-engine/index.d.ts +2 -2
  123. package/dist/layout-engine/index.js +2 -2
  124. package/dist/layout-engine/measure/measureBlocks.js +1 -6
  125. package/dist/layout-engine/types.d.ts +8 -2
  126. package/dist/layout-engine/types.js +35 -2
  127. package/dist/markdown/index.js +1 -1
  128. package/dist/markdown/internals.d.ts +6 -1
  129. package/dist/markdown/internals.js +14 -1
  130. package/dist/markdown/renderBlock.js +35 -21
  131. package/dist/markdown/renderParagraph.js +14 -5
  132. package/dist/markdown/renderRuns.js +4 -3
  133. package/dist/markdown/renderTable.js +4 -3
  134. package/dist/markdown/trailers.js +41 -7
  135. package/dist/markdown/types.d.ts +3 -7
  136. package/dist/prosemirror/attrs/index.js +2 -5
  137. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
  138. package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
  139. package/dist/prosemirror/commands/index.d.ts +3 -3
  140. package/dist/prosemirror/commands/index.js +2 -2
  141. package/dist/prosemirror/commands/pageBreak.js +12 -1
  142. package/dist/prosemirror/commands/paragraph.d.ts +3 -3
  143. package/dist/prosemirror/commands/paragraph.js +2 -2
  144. package/dist/prosemirror/commentIdAllocator.js +2 -7
  145. package/dist/prosemirror/conversion/fromProseDoc.js +131 -41
  146. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
  147. package/dist/prosemirror/conversion/toProseDoc.js +402 -328
  148. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
  149. package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
  150. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
  151. package/dist/prosemirror/extensions/features/ListExtension.js +42 -4
  152. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  153. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
  154. package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
  155. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
  156. package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
  157. package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
  158. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
  159. package/dist/prosemirror/extensions/nodes/ImageExtension.js +2 -1
  160. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +1 -0
  161. package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
  162. package/dist/prosemirror/extensions/types.d.ts +2 -2
  163. package/dist/prosemirror/index.d.ts +3 -3
  164. package/dist/prosemirror/index.js +3 -3
  165. package/dist/prosemirror/insertOperations.d.ts +9 -2
  166. package/dist/prosemirror/insertOperations.js +9 -4
  167. package/dist/prosemirror/listMarker.js +2 -1
  168. package/dist/prosemirror/numberedRefFields.js +2 -1
  169. package/dist/prosemirror/pageBreakRunProjection.d.ts +11 -3
  170. package/dist/prosemirror/pageBreakRunProjection.js +16 -8
  171. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +159 -0
  172. package/dist/prosemirror/paragraphFormattingProvenance.js +106 -0
  173. package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
  174. package/dist/prosemirror/plugins/documentStyles.js +11 -1
  175. package/dist/prosemirror/plugins/index.d.ts +2 -2
  176. package/dist/prosemirror/plugins/index.js +2 -2
  177. package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
  178. package/dist/prosemirror/plugins/revisionIds.js +21 -6
  179. package/dist/prosemirror/plugins/templatePreviewValues.d.ts +42 -1
  180. package/dist/prosemirror/plugins/templatePreviewValues.js +217 -14
  181. package/dist/prosemirror/runFormattingReconciliation.js +3 -2
  182. package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
  183. package/dist/prosemirror/schema/nodes.d.ts +31 -0
  184. package/dist/prosemirror/styles/resolvedStyleAttrs.js +4 -1
  185. package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
  186. package/dist/prosemirror/styles/styleResolver.js +15 -6
  187. package/dist/prosemirror/utils/visualLineNavigation.d.ts +22 -2
  188. package/dist/prosemirror/utils/visualLineNavigation.js +80 -63
  189. package/dist/style-engine/styleEngine.d.ts +4 -1
  190. package/dist/style-engine/styleEngine.js +3 -0
  191. package/dist/style-sets/extract.js +35 -11
  192. package/dist/style-sets/stellaStyle.js +46 -39
  193. package/dist/style-sets/styleSetNormalization.d.ts +19 -0
  194. package/dist/style-sets/styleSetNormalization.js +99 -0
  195. package/dist/types/content.d.ts +2 -2
  196. package/dist/utils/createDocument.js +145 -20
  197. package/dist/utils/headingCollector.d.ts +8 -5
  198. package/dist/utils/headingCollector.js +23 -25
  199. package/dist/utils/tableOfContentsStyle.js +9 -2
  200. package/package.json +3 -2
  201. package/dist/docx/textWhitespace.d.ts +0 -4
  202. package/dist/docx/textWhitespace.js +0 -4
  203. package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
  204. package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
  205. package/dist/markdown/headings.d.ts +0 -13
  206. package/dist/markdown/headings.js +0 -20
@@ -1,7 +1,8 @@
1
+ import { findCollapsedLineEdgeCaretTarget } from "../../layout-bridge/dom/clickToPositionDom.js";
1
2
  import { findBodyEmptyRuns, findBodyPmSpans } from "../../layout-bridge/dom/findBodyPmSpans.js";
2
3
  import { createTextStreamRange, descendantTextNodes, totalTextLength } from "../../layout-bridge/dom/textStreamDom.js";
3
4
  import { findVerticalScrollParent } from "../../utils/findVerticalScrollParent.js";
4
- import { TextSelection } from "prosemirror-state";
5
+ import { Selection, TextSelection } from "prosemirror-state";
5
6
  //#region src/prosemirror/utils/visualLineNavigation.ts
6
7
  /**
7
8
  * Visual line navigation helpers — implements Word/Google-Docs-style
@@ -17,12 +18,10 @@ import { TextSelection } from "prosemirror-state";
17
18
  * @internal
18
19
  */
19
20
  const CONTENT_LINE_SELECTOR = ".layout-page-content .layout-line";
21
+ const PM_SPAN_SELECTOR = "span[data-pm-start][data-pm-end]";
20
22
  /** @internal */
21
23
  function createVisualLineState() {
22
- return {
23
- stickyX: null,
24
- lastVisualLineIndex: -1
25
- };
24
+ return { step: null };
26
25
  }
27
26
  function scrollIntoViewIfNeeded(el) {
28
27
  const container = findVerticalScrollParent(el);
@@ -35,7 +34,10 @@ function scrollIntoViewIfNeeded(el) {
35
34
  }
36
35
  /** @internal */
37
36
  function getCaretClientX(container, pmPos) {
38
- for (const spanEl of findBodyPmSpans(container)) {
37
+ const spans = findBodyPmSpans(container);
38
+ const collapsedTarget = findCollapsedLineEdgeCaretTarget(spans, pmPos);
39
+ if (collapsedTarget) return collapsedTarget.geometry.left;
40
+ for (const spanEl of spans) {
39
41
  const pmStart = Number(spanEl.dataset["pmStart"]);
40
42
  const pmEnd = Number(spanEl.dataset["pmEnd"]);
41
43
  if (spanEl.classList.contains("layout-run-tab")) {
@@ -58,21 +60,24 @@ function getCaretClientX(container, pmPos) {
58
60
  }
59
61
  return null;
60
62
  }
63
+ /**
64
+ * Whether one painted line carries `pmPos`. Span endpoints are inclusive, so a
65
+ * soft-wrap boundary answers true for both the line it ends and the line it
66
+ * starts.
67
+ */
68
+ const lineCarriesPosition = (lineEl, pmPos) => {
69
+ for (const span of Array.from(lineEl.querySelectorAll(PM_SPAN_SELECTOR))) {
70
+ const start = Number(span.dataset["pmStart"]);
71
+ const end = Number(span.dataset["pmEnd"]);
72
+ if (pmPos >= start && pmPos <= end) return true;
73
+ }
74
+ return false;
75
+ };
61
76
  /** @internal */
62
77
  function findLineElementAtPosition(container, pmPos) {
63
78
  const allLines = container.querySelectorAll(CONTENT_LINE_SELECTOR);
64
- for (const line of Array.from(allLines)) {
65
- const lineEl = line;
66
- const spans = lineEl.querySelectorAll("span[data-pm-start][data-pm-end]");
67
- for (const span of Array.from(spans)) {
68
- const s = span;
69
- const start = Number(s.dataset["pmStart"]);
70
- const end = Number(s.dataset["pmEnd"]);
71
- if (pmPos >= start && pmPos <= end) return lineEl;
72
- }
73
- }
74
- for (const line of Array.from(allLines)) {
75
- const lineEl = line;
79
+ for (const lineEl of Array.from(allLines)) if (lineCarriesPosition(lineEl, pmPos)) return lineEl;
80
+ for (const lineEl of Array.from(allLines)) {
76
81
  const paragraph = lineEl.closest(".layout-paragraph");
77
82
  if (!paragraph) continue;
78
83
  const pStart = Number(paragraph.dataset["pmStart"]);
@@ -145,6 +150,36 @@ function findPositionOnLineAtClientX(lineEl, clientX) {
145
150
  return clientX < closestSpan.getBoundingClientRect().left ? Number(closestSpan.dataset["pmStart"]) : Number(closestSpan.dataset["pmEnd"]);
146
151
  }
147
152
  /**
153
+ * The step the next vertical move continues from: the remembered one while the
154
+ * caret is still where that move left it, the caret's own painted geometry
155
+ * otherwise.
156
+ */
157
+ const resolveVisualLineStep = ({ state, container, allLines, pmPos }) => {
158
+ const remembered = state.step;
159
+ if (remembered?.pmPos === pmPos) {
160
+ const rememberedLine = allLines[remembered.lineIndex];
161
+ if (rememberedLine && lineCarriesPosition(rememberedLine, pmPos)) return remembered;
162
+ }
163
+ const currentLine = findLineElementAtPosition(container, pmPos);
164
+ if (!currentLine) return null;
165
+ const lineIndex = allLines.indexOf(currentLine);
166
+ if (lineIndex === -1) return null;
167
+ const stickyX = getCaretClientX(container, pmPos);
168
+ return stickyX === null ? null : {
169
+ stickyX,
170
+ lineIndex,
171
+ pmPos
172
+ };
173
+ };
174
+ const createVerticalSelection = ({ doc, anchor, head, extend }) => {
175
+ try {
176
+ return extend ? TextSelection.create(doc, anchor, head) : TextSelection.create(doc, head);
177
+ } catch {
178
+ const $head = doc.resolve(head);
179
+ return extend ? TextSelection.between(doc.resolve(anchor), $head) : Selection.near($head);
180
+ }
181
+ };
182
+ /**
148
183
  * Handle PM ArrowUp / ArrowDown with visual-line awareness + sticky
149
184
  * X. Returns true if the event was handled and PM should not run
150
185
  * its default behaviour. Mutates `state` so consecutive presses
@@ -153,59 +188,41 @@ function findPositionOnLineAtClientX(lineEl, clientX) {
153
188
  * @internal
154
189
  */
155
190
  function handleVisualLineKeyDown(state, view, event, container) {
156
- if (event.key !== "ArrowUp" && event.key !== "ArrowDown") {
157
- if ([
158
- "ArrowLeft",
159
- "ArrowRight",
160
- "Home",
161
- "End"
162
- ].includes(event.key) || event.key.length === 1 && !event.ctrlKey && !event.metaKey) {
163
- state.stickyX = null;
164
- state.lastVisualLineIndex = -1;
165
- }
166
- return false;
167
- }
168
- if (event.ctrlKey || event.metaKey) {
169
- state.stickyX = null;
170
- state.lastVisualLineIndex = -1;
171
- return false;
172
- }
191
+ if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return false;
192
+ if (event.ctrlKey || event.metaKey) return false;
173
193
  if (!container) return false;
174
194
  const allLines = Array.from(container.querySelectorAll(CONTENT_LINE_SELECTOR));
175
195
  if (allLines.length === 0) return false;
176
- const { from, anchor } = view.state.selection;
177
- if (state.stickyX === null) {
178
- const clientX = getCaretClientX(container, from);
179
- if (clientX === null) return false;
180
- state.stickyX = clientX;
181
- }
182
- let currentIndex;
183
- if (state.lastVisualLineIndex >= 0 && state.lastVisualLineIndex < allLines.length) currentIndex = state.lastVisualLineIndex;
184
- else {
185
- const currentLine = findLineElementAtPosition(container, from);
186
- if (!currentLine) return false;
187
- currentIndex = allLines.indexOf(currentLine);
188
- if (currentIndex === -1) return false;
189
- }
190
- const targetIndex = event.key === "ArrowUp" ? currentIndex - 1 : currentIndex + 1;
191
- if (targetIndex < 0 || targetIndex >= allLines.length) {
192
- state.lastVisualLineIndex = -1;
196
+ const { head, anchor } = view.state.selection;
197
+ const step = resolveVisualLineStep({
198
+ state,
199
+ container,
200
+ allLines,
201
+ pmPos: head
202
+ });
203
+ if (!step) return false;
204
+ const targetIndex = event.key === "ArrowUp" ? step.lineIndex - 1 : step.lineIndex + 1;
205
+ const targetLine = allLines[targetIndex];
206
+ if (!targetLine) {
207
+ state.step = null;
193
208
  return false;
194
209
  }
195
- const targetLine = allLines[targetIndex];
196
- const newPos = findPositionOnLineAtClientX(targetLine, state.stickyX);
210
+ const newPos = findPositionOnLineAtClientX(targetLine, step.stickyX);
197
211
  if (newPos === null) return false;
198
- state.lastVisualLineIndex = targetIndex;
199
212
  const { state: pmState, dispatch } = view;
200
213
  const clampedPos = Math.max(0, Math.min(newPos, pmState.doc.content.size));
201
- try {
202
- const sel = event.shiftKey ? TextSelection.create(pmState.doc, anchor, clampedPos) : TextSelection.create(pmState.doc, clampedPos);
203
- dispatch(pmState.tr.setSelection(sel));
204
- } catch {
205
- const $newPos = pmState.doc.resolve(clampedPos);
206
- const sel = event.shiftKey ? TextSelection.between(pmState.doc.resolve(anchor), $newPos) : TextSelection.near($newPos);
207
- dispatch(pmState.tr.setSelection(sel));
208
- }
214
+ const selection = createVerticalSelection({
215
+ doc: pmState.doc,
216
+ anchor,
217
+ head: clampedPos,
218
+ extend: event.shiftKey
219
+ });
220
+ dispatch(pmState.tr.setSelection(selection));
221
+ state.step = {
222
+ stickyX: step.stickyX,
223
+ lineIndex: targetIndex,
224
+ pmPos: selection.head
225
+ };
209
226
  scrollIntoViewIfNeeded(targetLine);
210
227
  return true;
211
228
  }
@@ -1,4 +1,5 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { BuiltInStyleIndex } from "../docx/builtInStyles.js";
2
3
  import { ResolvedParagraphStyle, TableCellParagraphSpacingOverlay } from "../prosemirror/styles/styleResolver.js";
3
4
  //#region src/style-engine/styleEngine.d.ts
4
5
  /** Engine construction options. */
@@ -34,7 +35,7 @@ type StyleEngine = {
34
35
  hasStyle: (styleId: string) => boolean;
35
36
  /** Return the document-wide defaults (`w:docDefaults`). */
36
37
  getDocDefaults: () => document_d_exports.DocDefaults | undefined;
37
- /** The style flagged `w:default="1"` for paragraphs, else "Normal". */
38
+ /** The paragraph default per ECMA-376 17.7.4.17, else the built-in Normal. */
38
39
  getDefaultParagraphStyle: () => document_d_exports.Style | undefined;
39
40
  /** The style flagged `w:default="1"` for character styles. */
40
41
  getDefaultCharacterStyle: () => document_d_exports.Style | undefined;
@@ -44,6 +45,8 @@ type StyleEngine = {
44
45
  getParagraphStyles: () => document_d_exports.Style[];
45
46
  /** All visible table styles, sorted for the table-style gallery. */
46
47
  getTableStyles: () => document_d_exports.Style[];
48
+ /** The document's styles indexed by the built-in they are — see {@link StyleResolver.builtInStyles}. */
49
+ builtInStyles: BuiltInStyleIndex;
47
50
  /**
48
51
  * Resolve the full paragraph cascade for a given styleId.
49
52
  * Returned object is cached and must not be mutated.
@@ -62,6 +62,9 @@ function createStyleEngine(styleDefinitions, options) {
62
62
  getDefaultTableStyle: () => resolver.getDefaultTableStyle(),
63
63
  getParagraphStyles: () => resolver.getParagraphStyles(),
64
64
  getTableStyles: () => resolver.getTableStyles(),
65
+ get builtInStyles() {
66
+ return resolver.builtInStyles;
67
+ },
65
68
  resolveParagraphStyle: (styleId) => memoize(paragraphCache, cacheKey(styleId), () => resolver.resolveParagraphStyle(styleId)),
66
69
  resolveParagraphStyleInTable: (styleId, tableParagraphOverlay) => tableParagraphOverlay === void 0 ? memoize(paragraphCache, cacheKey(styleId), () => resolver.resolveParagraphStyleInTable(styleId, void 0)) : memoizeInTable(styleId, tableParagraphOverlay),
67
70
  resolveRunStyle: (styleId) => memoize(runCache, cacheKey(styleId), () => resolver.resolveRunStyle(styleId)),
@@ -1,10 +1,14 @@
1
+ import { mintDefaultParagraphStyle, resolveDefaultParagraphStyle } from "../docx/defaultParagraphStyle.js";
2
+ import { getCachedNumberingMap } from "../docx/numberingParser.js";
3
+ import { isNumberingReference } from "../docx/numberingReference.js";
4
+ import { normalizeStyleNumberingReferences } from "../docx/numberingReferenceNormalization.js";
1
5
  import { parseDocx } from "../docx/parser.js";
2
6
  import "./types.js";
3
7
  import { panic } from "better-result";
4
8
  //#region src/style-sets/extract.ts
5
9
  const inspectDocumentStyles = (document) => {
6
10
  const styles = document.package.styles?.styles ?? [];
7
- const defaultParagraphStyleId = styles.find((style) => style.type === "paragraph" && style.default)?.styleId;
11
+ const defaultParagraphStyleId = resolveDefaultParagraphStyle(styles)?.styleId;
8
12
  return {
9
13
  ...defaultParagraphStyleId ? { defaultParagraphStyleId } : {},
10
14
  styles: styles.map(toCatalogEntry)
@@ -24,15 +28,21 @@ const inspectDocumentStylesFromDocx = async (input) => inspectDocumentStyles(awa
24
28
  * are retained. No source content or package relationship can enter the result.
25
29
  */
26
30
  const extractDocumentStyleSet = (document, options) => {
31
+ if (options.styleIds?.length === 0) return panic("Cannot extract an empty style set");
27
32
  const definitions = document.package.styles;
28
- if (!definitions || definitions.styles.length === 0) return panic("Cannot extract a style set from a document without styles");
29
- const stylesById = new Map(definitions.styles.map((style) => [style.styleId, style]));
33
+ const sourceStyles = definitions?.styles ?? [];
34
+ const stylesById = new Map(sourceStyles.map((style) => [style.styleId, style]));
30
35
  const selectedStyleIds = options.styleIds === void 0 ? new Set(stylesById.keys()) : collectStyleDependencyClosure(stylesById, options.styleIds);
31
- const styles = definitions.styles.filter((style) => selectedStyleIds.has(style.styleId));
32
- if (styles.length === 0) return panic("Cannot extract an empty style set");
33
- const defaultParagraphStyle = styles.find((style) => style.type === "paragraph" && style.default);
34
- const initialParagraphStyleId = options.initialParagraphStyleId ?? defaultParagraphStyle?.styleId ?? "Normal";
35
- if (!styles.find((style) => style.styleId === initialParagraphStyleId && style.type === "paragraph")) return panic(`Initial paragraph style "${initialParagraphStyleId}" is not present in the extracted set`);
36
+ const styles = structuredClone(sourceStyles.filter((style) => selectedStyleIds.has(style.styleId)));
37
+ normalizeStyleNumberingReferences({
38
+ styles,
39
+ numbering: document.package.numbering ? getCachedNumberingMap(document.package.numbering) : void 0
40
+ });
41
+ const initialParagraphStyleId = ensureInitialParagraphStyle({
42
+ styles,
43
+ requested: options.initialParagraphStyleId,
44
+ hasDocDefaults: definitions?.docDefaults !== void 0
45
+ });
36
46
  const numbering = extractReferencedNumbering(styles, document);
37
47
  const fontTable = sanitizeFontTable(document.package.fontTable);
38
48
  return structuredClone({
@@ -40,8 +50,8 @@ const extractDocumentStyleSet = (document, options) => {
40
50
  name: options.name,
41
51
  initialParagraphStyleId,
42
52
  styles: {
43
- ...definitions.docDefaults ? { docDefaults: definitions.docDefaults } : {},
44
- ...definitions.latentStyles ? { latentStyles: definitions.latentStyles } : {},
53
+ ...definitions?.docDefaults ? { docDefaults: definitions.docDefaults } : {},
54
+ ...definitions?.latentStyles ? { latentStyles: definitions.latentStyles } : {},
45
55
  styles
46
56
  },
47
57
  ...numbering ? { numbering } : {},
@@ -59,6 +69,20 @@ const extractDocumentStyleSetFromDocx = async (input, options) => {
59
69
  });
60
70
  return extractDocumentStyleSet(document, options);
61
71
  };
72
+ const ensureInitialParagraphStyle = ({ styles, requested, hasDocDefaults }) => {
73
+ if (requested !== void 0) {
74
+ if (!styles.find((style) => style.styleId === requested && style.type === "paragraph")) return panic(`Initial paragraph style "${requested}" is not present in the extracted set`);
75
+ return requested;
76
+ }
77
+ const resolved = resolveDefaultParagraphStyle(styles);
78
+ if (resolved) return resolved.styleId;
79
+ const minted = mintDefaultParagraphStyle({
80
+ takenStyleIds: new Set(styles.map((style) => style.styleId)),
81
+ hasDocDefaults
82
+ });
83
+ styles.push(minted);
84
+ return minted.styleId;
85
+ };
62
86
  const collectStyleDependencyClosure = (stylesById, requestedStyleIds) => {
63
87
  const selected = /* @__PURE__ */ new Set();
64
88
  const pending = [...requestedStyleIds];
@@ -82,7 +106,7 @@ const extractReferencedNumbering = (styles, document) => {
82
106
  const referencedNumIds = /* @__PURE__ */ new Set();
83
107
  for (const style of styles) {
84
108
  const numId = style.pPr?.numPr?.numId;
85
- if (numId !== void 0) referencedNumIds.add(numId);
109
+ if (isNumberingReference(numId)) referencedNumIds.add(numId);
86
110
  }
87
111
  if (referencedNumIds.size === 0) return;
88
112
  const nums = source.nums.filter((numbering) => referencedNumIds.has(numbering.numId));
@@ -1,3 +1,4 @@
1
+ import { BUILT_IN_STYLE_NAME, builtInHeadingStyleName, builtInTableOfContentsStyleName } from "../docx/builtInStyles.js";
1
2
  import "./types.js";
2
3
  //#region src/style-sets/stellaStyle.ts
3
4
  const CLAUSE_NUMBERING_ID = 1;
@@ -43,7 +44,7 @@ const createStellaStyleSet = () => ({
43
44
  {
44
45
  styleId: "Normal",
45
46
  type: "paragraph",
46
- name: "Normal",
47
+ name: BUILT_IN_STYLE_NAME.normal,
47
48
  default: true,
48
49
  qFormat: true,
49
50
  uiPriority: 0,
@@ -64,7 +65,7 @@ const createStellaStyleSet = () => ({
64
65
  {
65
66
  styleId: "DefaultParagraphFont",
66
67
  type: "character",
67
- name: "Default Paragraph Font",
68
+ name: BUILT_IN_STYLE_NAME.defaultParagraphFont,
68
69
  default: true,
69
70
  semiHidden: true,
70
71
  unhideWhenUsed: true
@@ -72,7 +73,7 @@ const createStellaStyleSet = () => ({
72
73
  {
73
74
  styleId: "BodyText",
74
75
  type: "paragraph",
75
- name: "Body Text",
76
+ name: BUILT_IN_STYLE_NAME.bodyText,
76
77
  basedOn: "Normal",
77
78
  qFormat: true,
78
79
  uiPriority: 1
@@ -80,7 +81,7 @@ const createStellaStyleSet = () => ({
80
81
  {
81
82
  styleId: "Title",
82
83
  type: "paragraph",
83
- name: "Title",
84
+ name: BUILT_IN_STYLE_NAME.title,
84
85
  basedOn: "BodyText",
85
86
  next: "BodyText",
86
87
  qFormat: true,
@@ -109,7 +110,7 @@ const createStellaStyleSet = () => ({
109
110
  {
110
111
  styleId: "Subtitle",
111
112
  type: "paragraph",
112
- name: "Subtitle",
113
+ name: BUILT_IN_STYLE_NAME.subtitle,
113
114
  basedOn: "Title",
114
115
  next: "BodyText",
115
116
  qFormat: true,
@@ -131,7 +132,10 @@ const createStellaStyleSet = () => ({
131
132
  next: "Recital",
132
133
  qFormat: true,
133
134
  uiPriority: 5,
134
- pPr: { keepNext: true },
135
+ pPr: {
136
+ keepNext: true,
137
+ outlineLevel: 0
138
+ },
135
139
  rPr: { bold: true }
136
140
  },
137
141
  {
@@ -179,7 +183,7 @@ const createStellaStyleSet = () => ({
179
183
  {
180
184
  styleId: "ListParagraph",
181
185
  type: "paragraph",
182
- name: "List Paragraph",
186
+ name: BUILT_IN_STYLE_NAME.listParagraph,
183
187
  basedOn: "BodyText",
184
188
  qFormat: true,
185
189
  uiPriority: 31,
@@ -208,13 +212,14 @@ const createStellaStyleSet = () => ({
208
212
  pPr: {
209
213
  pageBreakBefore: true,
210
214
  keepNext: true,
211
- spaceAfter: 240
215
+ spaceAfter: 240,
216
+ outlineLevel: 0
212
217
  }
213
218
  },
214
219
  {
215
220
  styleId: "FootnoteText",
216
221
  type: "paragraph",
217
- name: "Footnote Text",
222
+ name: BUILT_IN_STYLE_NAME.footnoteText,
218
223
  basedOn: "Normal",
219
224
  link: "FootnoteTextChar",
220
225
  semiHidden: true,
@@ -229,7 +234,7 @@ const createStellaStyleSet = () => ({
229
234
  {
230
235
  styleId: "FootnoteTextChar",
231
236
  type: "character",
232
- name: "Footnote Text Char",
237
+ name: BUILT_IN_STYLE_NAME.footnoteTextChar,
233
238
  basedOn: "DefaultParagraphFont",
234
239
  link: "FootnoteText",
235
240
  semiHidden: true,
@@ -243,7 +248,7 @@ const createStellaStyleSet = () => ({
243
248
  {
244
249
  styleId: "FootnoteReference",
245
250
  type: "character",
246
- name: "Footnote Reference",
251
+ name: BUILT_IN_STYLE_NAME.footnoteReference,
247
252
  basedOn: "DefaultParagraphFont",
248
253
  semiHidden: true,
249
254
  unhideWhenUsed: true,
@@ -253,7 +258,7 @@ const createStellaStyleSet = () => ({
253
258
  {
254
259
  styleId: "EndnoteText",
255
260
  type: "paragraph",
256
- name: "Endnote Text",
261
+ name: BUILT_IN_STYLE_NAME.endnoteText,
257
262
  basedOn: "Normal",
258
263
  link: "EndnoteTextChar",
259
264
  semiHidden: true,
@@ -268,7 +273,7 @@ const createStellaStyleSet = () => ({
268
273
  {
269
274
  styleId: "EndnoteTextChar",
270
275
  type: "character",
271
- name: "Endnote Text Char",
276
+ name: BUILT_IN_STYLE_NAME.endnoteTextChar,
272
277
  basedOn: "DefaultParagraphFont",
273
278
  link: "EndnoteText",
274
279
  semiHidden: true,
@@ -282,7 +287,7 @@ const createStellaStyleSet = () => ({
282
287
  {
283
288
  styleId: "EndnoteReference",
284
289
  type: "character",
285
- name: "Endnote Reference",
290
+ name: BUILT_IN_STYLE_NAME.endnoteReference,
286
291
  basedOn: "DefaultParagraphFont",
287
292
  semiHidden: true,
288
293
  unhideWhenUsed: true,
@@ -292,7 +297,7 @@ const createStellaStyleSet = () => ({
292
297
  {
293
298
  styleId: "Footer",
294
299
  type: "paragraph",
295
- name: "Footer",
300
+ name: BUILT_IN_STYLE_NAME.footer,
296
301
  basedOn: "Normal",
297
302
  pPr: {
298
303
  alignment: "right",
@@ -307,7 +312,7 @@ const createStellaStyleSet = () => ({
307
312
  {
308
313
  styleId: "Hyperlink",
309
314
  type: "character",
310
- name: "Hyperlink",
315
+ name: BUILT_IN_STYLE_NAME.hyperlink,
311
316
  basedOn: "DefaultParagraphFont",
312
317
  unhideWhenUsed: true,
313
318
  uiPriority: 99,
@@ -319,7 +324,7 @@ const createStellaStyleSet = () => ({
319
324
  {
320
325
  styleId: "TableNormal",
321
326
  type: "table",
322
- name: "Normal Table",
327
+ name: BUILT_IN_STYLE_NAME.normalTable,
323
328
  default: true,
324
329
  semiHidden: true,
325
330
  unhideWhenUsed: true,
@@ -328,7 +333,7 @@ const createStellaStyleSet = () => ({
328
333
  {
329
334
  styleId: "TableGrid",
330
335
  type: "table",
331
- name: "Table Grid",
336
+ name: BUILT_IN_STYLE_NAME.tableGrid,
332
337
  basedOn: "TableNormal",
333
338
  qFormat: true,
334
339
  uiPriority: 59,
@@ -399,37 +404,37 @@ const createHeadingStyles = () => {
399
404
  return [
400
405
  {
401
406
  styleId: "Heading1",
402
- name: "heading 1",
407
+ name: builtInHeadingStyleName(0),
403
408
  fontSize: 28,
404
409
  spaceBefore: 360
405
410
  },
406
411
  {
407
412
  styleId: "Heading2",
408
- name: "heading 2",
413
+ name: builtInHeadingStyleName(1),
409
414
  fontSize: 24,
410
415
  spaceBefore: 240
411
416
  },
412
417
  {
413
418
  styleId: "Heading3",
414
- name: "heading 3",
419
+ name: builtInHeadingStyleName(2),
415
420
  fontSize: 22,
416
421
  spaceBefore: 240
417
422
  },
418
423
  {
419
424
  styleId: "Heading4",
420
- name: "heading 4",
425
+ name: builtInHeadingStyleName(3),
421
426
  fontSize: 20,
422
427
  spaceBefore: 120
423
428
  },
424
429
  {
425
430
  styleId: "Heading5",
426
- name: "heading 5",
431
+ name: builtInHeadingStyleName(4),
427
432
  fontSize: 20,
428
433
  spaceBefore: 120
429
434
  },
430
435
  {
431
436
  styleId: "Heading6",
432
- name: "heading 6",
437
+ name: builtInHeadingStyleName(5),
433
438
  fontSize: 20,
434
439
  spaceBefore: 120
435
440
  }
@@ -457,32 +462,33 @@ const createHeadingStyles = () => {
457
462
  };
458
463
  /** `TOCHeading` plus `TOC1`..`TOC3`, the styles a `TOC \o "1-3"` field fills. */
459
464
  const createTableOfContentsStyles = () => {
460
- return [{
461
- styleId: "TOCHeading",
462
- type: "paragraph",
463
- name: "TOC Heading",
464
- basedOn: "Heading1",
465
- next: "BodyText",
466
- unhideWhenUsed: true,
467
- uiPriority: 39,
468
- pPr: { outlineLevel: 9 }
469
- }, ...[
465
+ const levels = [
470
466
  {
471
467
  styleId: "TOC1",
472
- name: "toc 1",
468
+ name: builtInTableOfContentsStyleName(1),
473
469
  indent: 0
474
470
  },
475
471
  {
476
472
  styleId: "TOC2",
477
- name: "toc 2",
473
+ name: builtInTableOfContentsStyleName(2),
478
474
  indent: 220
479
475
  },
480
476
  {
481
477
  styleId: "TOC3",
482
- name: "toc 3",
478
+ name: builtInTableOfContentsStyleName(3),
483
479
  indent: 440
484
480
  }
485
- ].map(({ styleId, name, indent }) => ({
481
+ ];
482
+ return [{
483
+ styleId: "TOCHeading",
484
+ type: "paragraph",
485
+ name: BUILT_IN_STYLE_NAME.tocHeading,
486
+ basedOn: "Heading1",
487
+ next: "BodyText",
488
+ unhideWhenUsed: true,
489
+ uiPriority: 39,
490
+ pPr: { outlineLevel: 9 }
491
+ }, ...levels.map(({ styleId, name, indent }) => ({
486
492
  styleId,
487
493
  type: "paragraph",
488
494
  name,
@@ -548,7 +554,8 @@ const createClauseStyles = () => {
548
554
  ilvl: level
549
555
  },
550
556
  keepNext: level < 2,
551
- spaceBefore: clauseSpaceBefore(level)
557
+ spaceBefore: clauseSpaceBefore(level),
558
+ outlineLevel: level === 0 ? 0 : 9
552
559
  }
553
560
  };
554
561
  if (bold) return Object.assign(style, { rPr: { bold: true } });
@@ -0,0 +1,19 @@
1
+ import { DocumentStyleSet } from "./types.js";
2
+ import { ParseContext } from "../docx/parseContext.js";
3
+ //#region src/style-sets/styleSetNormalization.d.ts
4
+ /** The codes this normalisation is reported under, owned here, not at the caller. */
5
+ declare const DUPLICATE_STYLE_ID_WARNING: "style-set-duplicate-style-id";
6
+ declare const INITIAL_PARAGRAPH_STYLE_WARNING: "style-set-initial-style-missing";
7
+ declare const UNNUMBERED_STYLE_SET_STYLE_WARNING: "unnumbered-style";
8
+ /** The part a style-set normalisation names: the set itself, not a package. */
9
+ declare const STYLE_SET_PART = "style-set";
10
+ /**
11
+ * A normalised copy of the set, leaving the caller's value untouched.
12
+ *
13
+ * The version is the one thing still refused rather than repaired: a value
14
+ * folio has no reader for is programmer misuse, not a document defect, and
15
+ * guessing at its meaning would be worse than saying so.
16
+ */
17
+ declare const normalizeDocumentStyleSet: (styleSet: DocumentStyleSet, context?: ParseContext) => DocumentStyleSet;
18
+ //#endregion
19
+ export { DUPLICATE_STYLE_ID_WARNING, INITIAL_PARAGRAPH_STYLE_WARNING, STYLE_SET_PART, UNNUMBERED_STYLE_SET_STYLE_WARNING, normalizeDocumentStyleSet };