@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,10 +1,13 @@
1
- import { isValidHexColor } from "../utils/colorResolver.js";
2
1
  import { parseHorizontalScalePercent } from "../utils/horizontalScale.js";
3
2
  import { mergeParagraphFormatting } from "../utils/paragraphFormattingMerge.js";
4
3
  import { mergeStyleTextFormatting } from "../utils/textFormattingMerge.js";
5
- import { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
4
+ import { parseBorderSpec } from "./borderParser.js";
5
+ import { resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
6
+ import { ConditionalStyleTypeSchema, EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.js";
7
+ import { parseShading } from "./shadingParser.js";
8
+ import { parseTableLook } from "./tableParser.js";
6
9
  import { resolveThemeFontRef } from "./themeParser.js";
7
- import { findChild, findChildren, getAttribute, getLocalName, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute, parseOnOffValue, parseTableMeasurementValue, parseXmlDocument } from "./xmlParser.js";
10
+ import { findChild, findChildren, getAttribute, getLocalName, parseBooleanElement, parseNumberingLevelAttribute, parseNumericAttribute, parseOnOffAttribute, parseOnOffValue, parseTableMeasurementValue, parseXmlDocument } from "./xmlParser.js";
8
11
  //#region src/docx/styleParser.ts
9
12
  const findLastRunToggle = (rPr, localName) => findChildren(rPr, "w", localName).at(-1) ?? null;
10
13
  /**
@@ -55,7 +58,7 @@ function parseRunProperties(rPr, theme) {
55
58
  }
56
59
  const shd = findChild(rPr, "w", "shd");
57
60
  if (shd) {
58
- const shadingResult = parseShadingProperties(shd);
61
+ const shadingResult = parseShading(shd);
59
62
  if (shadingResult) formatting.shading = shadingResult;
60
63
  }
61
64
  const sz = findChild(rPr, "w", "sz");
@@ -189,50 +192,6 @@ function parseColorValue(rgb, themeColor, themeTint, themeShade) {
189
192
  return color;
190
193
  }
191
194
  /**
192
- * Parse shading properties (w:shd)
193
- */
194
- function parseShadingProperties(shd) {
195
- if (!shd) return;
196
- const props = {};
197
- const color = getAttribute(shd, "w", "color");
198
- if (color && color !== "auto" && isValidHexColor(color)) props.color = { rgb: color };
199
- const fill = getAttribute(shd, "w", "fill");
200
- if (fill && fill !== "auto" && isValidHexColor(fill)) props.fill = { rgb: fill };
201
- const validatedThemeFill = narrowEnum(getAttribute(shd, "w", "themeFill"), ThemeColorSlotSchema);
202
- if (validatedThemeFill) {
203
- if (!props.fill) props.fill = {};
204
- props.fill.themeColor = validatedThemeFill;
205
- }
206
- const themeFillTint = getAttribute(shd, "w", "themeFillTint");
207
- if (themeFillTint && props.fill) props.fill.themeTint = themeFillTint;
208
- const themeFillShade = getAttribute(shd, "w", "themeFillShade");
209
- if (themeFillShade && props.fill) props.fill.themeShade = themeFillShade;
210
- const pattern = narrowEnum(getAttribute(shd, "w", "val"), ShadingPatternSchema);
211
- if (pattern) props.pattern = pattern;
212
- return Object.keys(props).length > 0 ? props : void 0;
213
- }
214
- /**
215
- * Parse border specification
216
- */
217
- function parseBorderSpec(border) {
218
- if (!border) return;
219
- const rawStyle = getAttribute(border, "w", "val");
220
- if (!rawStyle) return;
221
- const spec = { style: narrowEnum(rawStyle, BorderStyleSchema) ?? rawStyle };
222
- const colorVal = getAttribute(border, "w", "color");
223
- const themeColor = getAttribute(border, "w", "themeColor");
224
- if (colorVal || themeColor) spec.color = parseColorValue(colorVal, themeColor, getAttribute(border, "w", "themeTint"), getAttribute(border, "w", "themeShade"));
225
- const sz = parseNumericAttribute(border, "w", "sz");
226
- if (sz !== void 0) spec.size = sz;
227
- const space = parseNumericAttribute(border, "w", "space");
228
- if (space !== void 0) spec.space = space;
229
- const shadowAttr = getAttribute(border, "w", "shadow");
230
- if (shadowAttr) spec.shadow = parseOnOffValue(shadowAttr) ?? false;
231
- const frame = getAttribute(border, "w", "frame");
232
- if (frame) spec.frame = parseOnOffValue(frame) ?? false;
233
- return spec;
234
- }
235
- /**
236
195
  * Parse tab stops (w:tabs)
237
196
  */
238
197
  function parseTabStops(tabs) {
@@ -280,10 +239,10 @@ function parseParagraphProperties(pPr, theme) {
280
239
  if (line !== void 0) formatting.lineSpacing = line;
281
240
  const lineRule = narrowEnum(getAttribute(spacing, "w", "lineRule"), LineSpacingRuleSchema);
282
241
  if (lineRule) formatting.lineSpacingRule = lineRule;
283
- const beforeAuto = getAttribute(spacing, "w", "beforeAutospacing");
284
- if (beforeAuto) formatting.beforeAutospacing = parseOnOffValue(beforeAuto) ?? false;
285
- const afterAuto = getAttribute(spacing, "w", "afterAutospacing");
286
- if (afterAuto) formatting.afterAutospacing = parseOnOffValue(afterAuto) ?? false;
242
+ const beforeAutospacing = parseOnOffAttribute(spacing, "w", "beforeAutospacing");
243
+ if (beforeAutospacing !== void 0) formatting.beforeAutospacing = beforeAutospacing;
244
+ const afterAutospacing = parseOnOffAttribute(spacing, "w", "afterAutospacing");
245
+ if (afterAutospacing !== void 0) formatting.afterAutospacing = afterAutospacing;
287
246
  }
288
247
  const ind = findChild(pPr, "w", "ind");
289
248
  if (ind) {
@@ -318,7 +277,7 @@ function parseParagraphProperties(pPr, theme) {
318
277
  }
319
278
  const shd = findChild(pPr, "w", "shd");
320
279
  if (shd) {
321
- const shadingResult = parseShadingProperties(shd);
280
+ const shadingResult = parseShading(shd);
322
281
  if (shadingResult) formatting.shading = shadingResult;
323
282
  }
324
283
  const tabs = findChild(pPr, "w", "tabs");
@@ -437,38 +396,6 @@ function parseCellMargins(tblCellMar) {
437
396
  return Object.keys(margins).length > 0 ? margins : void 0;
438
397
  }
439
398
  /**
440
- * Parse table look flags
441
- */
442
- function parseTableLook(tblLook) {
443
- if (!tblLook) return;
444
- const look = {};
445
- const val = getAttribute(tblLook, "w", "val");
446
- if (val) {
447
- const num = Number.parseInt(val, 16);
448
- if (!Number.isNaN(num)) {
449
- look.firstRow = (num & 32) !== 0;
450
- look.lastRow = (num & 64) !== 0;
451
- look.firstColumn = (num & 128) !== 0;
452
- look.lastColumn = (num & 256) !== 0;
453
- look.noHBand = (num & 512) !== 0;
454
- look.noVBand = (num & 1024) !== 0;
455
- }
456
- }
457
- const firstColumn = getAttribute(tblLook, "w", "firstColumn");
458
- if (firstColumn) look.firstColumn = parseOnOffValue(firstColumn) ?? false;
459
- const firstRow = getAttribute(tblLook, "w", "firstRow");
460
- if (firstRow) look.firstRow = parseOnOffValue(firstRow) ?? false;
461
- const lastColumn = getAttribute(tblLook, "w", "lastColumn");
462
- if (lastColumn) look.lastColumn = parseOnOffValue(lastColumn) ?? false;
463
- const lastRow = getAttribute(tblLook, "w", "lastRow");
464
- if (lastRow) look.lastRow = parseOnOffValue(lastRow) ?? false;
465
- const noHBand = getAttribute(tblLook, "w", "noHBand");
466
- if (noHBand) look.noHBand = parseOnOffValue(noHBand) ?? false;
467
- const noVBand = getAttribute(tblLook, "w", "noVBand");
468
- if (noVBand) look.noVBand = parseOnOffValue(noVBand) ?? false;
469
- return Object.keys(look).length > 0 ? look : void 0;
470
- }
471
- /**
472
399
  * Parse table formatting properties (w:tblPr)
473
400
  */
474
401
  function parseTableProperties(tblPr, _theme) {
@@ -521,7 +448,7 @@ function parseTableProperties(tblPr, _theme) {
521
448
  }
522
449
  const shd = findChild(tblPr, "w", "shd");
523
450
  if (shd) {
524
- const shadingResult = parseShadingProperties(shd);
451
+ const shadingResult = parseShading(shd);
525
452
  if (shadingResult) formatting.shading = shadingResult;
526
453
  }
527
454
  const bidiVisual = findChild(tblPr, "w", "bidiVisual");
@@ -577,7 +504,7 @@ function parseTableCellProperties(tcPr, _theme) {
577
504
  }
578
505
  const shd = findChild(tcPr, "w", "shd");
579
506
  if (shd) {
580
- const shadingResult = parseShadingProperties(shd);
507
+ const shadingResult = parseShading(shd);
581
508
  if (shadingResult) formatting.shading = shadingResult;
582
509
  }
583
510
  const vAlign = findChild(tcPr, "w", "vAlign");
@@ -916,8 +843,7 @@ function getResolvedStyle(styleId, styleMap) {
916
843
  * Get the default paragraph style
917
844
  */
918
845
  function getDefaultParagraphStyle(styleMap) {
919
- for (const style of styleMap.values()) if (style.type === "paragraph" && style.default) return style;
920
- return styleMap.get("Normal");
846
+ return resolveDefaultParagraphStyle(styleMap.values());
921
847
  }
922
848
  /**
923
849
  * Get the default character style
@@ -0,0 +1,36 @@
1
+ //#region src/docx/styleReferenceResolution.d.ts
2
+ /**
3
+ * Every style a package points at must be a style that package defines.
4
+ *
5
+ * A `w:pStyle`, `w:rStyle` or `w:tblStyle` naming an id `styles.xml` never
6
+ * declares is a dangling reference. Word tolerates one by falling back to the
7
+ * default style, which is exactly why it goes unnoticed: the document looks
8
+ * almost right, the paragraph silently loses its formatting, and a consumer
9
+ * that classifies by style — folio's own outline, TOC and AI snapshot included
10
+ * — sees nothing there. `w:basedOn`, `w:next` and `w:link` inside `styles.xml`
11
+ * dangle the same way.
12
+ *
13
+ * This is the "dangling by construction" bug class: a writer that hardcodes an
14
+ * English built-in id it does not also define produces it for *every* document
15
+ * it writes, not for some unlucky input. {@link danglingStyleReferences} is the
16
+ * shared check, so an authoring path can be held to it by a test rather than by
17
+ * the reviewer noticing.
18
+ */
19
+ /** One reference that resolves to nothing, and the part it was written into. */
20
+ type DanglingStyleReference = {
21
+ /** The `w:val` that names no defined style. */
22
+ styleId: string;
23
+ /** The package part the reference sits in, e.g. `word/document.xml`. */
24
+ part: string;
25
+ };
26
+ /**
27
+ * Collect the style references in `parts` that `stylesXml` does not define.
28
+ *
29
+ * `parts` maps a part name to its XML; pass every part that can carry a style
30
+ * reference (`word/document.xml`, the header/footer parts, `word/footnotes.xml`,
31
+ * `word/endnotes.xml`, `word/comments.xml`, and `word/styles.xml` itself for
32
+ * the `basedOn`/`next`/`link` graph).
33
+ */
34
+ declare const danglingStyleReferences: (stylesXml: string | undefined, parts: ReadonlyMap<string, string>) => DanglingStyleReference[];
35
+ //#endregion
36
+ export { DanglingStyleReference, danglingStyleReferences };
@@ -0,0 +1,51 @@
1
+ //#region src/docx/styleReferenceResolution.ts
2
+ /**
3
+ * Every style a package points at must be a style that package defines.
4
+ *
5
+ * A `w:pStyle`, `w:rStyle` or `w:tblStyle` naming an id `styles.xml` never
6
+ * declares is a dangling reference. Word tolerates one by falling back to the
7
+ * default style, which is exactly why it goes unnoticed: the document looks
8
+ * almost right, the paragraph silently loses its formatting, and a consumer
9
+ * that classifies by style — folio's own outline, TOC and AI snapshot included
10
+ * — sees nothing there. `w:basedOn`, `w:next` and `w:link` inside `styles.xml`
11
+ * dangle the same way.
12
+ *
13
+ * This is the "dangling by construction" bug class: a writer that hardcodes an
14
+ * English built-in id it does not also define produces it for *every* document
15
+ * it writes, not for some unlucky input. {@link danglingStyleReferences} is the
16
+ * shared check, so an authoring path can be held to it by a test rather than by
17
+ * the reviewer noticing.
18
+ */
19
+ const STYLE_REFERENCE = /<w:(?:pStyle|rStyle|tblStyle)\b[^>]*\bw:val="(?<id>[^"]*)"/gu;
20
+ const STYLE_LINK = /<w:(?:basedOn|next|link)\b[^>]*\bw:val="(?<id>[^"]*)"/gu;
21
+ const STYLE_DEFINITION = /<w:style\b[^>]*\bw:styleId="(?<id>[^"]*)"/gu;
22
+ const idsIn = (xml, pattern) => {
23
+ const ids = [];
24
+ for (const match of xml.matchAll(pattern)) {
25
+ const id = match.groups?.["id"];
26
+ if (id !== void 0 && id.length > 0) ids.push(id);
27
+ }
28
+ return ids;
29
+ };
30
+ /**
31
+ * Collect the style references in `parts` that `stylesXml` does not define.
32
+ *
33
+ * `parts` maps a part name to its XML; pass every part that can carry a style
34
+ * reference (`word/document.xml`, the header/footer parts, `word/footnotes.xml`,
35
+ * `word/endnotes.xml`, `word/comments.xml`, and `word/styles.xml` itself for
36
+ * the `basedOn`/`next`/`link` graph).
37
+ */
38
+ const danglingStyleReferences = (stylesXml, parts) => {
39
+ const defined = new Set(idsIn(stylesXml ?? "", STYLE_DEFINITION));
40
+ const dangling = [];
41
+ for (const [part, xml] of parts) {
42
+ const references = part === "word/styles.xml" ? idsIn(xml, STYLE_LINK) : [...idsIn(xml, STYLE_REFERENCE), ...idsIn(xml, STYLE_LINK)];
43
+ for (const styleId of references) if (!defined.has(styleId)) dangling.push({
44
+ styleId,
45
+ part
46
+ });
47
+ }
48
+ return dangling;
49
+ };
50
+ //#endregion
51
+ export { danglingStyleReferences };
@@ -0,0 +1,57 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/docx/tableLook.d.ts
3
+ /**
4
+ * Every flag, in the order `CT_TblLook` declares them.
5
+ *
6
+ * The reader and the serializer both walk this, so the attributes go back out
7
+ * in the order they came in.
8
+ */
9
+ declare const TABLE_LOOK_FLAGS: readonly ["firstRow", "lastRow", "firstColumn", "lastColumn", "noHBand", "noVBand"];
10
+ type TableLookFlag = (typeof TABLE_LOOK_FLAGS)[number];
11
+ /** The bit of `w:val` each flag restates (ECMA-376 §17.4.57). */
12
+ declare const TABLE_LOOK_BITS: {
13
+ readonly firstRow: 32;
14
+ readonly lastRow: 64;
15
+ readonly firstColumn: 128;
16
+ readonly lastColumn: 256;
17
+ readonly noHBand: 512;
18
+ readonly noVBand: 1024;
19
+ };
20
+ /**
21
+ * Every flag, decided.
22
+ *
23
+ * Binding the record to `TableLook`'s own keys is the totality gate: a flag
24
+ * added to the model that {@link TABLE_LOOK_FLAGS} does not list makes this
25
+ * alias fail its constraint, so the module stops compiling rather than letting
26
+ * a flag ship with no bit, no read order and no resolution.
27
+ */
28
+ type ResolvedTableLook = document_d_exports.ExhaustiveFields<Record<TableLookFlag, boolean>, Exclude<keyof document_d_exports.TableLook, "val">>;
29
+ /**
30
+ * Resolve a `w:tblLook` to the six answers a consumer can act on.
31
+ *
32
+ * Precedence is the flag the author stated, then the matching bit of `w:val`,
33
+ * then off. The attribute form wins because it is the later spelling of the
34
+ * same fact: a producer that writes both and disagrees means the flags, and a
35
+ * producer that writes only `w:val` still gets its banding and its header row.
36
+ */
37
+ declare const resolveTableLook: (look: document_d_exports.TableLook | undefined) => ResolvedTableLook;
38
+ type SetTableLookFlagsOptions = {
39
+ look: document_d_exports.TableLook | undefined;
40
+ /**
41
+ * The flags to state. A flag left out keeps whatever the author said, which
42
+ * may be nothing; this is a patch over the authored value, not a decision
43
+ * per flag, so `Partial` is the honest type.
44
+ */
45
+ flags: Readonly<Partial<ResolvedTableLook>>;
46
+ };
47
+ /**
48
+ * State flags on a `w:tblLook`, leaving `w:val` as the author wrote it.
49
+ *
50
+ * The attribute form is what {@link resolveTableLook} reads first, so stating a
51
+ * flag is enough to change the table. Re-encoding `w:val` instead would rewrite
52
+ * the bits outside the six modelled here — the bitmask is 16 bits wide and the
53
+ * format reserves the rest — and folio has nothing to put there.
54
+ */
55
+ declare const setTableLookFlags: ({ look, flags }: SetTableLookFlagsOptions) => document_d_exports.TableLook;
56
+ //#endregion
57
+ export { ResolvedTableLook, TABLE_LOOK_BITS, TABLE_LOOK_FLAGS, TableLookFlag, resolveTableLook, setTableLookFlags };
@@ -0,0 +1,63 @@
1
+ //#region src/docx/tableLook.ts
2
+ /**
3
+ * Every flag, in the order `CT_TblLook` declares them.
4
+ *
5
+ * The reader and the serializer both walk this, so the attributes go back out
6
+ * in the order they came in.
7
+ */
8
+ const TABLE_LOOK_FLAGS = [
9
+ "firstRow",
10
+ "lastRow",
11
+ "firstColumn",
12
+ "lastColumn",
13
+ "noHBand",
14
+ "noVBand"
15
+ ];
16
+ /** The bit of `w:val` each flag restates (ECMA-376 §17.4.57). */
17
+ const TABLE_LOOK_BITS = {
18
+ firstRow: 32,
19
+ lastRow: 64,
20
+ firstColumn: 128,
21
+ lastColumn: 256,
22
+ noHBand: 512,
23
+ noVBand: 1024
24
+ };
25
+ const tableLookMask = (val) => {
26
+ if (val === void 0) return 0;
27
+ const bits = Number.parseInt(val, 16);
28
+ return Number.isNaN(bits) ? 0 : bits;
29
+ };
30
+ /**
31
+ * Resolve a `w:tblLook` to the six answers a consumer can act on.
32
+ *
33
+ * Precedence is the flag the author stated, then the matching bit of `w:val`,
34
+ * then off. The attribute form wins because it is the later spelling of the
35
+ * same fact: a producer that writes both and disagrees means the flags, and a
36
+ * producer that writes only `w:val` still gets its banding and its header row.
37
+ */
38
+ const resolveTableLook = (look) => {
39
+ const mask = tableLookMask(look?.val);
40
+ const resolve = (flag) => look?.[flag] ?? (mask & TABLE_LOOK_BITS[flag]) !== 0;
41
+ return {
42
+ firstRow: resolve("firstRow"),
43
+ lastRow: resolve("lastRow"),
44
+ firstColumn: resolve("firstColumn"),
45
+ lastColumn: resolve("lastColumn"),
46
+ noHBand: resolve("noHBand"),
47
+ noVBand: resolve("noVBand")
48
+ };
49
+ };
50
+ /**
51
+ * State flags on a `w:tblLook`, leaving `w:val` as the author wrote it.
52
+ *
53
+ * The attribute form is what {@link resolveTableLook} reads first, so stating a
54
+ * flag is enough to change the table. Re-encoding `w:val` instead would rewrite
55
+ * the bits outside the six modelled here — the bitmask is 16 bits wide and the
56
+ * format reserves the rest — and folio has nothing to put there.
57
+ */
58
+ const setTableLookFlags = ({ look, flags }) => ({
59
+ ...look,
60
+ ...flags
61
+ });
62
+ //#endregion
63
+ export { TABLE_LOOK_BITS, TABLE_LOOK_FLAGS, resolveTableLook, setTableLookFlags };
@@ -23,7 +23,6 @@ declare function parseTableMeasurement(element: XmlElement | null): document_d_e
23
23
  * @param element - Border element (w:top, w:bottom, etc.)
24
24
  * @returns Parsed border or undefined
25
25
  */
26
- declare function parseBorderSpec(element: XmlElement | null): document_d_exports.BorderSpec | undefined;
27
26
  /**
28
27
  * Parse table borders (w:tblBorders or w:tcBorders)
29
28
  *
@@ -39,14 +38,13 @@ declare function parseTableBorders(bordersElement: XmlElement | null): document_
39
38
  */
40
39
  declare function parseCellMargins(marginsElement: XmlElement | null): document_d_exports.CellMargins | undefined;
41
40
  /**
42
- * Parse shading properties (w:shd)
41
+ * Read a `w:tblLook` (the only reader; `styleParser` calls this one).
43
42
  *
44
- * @param shdElement - The w:shd element
45
- * @returns Parsed shading or undefined
46
- */
47
- declare function parseShading(shdElement: XmlElement | null): document_d_exports.ShadingProperties | undefined;
48
- /**
49
- * Parse table look flags (w:tblLook)
43
+ * What the author wrote, and nothing more: `w:val` verbatim and each flag as
44
+ * stated, absent, `false` or `true`. Folding `w:val`'s bits into the flags here
45
+ * would forget which of the two the document said, and writing the result back
46
+ * would invent attributes the author never had. `resolveTableLook` owns the
47
+ * other direction.
50
48
  *
51
49
  * @param lookElement - The w:tblLook element
52
50
  * @returns Parsed table look or undefined
@@ -199,4 +197,4 @@ declare function getHeaderRows(table: document_d_exports.Table): document_d_expo
199
197
  */
200
198
  declare function isFloatingTable(table: document_d_exports.Table): boolean;
201
199
  //#endregion
202
- export { MAX_TABLE_COLUMNS, getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseBorderSpec, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseShading, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };
200
+ export { MAX_TABLE_COLUMNS, getHeaderRows, getTableColumnCount, getTableRowCount, getTableText, hasHeaderRow, isCellHorizontallyMerged, isCellMergeContinuation, isCellMergeStart, isFloatingTable, parseCellMargins, parseConditionalFormatStyle, parseFloatingTableProperties, parseTable, parseTableBorders, parseTableCell, parseTableCellProperties, parseTableGrid, parseTableLook, parseTableMeasurement, parseTableProperties, parseTableRow, parseTableRowProperties };