@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
@@ -0,0 +1,99 @@
1
+ import { mintDefaultParagraphStyle, resolveDefaultParagraphStyle } from "../docx/defaultParagraphStyle.js";
2
+ import { getCachedNumberingMap } from "../docx/numberingParser.js";
3
+ import { normalizeStyleNumberingReferences } from "../docx/numberingReferenceNormalization.js";
4
+ import "./types.js";
5
+ import { panic } from "better-result";
6
+ import { PARSE_WARNING_CODES } from "@stll/docx-core/model";
7
+ //#region src/style-sets/styleSetNormalization.ts
8
+ /**
9
+ * The boundary an external `DocumentStyleSet` crosses to become a document.
10
+ *
11
+ * A style set is portable by design: hosts persist one as JSON, ship it
12
+ * between workspaces, and hand it back months later. That makes it untrusted
13
+ * input on the same footing as a `.docx`, and it can carry the same defects a
14
+ * package can: a style numbering the set never defines, two styles under one
15
+ * id, an initial paragraph style that is not in the set. A set written before
16
+ * folio learned to normalise those still carries them.
17
+ *
18
+ * So it is normalised here, once, on the way in, through the same owners the
19
+ * parser and the extractor use, rather than at a third call site with its own
20
+ * rules. `createEmptyDocument` is the only door, so this is the only place
21
+ * that has to run.
22
+ *
23
+ * `DOCUMENT_STYLE_SET_VERSION` does not move: the shape is unchanged and a v1
24
+ * value is still a v1 value. What changed is that folio repairs one instead of
25
+ * trusting it.
26
+ */
27
+ /** The codes this normalisation is reported under, owned here, not at the caller. */
28
+ const DUPLICATE_STYLE_ID_WARNING = PARSE_WARNING_CODES.styleSetDuplicateStyleId;
29
+ const INITIAL_PARAGRAPH_STYLE_WARNING = PARSE_WARNING_CODES.styleSetInitialStyleMissing;
30
+ const UNNUMBERED_STYLE_SET_STYLE_WARNING = PARSE_WARNING_CODES.unnumberedStyle;
31
+ /** The part a style-set normalisation names: the set itself, not a package. */
32
+ const STYLE_SET_PART = "style-set";
33
+ /**
34
+ * A normalised copy of the set, leaving the caller's value untouched.
35
+ *
36
+ * The version is the one thing still refused rather than repaired: a value
37
+ * folio has no reader for is programmer misuse, not a document defect, and
38
+ * guessing at its meaning would be worse than saying so.
39
+ */
40
+ const normalizeDocumentStyleSet = (styleSet, context) => {
41
+ if (styleSet.version !== 1) return panic(`Unsupported document style set version: ${String(styleSet.version)}`);
42
+ if (styleSet.name.trim().length === 0) return panic("Document style set name cannot be empty");
43
+ const scoped = context?.scoped({ part: STYLE_SET_PART });
44
+ const normalized = structuredClone(styleSet);
45
+ const styles = dropDuplicateStyleIds(normalized.styles.styles, scoped);
46
+ normalized.styles.styles = styles;
47
+ const unnumbered = normalizeStyleNumberingReferences({
48
+ styles,
49
+ numbering: normalized.numbering ? getCachedNumberingMap(normalized.numbering) : void 0
50
+ });
51
+ for (const styleId of unnumbered.unnumberedStyleIds) scoped?.warn({
52
+ code: UNNUMBERED_STYLE_SET_STYLE_WARNING,
53
+ value: styleId,
54
+ at: `style "${styleId}"`
55
+ });
56
+ normalized.initialParagraphStyleId = resolveInitialParagraphStyleId({
57
+ styles,
58
+ requested: styleSet.initialParagraphStyleId,
59
+ hasDocDefaults: normalized.styles.docDefaults !== void 0,
60
+ context: scoped
61
+ });
62
+ return normalized;
63
+ };
64
+ const dropDuplicateStyleIds = (styles, context) => {
65
+ const seen = /* @__PURE__ */ new Set();
66
+ const kept = [];
67
+ for (const style of styles) {
68
+ if (seen.has(style.styleId)) {
69
+ context?.warn({
70
+ code: DUPLICATE_STYLE_ID_WARNING,
71
+ value: style.styleId,
72
+ at: `style "${style.styleId}"`
73
+ });
74
+ continue;
75
+ }
76
+ seen.add(style.styleId);
77
+ kept.push(style);
78
+ }
79
+ return kept;
80
+ };
81
+ const resolveInitialParagraphStyleId = ({ styles, requested, hasDocDefaults, context }) => {
82
+ if (styles.find((style) => style.styleId === requested && style.type === "paragraph")) return requested;
83
+ const replacement = resolveDefaultParagraphStyle(styles) ?? (() => {
84
+ const minted = mintDefaultParagraphStyle({
85
+ takenStyleIds: new Set(styles.map((style) => style.styleId)),
86
+ hasDocDefaults
87
+ });
88
+ styles.push(minted);
89
+ return minted;
90
+ })();
91
+ context?.warn({
92
+ code: INITIAL_PARAGRAPH_STYLE_WARNING,
93
+ value: requested,
94
+ at: `style "${replacement.styleId}"`
95
+ });
96
+ return replacement.styleId;
97
+ };
98
+ //#endregion
99
+ export { DUPLICATE_STYLE_ID_WARNING, INITIAL_PARAGRAPH_STYLE_WARNING, STYLE_SET_PART, UNNUMBERED_STYLE_SET_STYLE_WARNING, normalizeDocumentStyleSet };
@@ -1,2 +1,2 @@
1
- import { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign } from "@stll/docx-core/model";
2
- export type { BlockContent, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign };
1
+ import { BlockContent, BlockRangeMarkerCapture, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DisplacedByCustomXml, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign } from "@stll/docx-core/model";
2
+ export type { BlockContent, BlockRangeMarkerCapture, BlockSdt, BookmarkEnd, BookmarkStart, BreakContent, Column, Comment, CommentRangeEnd, CommentRangeStart, CommentReference, ComplexField, Deletion, DisplacedByCustomXml, DocumentBody, DrawingContent, DrawingRawXmlMode, Endnote, EndnotePosition, EndnoteProperties, Field, FieldCharContent, FieldType, FooterReference, Footnote, FootnotePosition, FootnoteProperties, HeaderFooter, HeaderFooterType, HeaderReference, Hyperlink, Image, ImageCrop, ImagePadding, ImagePosition, ImageSize, ImageTransform, ImageWrap, InlineSdt, Insertion, InstrTextContent, LineNumberRestart, MathEquation, MoveFrom, MoveFromRangeEnd, MoveFromRangeStart, MoveTo, MoveToRangeEnd, MoveToRangeStart, NoBreakHyphenContent, NoteNumberRestart, NoteReferenceContent, PageOrientation, Paragraph, ParagraphContent, ParagraphPropertyChange, PositionalTab, PropertyChangeInfo, Run, RunContent, RunPropertyChange, SdtProperties, SdtType, Section, SectionProperties, SectionStart, Shape, ShapeContent, ShapeFill, ShapeGeometryAdjustment, ShapeOutline, ShapeTextBody, ShapeType, SimpleField, SoftHyphenContent, SymbolContent, TabContent, Table, TableCell, TableCellPropertyChange, TableRow, TableRowPropertyChange, TableStructuralChangeInfo, TextBox, TextContent, TrackedChangeInfo, TrackedRunChange, TrackedRunContent, VerticalAlign };
@@ -1,3 +1,8 @@
1
+ import { BUILT_IN_STYLE_NAME, builtInHeadingStyleName } from "../docx/builtInStyles.js";
2
+ import "../docx/defaultParagraphStyle.js";
3
+ import { createParseWarningCollector } from "../docx/parseContext.js";
4
+ import { formatParseWarnings } from "../docx/parseWarningMessage.js";
5
+ import { STYLE_SET_PART, normalizeDocumentStyleSet } from "../style-sets/styleSetNormalization.js";
1
6
  import "../style-sets/types.js";
2
7
  import { panic } from "better-result";
3
8
  import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
@@ -12,13 +17,17 @@ import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
12
17
  *
13
18
  * Font sizes are in half-points (e.g., 22 = 11pt, 40 = 20pt)
14
19
  * Colors are RGB hex without # prefix
20
+ *
21
+ * Each style carries the built-in `w:name` it stands for, which is how every
22
+ * consumer recognises it (`docx/builtInStyles.ts`), and the headings carry
23
+ * `w:outlineLvl` so a Word TOC field and the navigation pane list them.
15
24
  */
16
25
  function getDefaultStyles() {
17
26
  return [
18
27
  {
19
28
  styleId: "Normal",
20
29
  type: "paragraph",
21
- name: "Normal",
30
+ name: BUILT_IN_STYLE_NAME.normal,
22
31
  default: true,
23
32
  qFormat: true,
24
33
  uiPriority: 0,
@@ -34,7 +43,7 @@ function getDefaultStyles() {
34
43
  {
35
44
  styleId: "Title",
36
45
  type: "paragraph",
37
- name: "Title",
46
+ name: BUILT_IN_STYLE_NAME.title,
38
47
  basedOn: "Normal",
39
48
  next: "Normal",
40
49
  qFormat: true,
@@ -52,7 +61,7 @@ function getDefaultStyles() {
52
61
  {
53
62
  styleId: "Subtitle",
54
63
  type: "paragraph",
55
- name: "Subtitle",
64
+ name: BUILT_IN_STYLE_NAME.subtitle,
56
65
  basedOn: "Normal",
57
66
  next: "Normal",
58
67
  qFormat: true,
@@ -70,7 +79,7 @@ function getDefaultStyles() {
70
79
  {
71
80
  styleId: "Heading1",
72
81
  type: "paragraph",
73
- name: "Heading 1",
82
+ name: builtInHeadingStyleName(0),
74
83
  basedOn: "Normal",
75
84
  next: "Normal",
76
85
  qFormat: true,
@@ -86,13 +95,14 @@ function getDefaultStyles() {
86
95
  pPr: {
87
96
  spaceBefore: 400,
88
97
  spaceAfter: 120,
89
- lineSpacing: 240
98
+ lineSpacing: 240,
99
+ outlineLevel: 0
90
100
  }
91
101
  },
92
102
  {
93
103
  styleId: "Heading2",
94
104
  type: "paragraph",
95
- name: "Heading 2",
105
+ name: builtInHeadingStyleName(1),
96
106
  basedOn: "Normal",
97
107
  next: "Normal",
98
108
  qFormat: true,
@@ -108,13 +118,14 @@ function getDefaultStyles() {
108
118
  pPr: {
109
119
  spaceBefore: 360,
110
120
  spaceAfter: 80,
111
- lineSpacing: 240
121
+ lineSpacing: 240,
122
+ outlineLevel: 1
112
123
  }
113
124
  },
114
125
  {
115
126
  styleId: "Heading3",
116
127
  type: "paragraph",
117
- name: "Heading 3",
128
+ name: builtInHeadingStyleName(2),
118
129
  basedOn: "Normal",
119
130
  next: "Normal",
120
131
  qFormat: true,
@@ -130,13 +141,14 @@ function getDefaultStyles() {
130
141
  pPr: {
131
142
  spaceBefore: 320,
132
143
  spaceAfter: 80,
133
- lineSpacing: 240
144
+ lineSpacing: 240,
145
+ outlineLevel: 2
134
146
  }
135
147
  },
136
148
  {
137
149
  styleId: "Heading4",
138
150
  type: "paragraph",
139
- name: "Heading 4",
151
+ name: builtInHeadingStyleName(3),
140
152
  basedOn: "Normal",
141
153
  next: "Normal",
142
154
  qFormat: true,
@@ -152,6 +164,121 @@ function getDefaultStyles() {
152
164
  pPr: {
153
165
  spaceBefore: 280,
154
166
  spaceAfter: 80,
167
+ lineSpacing: 240,
168
+ outlineLevel: 3
169
+ }
170
+ },
171
+ {
172
+ styleId: "Heading5",
173
+ type: "paragraph",
174
+ name: builtInHeadingStyleName(4),
175
+ basedOn: "Normal",
176
+ next: "Normal",
177
+ qFormat: true,
178
+ uiPriority: 9,
179
+ rPr: {
180
+ fontSize: 22,
181
+ bold: true,
182
+ fontFamily: {
183
+ ascii: "Arial",
184
+ hAnsi: "Arial"
185
+ }
186
+ },
187
+ pPr: {
188
+ spaceBefore: 240,
189
+ spaceAfter: 80,
190
+ lineSpacing: 240,
191
+ outlineLevel: 4
192
+ }
193
+ },
194
+ {
195
+ styleId: "Heading6",
196
+ type: "paragraph",
197
+ name: builtInHeadingStyleName(5),
198
+ basedOn: "Normal",
199
+ next: "Normal",
200
+ qFormat: true,
201
+ uiPriority: 9,
202
+ rPr: {
203
+ fontSize: 22,
204
+ bold: true,
205
+ color: { rgb: "595959" },
206
+ fontFamily: {
207
+ ascii: "Arial",
208
+ hAnsi: "Arial"
209
+ }
210
+ },
211
+ pPr: {
212
+ spaceBefore: 240,
213
+ spaceAfter: 80,
214
+ lineSpacing: 240,
215
+ outlineLevel: 5
216
+ }
217
+ },
218
+ {
219
+ styleId: "TableNormal",
220
+ type: "table",
221
+ name: BUILT_IN_STYLE_NAME.normalTable,
222
+ uiPriority: 99,
223
+ semiHidden: true,
224
+ unhideWhenUsed: true
225
+ },
226
+ {
227
+ styleId: "TableGrid",
228
+ type: "table",
229
+ name: BUILT_IN_STYLE_NAME.tableGrid,
230
+ basedOn: "TableNormal",
231
+ uiPriority: 39,
232
+ tblPr: { borders: {
233
+ top: {
234
+ style: "single",
235
+ size: 4,
236
+ space: 0
237
+ },
238
+ bottom: {
239
+ style: "single",
240
+ size: 4,
241
+ space: 0
242
+ },
243
+ left: {
244
+ style: "single",
245
+ size: 4,
246
+ space: 0
247
+ },
248
+ right: {
249
+ style: "single",
250
+ size: 4,
251
+ space: 0
252
+ },
253
+ insideH: {
254
+ style: "single",
255
+ size: 4,
256
+ space: 0
257
+ },
258
+ insideV: {
259
+ style: "single",
260
+ size: 4,
261
+ space: 0
262
+ }
263
+ } }
264
+ },
265
+ {
266
+ styleId: "Quote",
267
+ type: "paragraph",
268
+ name: BUILT_IN_STYLE_NAME.quote,
269
+ basedOn: "Normal",
270
+ next: "Normal",
271
+ qFormat: true,
272
+ uiPriority: 29,
273
+ rPr: {
274
+ italic: true,
275
+ color: { rgb: "404040" }
276
+ },
277
+ pPr: {
278
+ indentLeft: 720,
279
+ indentRight: 720,
280
+ spaceBefore: 160,
281
+ spaceAfter: 160,
155
282
  lineSpacing: 240
156
283
  }
157
284
  }
@@ -203,9 +330,10 @@ function getDefaultSectionProperties() {
203
330
  * ```
204
331
  */
205
332
  function createEmptyDocument(options = {}) {
206
- const styleSet = options.preset?.styleSet ?? options.styleSet;
207
- validateDocumentStyleSet(styleSet);
333
+ const suppliedStyleSet = options.preset?.styleSet ?? options.styleSet;
208
334
  if (options.preset?.version !== void 0 && options.preset.version !== 1) return panic(`Unsupported document preset version: ${options.preset.version}`);
335
+ const { context: styleSetContext, warnings: styleSetWarnings } = createParseWarningCollector(STYLE_SET_PART);
336
+ const styleSet = suppliedStyleSet === void 0 ? void 0 : normalizeDocumentStyleSet(suppliedStyleSet, styleSetContext);
209
337
  const sectionProps = structuredClone(options.preset?.sectionProperties ?? getDefaultSectionProperties());
210
338
  if (options.pageWidth !== void 0) sectionProps.pageWidth = Math.round(options.pageWidth);
211
339
  if (options.pageHeight !== void 0) sectionProps.pageHeight = Math.round(options.pageHeight);
@@ -253,18 +381,15 @@ function createEmptyDocument(options = {}) {
253
381
  if (styleSet?.theme) docxPackage.theme = structuredClone(styleSet.theme);
254
382
  if (styleSet?.fontTable) docxPackage.fontTable = structuredClone(styleSet.fontTable);
255
383
  if (styleSet?.settings) docxPackage.settings = structuredClone(styleSet.settings);
256
- return {
384
+ const parseWarnings = styleSetWarnings();
385
+ const document = {
257
386
  package: docxPackage,
258
387
  templateVariables: [],
259
- warnings: []
388
+ warnings: formatParseWarnings(parseWarnings)
260
389
  };
390
+ if (parseWarnings.length > 0) document.parseWarnings = parseWarnings;
391
+ return document;
261
392
  }
262
- const validateDocumentStyleSet = (styleSet) => {
263
- if (!styleSet) return;
264
- if (styleSet.version !== 1) return panic(`Unsupported document style set version: ${styleSet.version}`);
265
- if (styleSet.name.trim().length === 0) return panic("Document style set name cannot be empty");
266
- if (styleSet.styles.styles.find((style) => style.styleId === styleSet.initialParagraphStyleId)?.type !== "paragraph") return panic(`Initial paragraph style "${styleSet.initialParagraphStyleId}" is missing from style set "${styleSet.name}"`);
267
- };
268
393
  /**
269
394
  * Create a document with a single paragraph containing the given text
270
395
  *
@@ -1,3 +1,4 @@
1
+ import { BuiltInStyleIndex } from "../docx/builtInStyles.js";
1
2
  import { Node } from "prosemirror-model";
2
3
  //#region src/utils/headingCollector.d.ts
3
4
  /**
@@ -14,12 +15,14 @@ type HeadingInfo = {
14
15
  pageNumber?: number | null;
15
16
  };
16
17
  /**
17
- * Collect all headings from a ProseMirror document.
18
+ * Collect all headings from a ProseMirror document, in document order.
18
19
  *
19
- * Detection logic:
20
- * 1. Check `outlineLevel` attr (set by OOXML parsing or style resolution)
21
- * 2. Fallback to `styleId` matching /^[Hh]eading(\d)$/
20
+ * Classification is {@link resolveHeadingLevel}'s: the paragraph's effective
21
+ * outline level, else the style's built-in `w:name`. Pass the open document's
22
+ * index (`styleResolver.builtInStyles`) so a localized style id such as
23
+ * `Nadpis1` or `berschrift1` resolves through its name rather than falling out
24
+ * of the outline.
22
25
  */
23
- declare function collectHeadings(doc: Node): HeadingInfo[];
26
+ declare function collectHeadings(doc: Node, styles: BuiltInStyleIndex): HeadingInfo[];
24
27
  //#endregion
25
28
  export { HeadingInfo, collectHeadings };
@@ -1,34 +1,32 @@
1
+ import { resolveHeadingLevel } from "../docx/builtInStyles.js";
1
2
  //#region src/utils/headingCollector.ts
2
3
  /**
3
- * Collect all headings from a ProseMirror document.
4
+ * Collect all headings from a ProseMirror document, in document order.
4
5
  *
5
- * Detection logic:
6
- * 1. Check `outlineLevel` attr (set by OOXML parsing or style resolution)
7
- * 2. Fallback to `styleId` matching /^[Hh]eading(\d)$/
6
+ * Classification is {@link resolveHeadingLevel}'s: the paragraph's effective
7
+ * outline level, else the style's built-in `w:name`. Pass the open document's
8
+ * index (`styleResolver.builtInStyles`) so a localized style id such as
9
+ * `Nadpis1` or `berschrift1` resolves through its name rather than falling out
10
+ * of the outline.
8
11
  */
9
- function collectHeadings(doc) {
12
+ function collectHeadings(doc, styles) {
10
13
  const headings = [];
11
14
  doc.descendants((node, pos) => {
12
- if (node.type.name === "paragraph") {
13
- const level = node.attrs["outlineLevel"];
14
- const styleId = node.attrs["styleId"];
15
- let effectiveLevel = level;
16
- if (effectiveLevel === null && styleId) {
17
- const match = /^[Hh]eading(?<level>\d)$/u.exec(styleId);
18
- if (match) effectiveLevel = Number.parseInt(match.groups["level"], 10) - 1;
19
- }
20
- if (effectiveLevel !== null && effectiveLevel >= 0 && effectiveLevel <= 8) {
21
- let text = "";
22
- node.forEach((child) => {
23
- if (child.isText) text += child.text || "";
24
- });
25
- if (text.trim()) headings.push({
26
- text: text.trim(),
27
- level: effectiveLevel,
28
- pmPos: pos
29
- });
30
- }
31
- }
15
+ if (node.type.name !== "paragraph") return;
16
+ const level = resolveHeadingLevel({
17
+ outlineLevel: node.attrs["outlineLevel"],
18
+ styleId: node.attrs["styleId"]
19
+ }, styles);
20
+ if (level === void 0) return;
21
+ let text = "";
22
+ node.forEach((child) => {
23
+ if (child.isText) text += child.text || "";
24
+ });
25
+ if (text.trim()) headings.push({
26
+ text: text.trim(),
27
+ level,
28
+ pmPos: pos
29
+ });
32
30
  });
33
31
  return headings;
34
32
  }
@@ -1,6 +1,13 @@
1
+ import { normalizeStyleName } from "../docx/builtInStyles.js";
1
2
  //#region src/utils/tableOfContentsStyle.ts
2
3
  const TABLE_OF_CONTENTS_STYLE_ID = /^TOC(?<level>\d*)$/iu;
3
- const TABLE_OF_CONTENTS_STYLE_NAME = /^toc\s+(?<level>\d+)$/iu;
4
+ /**
5
+ * Against an already-normalised name, so the same tolerance applies here as in
6
+ * `builtInStyles.ts`: the corpus carries `toc 1`, `TOC 1` and even `TOC 1`
7
+ * with a double space, and a producer that drops the space entirely would
8
+ * otherwise fall out.
9
+ */
10
+ const TABLE_OF_CONTENTS_STYLE_NAME = /^toc(?<level>\d+)$/u;
4
11
  const parsedLevel = (match) => {
5
12
  if (!match) return;
6
13
  const rawLevel = match.groups?.["level"];
@@ -9,6 +16,6 @@ const parsedLevel = (match) => {
9
16
  return Number.isSafeInteger(level) && level > 0 ? level : void 0;
10
17
  };
11
18
  /** Resolve a built-in TOC entry style without relying on its localized style id. */
12
- const tableOfContentsStyleLevel = ({ styleId, styleName }) => parsedLevel(TABLE_OF_CONTENTS_STYLE_ID.exec(styleId ?? "")) ?? parsedLevel(TABLE_OF_CONTENTS_STYLE_NAME.exec(styleName ?? ""));
19
+ const tableOfContentsStyleLevel = ({ styleId, styleName }) => parsedLevel(TABLE_OF_CONTENTS_STYLE_ID.exec(styleId ?? "")) ?? parsedLevel(TABLE_OF_CONTENTS_STYLE_NAME.exec(normalizeStyleName(styleName ?? "")));
13
20
  //#endregion
14
21
  export { tableOfContentsStyleLevel };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.42.0",
3
+ "version": "0.44.0",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",
@@ -121,7 +121,7 @@
121
121
  "perf": "bun scripts/profile-editor.ts"
122
122
  },
123
123
  "dependencies": {
124
- "@stll/docx-core": "^0.21.0",
124
+ "@stll/docx-core": "^0.22.0",
125
125
  "@stll/docx-utils": "^0.1.0",
126
126
  "@stll/template-conditions": ">=0.4.0 <1.0.0",
127
127
  "better-result": "3.0.1",
@@ -134,6 +134,7 @@
134
134
  "prosemirror-dropcursor": "^1.8.2",
135
135
  "prosemirror-gapcursor": "^1.4.1",
136
136
  "prosemirror-history": "^1.5.0",
137
+ "prosemirror-inputrules": "^1.5.0",
137
138
  "prosemirror-keymap": "^1.2.3",
138
139
  "prosemirror-model": "^1.25.9",
139
140
  "prosemirror-state": "^1.4.4",
@@ -1,4 +0,0 @@
1
- //#region src/docx/textWhitespace.d.ts
2
- declare const requiresXmlSpacePreserve: (text: string) => boolean;
3
- //#endregion
4
- export { requiresXmlSpacePreserve };
@@ -1,4 +0,0 @@
1
- //#region src/docx/textWhitespace.ts
2
- const requiresXmlSpacePreserve = (text) => text.startsWith(" ") || text.endsWith(" ") || text.includes(" ");
3
- //#endregion
4
- export { requiresXmlSpacePreserve };
@@ -1,6 +0,0 @@
1
- import { document_d_exports } from "../../types/document.js";
2
- //#region src/layout-bridge/engine/tableWidthUtils.d.ts
3
- declare function resolveTableWidthPx(width: number | undefined, widthType: document_d_exports.TableWidthType | undefined, containerWidth: number): number | undefined;
4
- declare function normalizeTableColumnWidths(widths: number[], columnCount: number, targetWidth: number): number[];
5
- //#endregion
6
- export { normalizeTableColumnWidths, resolveTableWidthPx };
@@ -1,25 +0,0 @@
1
- //#region src/layout-bridge/engine/tableWidthUtils.ts
2
- const TWIPS_PER_INCH = 1440;
3
- const PX_PER_INCH = 96;
4
- const PCT_DENOMINATOR = 5e3;
5
- const twipsToPixels = (twips) => twips / TWIPS_PER_INCH * PX_PER_INCH;
6
- function resolveTableWidthPx(width, widthType, containerWidth) {
7
- if (width === void 0 || width <= 0) return;
8
- if (widthType === "dxa") return twipsToPixels(width);
9
- if (widthType === "pct") return width / PCT_DENOMINATOR * containerWidth;
10
- }
11
- function normalizeTableColumnWidths(widths, columnCount, targetWidth) {
12
- if (columnCount <= 0) return [];
13
- if (widths.length === 0) return Array.from({ length: columnCount }, () => targetWidth / columnCount);
14
- const normalized = widths.slice(0, columnCount);
15
- const positives = normalized.filter((width) => width > 0);
16
- const fallback = positives.length > 0 ? positives.reduce((sum, width) => sum + width, 0) / positives.length : targetWidth / columnCount;
17
- while (normalized.length < columnCount) normalized.push(fallback);
18
- let fixedTotal = 0;
19
- for (const width of normalized) if (width > 0) fixedTotal += width;
20
- const missingCount = normalized.filter((width) => width <= 0).length;
21
- const missingWidth = missingCount > 0 ? Math.max(0, targetWidth - fixedTotal) / missingCount : 0;
22
- return normalized.map((width) => width > 0 ? width : missingWidth);
23
- }
24
- //#endregion
25
- export { normalizeTableColumnWidths, resolveTableWidthPx };
@@ -1,13 +0,0 @@
1
- //#region src/markdown/headings.d.ts
2
- /**
3
- * Heading-style detection from a paragraph style id. Ported from eigenpal
4
- * `agent/text-utils` (PR #595) so the markdown exporter stays self-contained
5
- * (folio has no `agent/text-utils` module). Word's built-in heading styles are
6
- * `Heading1`…`Heading9` (and localised aliases that still contain "heading").
7
- */
8
- /** True when the style id denotes a Word heading style. */
9
- declare function isHeadingStyle(styleId?: string): boolean;
10
- /** Extract the 1-based heading level from a style id, or undefined. */
11
- declare function parseHeadingLevel(styleId?: string): number | undefined;
12
- //#endregion
13
- export { isHeadingStyle, parseHeadingLevel };
@@ -1,20 +0,0 @@
1
- //#region src/markdown/headings.ts
2
- /**
3
- * Heading-style detection from a paragraph style id. Ported from eigenpal
4
- * `agent/text-utils` (PR #595) so the markdown exporter stays self-contained
5
- * (folio has no `agent/text-utils` module). Word's built-in heading styles are
6
- * `Heading1`…`Heading9` (and localised aliases that still contain "heading").
7
- */
8
- /** True when the style id denotes a Word heading style. */
9
- function isHeadingStyle(styleId) {
10
- if (!styleId) return false;
11
- return styleId.toLowerCase().includes("heading");
12
- }
13
- /** Extract the 1-based heading level from a style id, or undefined. */
14
- function parseHeadingLevel(styleId) {
15
- if (!styleId) return;
16
- const digit = /heading\s*(?<level>\d)/iu.exec(styleId)?.groups?.["level"];
17
- if (digit) return Number.parseInt(digit, 10);
18
- }
19
- //#endregion
20
- export { isHeadingStyle, parseHeadingLevel };