@stll/folio-core 0.43.0 → 0.45.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 (237) hide show
  1. package/dist/ai-edits/__fixtures__/paragraphs.js +2 -2
  2. package/dist/ai-edits/headless.js +7 -5
  3. package/dist/ai-edits/index.d.ts +2 -2
  4. package/dist/ai-edits/index.js +2 -2
  5. package/dist/ai-edits/snapshot.js +13 -9
  6. package/dist/compare/content-alignment.js +94 -54
  7. package/dist/compare/inline-atoms.js +34 -20
  8. package/dist/compare/style-resources.js +6 -0
  9. package/dist/content-controls/mutateContentControls.js +4 -2
  10. package/dist/display-list/dom/renderDisplayListToDom.js +8 -8
  11. package/dist/document-operations.js +14 -3
  12. package/dist/docx/appVersionNormalization.d.ts +0 -18
  13. package/dist/docx/blockContentParser.js +8 -0
  14. package/dist/docx/blockRangeMarkers.d.ts +36 -0
  15. package/dist/docx/blockRangeMarkers.js +59 -0
  16. package/dist/docx/bookmarkParser.d.ts +2 -20
  17. package/dist/docx/bookmarkParser.js +6 -30
  18. package/dist/docx/borderParser.d.ts +13 -0
  19. package/dist/docx/borderParser.js +71 -0
  20. package/dist/docx/builtInStyles.d.ts +165 -0
  21. package/dist/docx/builtInStyles.js +239 -0
  22. package/dist/docx/commentIdNormalization.d.ts +3 -1
  23. package/dist/docx/commentIdNormalization.js +18 -1
  24. package/dist/docx/commentParser.d.ts +2 -1
  25. package/dist/docx/commentParser.js +80 -42
  26. package/dist/docx/commentReferenceNormalization.d.ts +4 -1
  27. package/dist/docx/commentReferenceNormalization.js +23 -14
  28. package/dist/docx/commentThreadKey.d.ts +18 -0
  29. package/dist/docx/commentThreadKey.js +22 -0
  30. package/dist/docx/danglingRelationshipReferences.d.ts +15 -0
  31. package/dist/docx/danglingRelationshipReferences.js +30 -0
  32. package/dist/docx/defaultParagraphStyle.d.ts +18 -1
  33. package/dist/docx/defaultParagraphStyle.js +23 -1
  34. package/dist/docx/diagramPreview.js +87 -27
  35. package/dist/docx/documentParser.d.ts +2 -1
  36. package/dist/docx/documentParser.js +2 -2
  37. package/dist/docx/drawingUtils.d.ts +8 -1
  38. package/dist/docx/drawingUtils.js +12 -3
  39. package/dist/docx/fieldParser.js +3 -5
  40. package/dist/docx/footnoteParser.d.ts +3 -2
  41. package/dist/docx/footnoteParser.js +19 -4
  42. package/dist/docx/groupDrawingParser.js +4 -4
  43. package/dist/docx/headerFooterRefParser.d.ts +4 -3
  44. package/dist/docx/headerFooterRefParser.js +42 -12
  45. package/dist/docx/headerFooterReferenceNormalization.d.ts +4 -1
  46. package/dist/docx/headerFooterReferenceNormalization.js +5 -1
  47. package/dist/docx/hyperlinkParser.js +13 -17
  48. package/dist/docx/imageParser.d.ts +10 -2
  49. package/dist/docx/imageParser.js +80 -30
  50. package/dist/docx/imageRawXml.d.ts +14 -1
  51. package/dist/docx/imageRawXml.js +35 -11
  52. package/dist/docx/markupRangeMarker.d.ts +15 -0
  53. package/dist/docx/markupRangeMarker.js +44 -0
  54. package/dist/docx/mathToMathml.js +12 -14
  55. package/dist/docx/nonVisualDrawingProps.d.ts +34 -0
  56. package/dist/docx/nonVisualDrawingProps.js +46 -0
  57. package/dist/docx/noteReferenceStyles.d.ts +29 -0
  58. package/dist/docx/noteReferenceStyles.js +70 -0
  59. package/dist/docx/numberingReferenceNormalization.d.ts +4 -1
  60. package/dist/docx/numberingReferenceNormalization.js +20 -1
  61. package/dist/docx/paraIdRangeNormalization.d.ts +0 -19
  62. package/dist/docx/paragraphParser.js +66 -99
  63. package/dist/docx/paragraphPropertySource.js +1 -0
  64. package/dist/docx/paragraphTextBoxEnrichment.js +3 -0
  65. package/dist/docx/paragraphTraversal.d.ts +37 -1
  66. package/dist/docx/paragraphTraversal.js +84 -1
  67. package/dist/docx/parseContext.d.ts +37 -0
  68. package/dist/docx/parseContext.js +67 -0
  69. package/dist/docx/parseWarningMessage.d.ts +6 -0
  70. package/dist/docx/parseWarningMessage.js +44 -0
  71. package/dist/docx/parser.js +83 -29
  72. package/dist/docx/previewBudget.d.ts +64 -0
  73. package/dist/docx/previewBudget.js +88 -0
  74. package/dist/docx/relsParser.d.ts +28 -11
  75. package/dist/docx/relsParser.js +26 -13
  76. package/dist/docx/revisionIdNormalization.js +96 -10
  77. package/dist/docx/rezip.js +80 -40
  78. package/dist/docx/runConsolidator.js +1 -2
  79. package/dist/docx/runParser.d.ts +8 -1
  80. package/dist/docx/runParser.js +30 -48
  81. package/dist/docx/sdtPropertiesPatch.js +24 -18
  82. package/dist/docx/sectionParser.d.ts +2 -1
  83. package/dist/docx/sectionParser.js +21 -65
  84. package/dist/docx/sectionReferenceHistory.js +2 -2
  85. package/dist/docx/selectiveSave.js +6 -6
  86. package/dist/docx/serializer/blockSdtSerializer.js +38 -26
  87. package/dist/docx/serializer/borderSerializer.d.ts +2 -3
  88. package/dist/docx/serializer/borderSerializer.js +13 -12
  89. package/dist/docx/serializer/commentSerializer.d.ts +41 -16
  90. package/dist/docx/serializer/commentSerializer.js +82 -72
  91. package/dist/docx/serializer/documentSerializer.d.ts +1 -5
  92. package/dist/docx/serializer/documentSerializer.js +6 -16
  93. package/dist/docx/serializer/fontTableSerializer.js +6 -6
  94. package/dist/docx/serializer/headerFooterSerializer.js +10 -5
  95. package/dist/docx/serializer/markupRangeAttributes.d.ts +8 -0
  96. package/dist/docx/serializer/markupRangeAttributes.js +24 -0
  97. package/dist/docx/serializer/noteSerializer.js +5 -0
  98. package/dist/docx/serializer/numberingSerializer.js +7 -6
  99. package/dist/docx/serializer/paragraphSerializer.d.ts +1 -5
  100. package/dist/docx/serializer/paragraphSerializer.js +47 -52
  101. package/dist/docx/serializer/partNamespaces.js +2 -2
  102. package/dist/docx/serializer/runSerializer.js +57 -31
  103. package/dist/docx/serializer/sectionPropertiesSerializer.js +11 -10
  104. package/dist/docx/serializer/settingsSerializer.js +4 -3
  105. package/dist/docx/serializer/stylesSerializer.js +6 -6
  106. package/dist/docx/serializer/tableSerializer.js +37 -21
  107. package/dist/docx/serializer/textFormattingSerializer.d.ts +2 -3
  108. package/dist/docx/serializer/textFormattingSerializer.js +29 -28
  109. package/dist/docx/serializer/themeSerializer.js +6 -6
  110. package/dist/docx/serializer/trackedChangeAttributes.js +2 -2
  111. package/dist/docx/serializer/xmlUtils.d.ts +1 -2
  112. package/dist/docx/serializer/xmlUtils.js +1 -13
  113. package/dist/docx/server/boundedArchive.d.ts +12 -0
  114. package/dist/docx/server/boundedArchive.js +20 -1
  115. package/dist/docx/server/build.js +8 -1
  116. package/dist/docx/server/createBilingualDocument.js +10 -18
  117. package/dist/docx/server/extractDocxText.js +3 -4
  118. package/dist/docx/server/validateDocxConformance.js +22 -1
  119. package/dist/docx/shadingParser.d.ts +6 -0
  120. package/dist/docx/shadingParser.js +32 -0
  121. package/dist/docx/shapeParser.js +10 -8
  122. package/dist/docx/styleParser.js +13 -87
  123. package/dist/docx/styleReferenceResolution.d.ts +36 -0
  124. package/dist/docx/styleReferenceResolution.js +51 -0
  125. package/dist/docx/tableLook.d.ts +57 -0
  126. package/dist/docx/tableLook.js +63 -0
  127. package/dist/docx/tableParser.d.ts +7 -9
  128. package/dist/docx/tableParser.js +64 -110
  129. package/dist/docx/textBoxParser.js +11 -6
  130. package/dist/docx/trackedMoveRangeNormalization.d.ts +3 -1
  131. package/dist/docx/trackedMoveRangeNormalization.js +11 -21
  132. package/dist/docx/transitionalSpelling.d.ts +13 -2
  133. package/dist/docx/transitionalSpelling.js +23 -1
  134. package/dist/docx/unzip.d.ts +23 -0
  135. package/dist/docx/unzip.js +32 -22
  136. package/dist/docx/verbatimCapture.js +5 -12
  137. package/dist/docx/vmlImageParser.js +5 -4
  138. package/dist/docx/vmlPreview.d.ts +1 -3
  139. package/dist/docx/vmlPreview.js +2 -30
  140. package/dist/docx/watermarkParser.js +2 -2
  141. package/dist/docx/xmlParser.d.ts +38 -33
  142. package/dist/docx/xmlParser.js +92 -47
  143. package/dist/docx/xmlResourceLimits.d.ts +89 -9
  144. package/dist/docx/xmlResourceLimits.js +105 -24
  145. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  146. package/dist/internal/paragraphFormattingSerialization.d.ts +2 -3
  147. package/dist/internal/paragraphFormattingSerialization.js +29 -8
  148. package/dist/layout-bridge/convert/footnoteLayout.js +2 -7
  149. package/dist/layout-engine/index.d.ts +2 -2
  150. package/dist/layout-engine/index.js +2 -2
  151. package/dist/layout-engine/measure/measureBlocks.js +1 -6
  152. package/dist/layout-engine/types.d.ts +8 -2
  153. package/dist/layout-engine/types.js +35 -2
  154. package/dist/layout-painter/renderImage.js +4 -3
  155. package/dist/layout-painter/renderParagraph.js +4 -3
  156. package/dist/managers/autoSaveCodec.js +2 -8
  157. package/dist/markdown/images.js +1 -4
  158. package/dist/markdown/index.js +1 -1
  159. package/dist/markdown/internals.d.ts +6 -1
  160. package/dist/markdown/internals.js +14 -1
  161. package/dist/markdown/renderBlock.js +35 -21
  162. package/dist/markdown/renderParagraph.js +14 -5
  163. package/dist/markdown/renderRuns.js +4 -3
  164. package/dist/markdown/renderTable.js +4 -3
  165. package/dist/markdown/trailers.js +41 -7
  166. package/dist/markdown/types.d.ts +3 -7
  167. package/dist/prosemirror/attrs/index.js +71 -5
  168. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +11 -1
  169. package/dist/prosemirror/bookmarkBoundaryAttrs.js +18 -3
  170. package/dist/prosemirror/commands/image.js +1 -0
  171. package/dist/prosemirror/commands/index.d.ts +3 -3
  172. package/dist/prosemirror/commands/index.js +2 -2
  173. package/dist/prosemirror/commands/paragraph.d.ts +3 -3
  174. package/dist/prosemirror/commands/paragraph.js +2 -2
  175. package/dist/prosemirror/commentIdAllocator.js +2 -7
  176. package/dist/prosemirror/conversion/fromProseDoc.js +197 -68
  177. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -14
  178. package/dist/prosemirror/conversion/toProseDoc.js +458 -335
  179. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +14 -1
  180. package/dist/prosemirror/extensions/core/ParagraphExtension.js +11 -6
  181. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +3 -3
  182. package/dist/prosemirror/extensions/features/PasteCleanupExtension.d.ts +4 -1
  183. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +6 -2
  184. package/dist/prosemirror/extensions/features/pastedHeadingStyles.d.ts +7 -0
  185. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +74 -0
  186. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +2 -3
  187. package/dist/prosemirror/extensions/marks/markUtils.d.ts +11 -3
  188. package/dist/prosemirror/extensions/marks/markUtils.js +98 -19
  189. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +7 -3
  190. package/dist/prosemirror/extensions/nodes/ImageExtension.js +6 -1
  191. package/dist/prosemirror/extensions/nodes/ShapeExtension.js +8 -2
  192. package/dist/prosemirror/extensions/nodes/TableExtension.js +15 -1
  193. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +8 -4
  194. package/dist/prosemirror/extensions/types.d.ts +2 -2
  195. package/dist/prosemirror/index.d.ts +3 -3
  196. package/dist/prosemirror/index.js +3 -3
  197. package/dist/prosemirror/insertOperations.d.ts +9 -2
  198. package/dist/prosemirror/insertOperations.js +9 -4
  199. package/dist/prosemirror/paragraphFormattingProvenance.d.ts +162 -0
  200. package/dist/prosemirror/paragraphFormattingProvenance.js +115 -0
  201. package/dist/prosemirror/plugins/documentStyles.d.ts +9 -1
  202. package/dist/prosemirror/plugins/documentStyles.js +11 -1
  203. package/dist/prosemirror/plugins/index.d.ts +2 -2
  204. package/dist/prosemirror/plugins/index.js +2 -2
  205. package/dist/prosemirror/plugins/revisionIds.d.ts +11 -2
  206. package/dist/prosemirror/plugins/revisionIds.js +21 -6
  207. package/dist/prosemirror/runFormattingReconciliation.js +3 -2
  208. package/dist/prosemirror/runStyleFormatting.d.ts +1 -1
  209. package/dist/prosemirror/schema/nodes.d.ts +81 -1
  210. package/dist/prosemirror/styles/resolvedStyleAttrs.js +2 -0
  211. package/dist/prosemirror/styles/styleResolver.d.ts +9 -0
  212. package/dist/prosemirror/styles/styleResolver.js +12 -0
  213. package/dist/style-engine/styleEngine.d.ts +3 -0
  214. package/dist/style-engine/styleEngine.js +3 -0
  215. package/dist/style-sets/extract.js +1 -23
  216. package/dist/style-sets/stellaStyle.js +46 -39
  217. package/dist/style-sets/styleSetNormalization.d.ts +19 -0
  218. package/dist/style-sets/styleSetNormalization.js +99 -0
  219. package/dist/types/content.d.ts +2 -2
  220. package/dist/utils/base64.d.ts +36 -0
  221. package/dist/utils/base64.js +40 -0
  222. package/dist/utils/clipboard.js +2 -1
  223. package/dist/utils/createDocument.js +145 -20
  224. package/dist/utils/headingCollector.d.ts +8 -5
  225. package/dist/utils/headingCollector.js +23 -25
  226. package/dist/utils/tableOfContentsStyle.js +9 -2
  227. package/dist/utils/units.d.ts +10 -1
  228. package/dist/utils/units.js +12 -1
  229. package/dist/utils/urlSecurity.d.ts +8 -2
  230. package/dist/utils/urlSecurity.js +21 -3
  231. package/package.json +2 -2
  232. package/dist/docx/textWhitespace.d.ts +0 -4
  233. package/dist/docx/textWhitespace.js +0 -4
  234. package/dist/layout-bridge/engine/tableWidthUtils.d.ts +0 -6
  235. package/dist/layout-bridge/engine/tableWidthUtils.js +0 -25
  236. package/dist/markdown/headings.d.ts +0 -13
  237. package/dist/markdown/headings.js +0 -20
@@ -1,6 +1,7 @@
1
1
  import { parseAnchorPosition, parseAnchorWrap, parseFill, parseOutline } from "./drawingUtils.js";
2
+ import { parseNonVisualDrawingNames } from "./nonVisualDrawingProps.js";
2
3
  import { ShapeTypeSchema, narrowEnum } from "./parserEnums.js";
3
- import { findAllDeep, findChildByLocalName, findChildren, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
4
+ import { findAllDeep, findChildByLocalName, findChildren, getAttribute, getChildElements, parseNumericAttribute, parseOnOffAttribute } from "./xmlParser.js";
4
5
  //#region src/docx/shapeParser.ts
5
6
  /** Convert OOXML rotation (1/60000ths of a degree) to degrees. */
6
7
  function rotToDegrees(rot) {
@@ -26,8 +27,8 @@ function parseTransform(xfrm) {
26
27
  height: parseNumericAttribute(ext, null, "cy") ?? 0
27
28
  };
28
29
  const rotation = rotToDegrees(getAttribute(xfrm, null, "rot"));
29
- const flipH = getAttribute(xfrm, null, "flipH") === "1";
30
- const flipV = getAttribute(xfrm, null, "flipV") === "1";
30
+ const flipH = parseOnOffAttribute(xfrm, null, "flipH") === true;
31
+ const flipV = parseOnOffAttribute(xfrm, null, "flipV") === true;
31
32
  if (rotation === void 0 && !flipH && !flipV) return { size };
32
33
  const transform = {};
33
34
  if (rotation !== void 0) transform.rotation = rotation;
@@ -139,16 +140,15 @@ function parseShape(node) {
139
140
  const fill = parseShapeFill(spPr);
140
141
  const outline = parseOutline(spPr);
141
142
  const id = cNvPr ? getAttribute(cNvPr, null, "id") ?? void 0 : void 0;
142
- const name = cNvPr ? getAttribute(cNvPr, null, "name") ?? void 0 : void 0;
143
143
  const shape = {
144
144
  type: "shape",
145
145
  shapeType,
146
- size
146
+ size,
147
+ ...parseNonVisualDrawingNames(cNvPr)
147
148
  };
148
149
  const geometryAdjustments = parseGeometryAdjustments(spPr);
149
150
  if (geometryAdjustments !== void 0) shape.geometryAdjustments = geometryAdjustments;
150
151
  if (id !== void 0) shape.id = id;
151
- if (name !== void 0) shape.name = name;
152
152
  if (fill !== void 0) shape.fill = fill;
153
153
  if (outline !== void 0) shape.outline = outline;
154
154
  if (transform !== void 0) shape.transform = transform;
@@ -193,9 +193,11 @@ function parseShapeFromDrawing(drawingEl) {
193
193
  const docPr = findChildByLocalName(container, "docPr");
194
194
  if (docPr) {
195
195
  const id = getAttribute(docPr, null, "id");
196
- const name = getAttribute(docPr, null, "name");
197
196
  if (id !== null) shape.id = id;
198
- if (name !== null) shape.name = name;
197
+ const names = parseNonVisualDrawingNames(docPr);
198
+ if (names.name !== void 0) shape.name = names.name;
199
+ if (names.alt !== void 0) shape.alt = names.alt;
200
+ if (names.title !== void 0) shape.title = names.title;
199
201
  }
200
202
  return shape;
201
203
  }
@@ -1,11 +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";
4
+ import { parseBorderSpec } from "./borderParser.js";
5
5
  import { resolveDefaultParagraphStyle } from "./defaultParagraphStyle.js";
6
- import { BorderStyleSchema, ConditionalStyleTypeSchema, EmphasisMarkSchema, FontHintSchema, FontThemeSchema, HighlightColorSchema, LineSpacingRuleSchema, ParagraphAlignmentSchema, ShadingPatternSchema, StyleTypeSchema, TabLeaderSchema, TabStopAlignmentSchema, TableCellTextDirectionSchema, TableRowHeightRuleSchema, TableWidthTypeSchema, TextEffectSchema, ThemeColorSlotSchema, UnderlineStyleSchema, narrowEnum } from "./parserEnums.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";
7
9
  import { resolveThemeFontRef } from "./themeParser.js";
8
- 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";
9
11
  //#region src/docx/styleParser.ts
10
12
  const findLastRunToggle = (rPr, localName) => findChildren(rPr, "w", localName).at(-1) ?? null;
11
13
  /**
@@ -56,7 +58,7 @@ function parseRunProperties(rPr, theme) {
56
58
  }
57
59
  const shd = findChild(rPr, "w", "shd");
58
60
  if (shd) {
59
- const shadingResult = parseShadingProperties(shd);
61
+ const shadingResult = parseShading(shd);
60
62
  if (shadingResult) formatting.shading = shadingResult;
61
63
  }
62
64
  const sz = findChild(rPr, "w", "sz");
@@ -190,50 +192,6 @@ function parseColorValue(rgb, themeColor, themeTint, themeShade) {
190
192
  return color;
191
193
  }
192
194
  /**
193
- * Parse shading properties (w:shd)
194
- */
195
- function parseShadingProperties(shd) {
196
- if (!shd) return;
197
- const props = {};
198
- const color = getAttribute(shd, "w", "color");
199
- if (color && color !== "auto" && isValidHexColor(color)) props.color = { rgb: color };
200
- const fill = getAttribute(shd, "w", "fill");
201
- if (fill && fill !== "auto" && isValidHexColor(fill)) props.fill = { rgb: fill };
202
- const validatedThemeFill = narrowEnum(getAttribute(shd, "w", "themeFill"), ThemeColorSlotSchema);
203
- if (validatedThemeFill) {
204
- if (!props.fill) props.fill = {};
205
- props.fill.themeColor = validatedThemeFill;
206
- }
207
- const themeFillTint = getAttribute(shd, "w", "themeFillTint");
208
- if (themeFillTint && props.fill) props.fill.themeTint = themeFillTint;
209
- const themeFillShade = getAttribute(shd, "w", "themeFillShade");
210
- if (themeFillShade && props.fill) props.fill.themeShade = themeFillShade;
211
- const pattern = narrowEnum(getAttribute(shd, "w", "val"), ShadingPatternSchema);
212
- if (pattern) props.pattern = pattern;
213
- return Object.keys(props).length > 0 ? props : void 0;
214
- }
215
- /**
216
- * Parse border specification
217
- */
218
- function parseBorderSpec(border) {
219
- if (!border) return;
220
- const rawStyle = getAttribute(border, "w", "val");
221
- if (!rawStyle) return;
222
- const spec = { style: narrowEnum(rawStyle, BorderStyleSchema) ?? rawStyle };
223
- const colorVal = getAttribute(border, "w", "color");
224
- const themeColor = getAttribute(border, "w", "themeColor");
225
- if (colorVal || themeColor) spec.color = parseColorValue(colorVal, themeColor, getAttribute(border, "w", "themeTint"), getAttribute(border, "w", "themeShade"));
226
- const sz = parseNumericAttribute(border, "w", "sz");
227
- if (sz !== void 0) spec.size = sz;
228
- const space = parseNumericAttribute(border, "w", "space");
229
- if (space !== void 0) spec.space = space;
230
- const shadowAttr = getAttribute(border, "w", "shadow");
231
- if (shadowAttr) spec.shadow = parseOnOffValue(shadowAttr) ?? false;
232
- const frame = getAttribute(border, "w", "frame");
233
- if (frame) spec.frame = parseOnOffValue(frame) ?? false;
234
- return spec;
235
- }
236
- /**
237
195
  * Parse tab stops (w:tabs)
238
196
  */
239
197
  function parseTabStops(tabs) {
@@ -281,10 +239,10 @@ function parseParagraphProperties(pPr, theme) {
281
239
  if (line !== void 0) formatting.lineSpacing = line;
282
240
  const lineRule = narrowEnum(getAttribute(spacing, "w", "lineRule"), LineSpacingRuleSchema);
283
241
  if (lineRule) formatting.lineSpacingRule = lineRule;
284
- const beforeAuto = getAttribute(spacing, "w", "beforeAutospacing");
285
- if (beforeAuto) formatting.beforeAutospacing = parseOnOffValue(beforeAuto) ?? false;
286
- const afterAuto = getAttribute(spacing, "w", "afterAutospacing");
287
- 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;
288
246
  }
289
247
  const ind = findChild(pPr, "w", "ind");
290
248
  if (ind) {
@@ -319,7 +277,7 @@ function parseParagraphProperties(pPr, theme) {
319
277
  }
320
278
  const shd = findChild(pPr, "w", "shd");
321
279
  if (shd) {
322
- const shadingResult = parseShadingProperties(shd);
280
+ const shadingResult = parseShading(shd);
323
281
  if (shadingResult) formatting.shading = shadingResult;
324
282
  }
325
283
  const tabs = findChild(pPr, "w", "tabs");
@@ -438,38 +396,6 @@ function parseCellMargins(tblCellMar) {
438
396
  return Object.keys(margins).length > 0 ? margins : void 0;
439
397
  }
440
398
  /**
441
- * Parse table look flags
442
- */
443
- function parseTableLook(tblLook) {
444
- if (!tblLook) return;
445
- const look = {};
446
- const val = getAttribute(tblLook, "w", "val");
447
- if (val) {
448
- const num = Number.parseInt(val, 16);
449
- if (!Number.isNaN(num)) {
450
- look.firstRow = (num & 32) !== 0;
451
- look.lastRow = (num & 64) !== 0;
452
- look.firstColumn = (num & 128) !== 0;
453
- look.lastColumn = (num & 256) !== 0;
454
- look.noHBand = (num & 512) !== 0;
455
- look.noVBand = (num & 1024) !== 0;
456
- }
457
- }
458
- const firstColumn = getAttribute(tblLook, "w", "firstColumn");
459
- if (firstColumn) look.firstColumn = parseOnOffValue(firstColumn) ?? false;
460
- const firstRow = getAttribute(tblLook, "w", "firstRow");
461
- if (firstRow) look.firstRow = parseOnOffValue(firstRow) ?? false;
462
- const lastColumn = getAttribute(tblLook, "w", "lastColumn");
463
- if (lastColumn) look.lastColumn = parseOnOffValue(lastColumn) ?? false;
464
- const lastRow = getAttribute(tblLook, "w", "lastRow");
465
- if (lastRow) look.lastRow = parseOnOffValue(lastRow) ?? false;
466
- const noHBand = getAttribute(tblLook, "w", "noHBand");
467
- if (noHBand) look.noHBand = parseOnOffValue(noHBand) ?? false;
468
- const noVBand = getAttribute(tblLook, "w", "noVBand");
469
- if (noVBand) look.noVBand = parseOnOffValue(noVBand) ?? false;
470
- return Object.keys(look).length > 0 ? look : void 0;
471
- }
472
- /**
473
399
  * Parse table formatting properties (w:tblPr)
474
400
  */
475
401
  function parseTableProperties(tblPr, _theme) {
@@ -522,7 +448,7 @@ function parseTableProperties(tblPr, _theme) {
522
448
  }
523
449
  const shd = findChild(tblPr, "w", "shd");
524
450
  if (shd) {
525
- const shadingResult = parseShadingProperties(shd);
451
+ const shadingResult = parseShading(shd);
526
452
  if (shadingResult) formatting.shading = shadingResult;
527
453
  }
528
454
  const bidiVisual = findChild(tblPr, "w", "bidiVisual");
@@ -578,7 +504,7 @@ function parseTableCellProperties(tcPr, _theme) {
578
504
  }
579
505
  const shd = findChild(tcPr, "w", "shd");
580
506
  if (shd) {
581
- const shadingResult = parseShadingProperties(shd);
507
+ const shadingResult = parseShading(shd);
582
508
  if (shadingResult) formatting.shading = shadingResult;
583
509
  }
584
510
  const vAlign = findChild(tcPr, "w", "vAlign");
@@ -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 };