@stll/folio-core 0.7.0 → 0.8.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 (92) hide show
  1. package/dist/ai-edits/blockRange.d.ts +13 -2
  2. package/dist/ai-edits/blockRange.js +23 -2
  3. package/dist/ai-edits/index.d.ts +4 -2
  4. package/dist/ai-edits/index.js +3 -1
  5. package/dist/ai-edits/scoped-reading.d.ts +9 -0
  6. package/dist/ai-edits/scoped-reading.js +60 -0
  7. package/dist/ai-edits/snapshot.js +13 -4
  8. package/dist/ai-edits/types.d.ts +44 -2
  9. package/dist/compat/eigenpal.d.ts +5 -2
  10. package/dist/compat/eigenpal.js +4 -1
  11. package/dist/controller/fontReadiness.d.ts +29 -0
  12. package/dist/controller/fontReadiness.js +139 -0
  13. package/dist/controller/layoutPipeline.js +76 -9
  14. package/dist/docx/blockContentParser.js +51 -8
  15. package/dist/docx/capabilities.d.ts +41 -0
  16. package/dist/docx/capabilities.js +322 -0
  17. package/dist/docx/compatibility.d.ts +34 -2
  18. package/dist/docx/compatibility.js +128 -38
  19. package/dist/docx/conformance.d.ts +6 -0
  20. package/dist/docx/conformance.js +18 -0
  21. package/dist/docx/ensureParaIds.d.ts +29 -0
  22. package/dist/docx/ensureParaIds.js +423 -0
  23. package/dist/docx/numberingParser.js +1 -0
  24. package/dist/docx/paragraphParser.js +9 -0
  25. package/dist/docx/paragraphTextBoxEnrichment.js +141 -2
  26. package/dist/docx/parser.js +2 -0
  27. package/dist/docx/selectiveXmlPatch.d.ts +10 -1
  28. package/dist/docx/selectiveXmlPatch.js +1 -1
  29. package/dist/docx/serializer/paragraphSerializer.js +4 -0
  30. package/dist/docx/serializer/runSerializer.js +7 -2
  31. package/dist/docx/serializer/tableSerializer.js +4 -0
  32. package/dist/docx/tableParser.js +8 -0
  33. package/dist/docx/textBoxParser.js +6 -1
  34. package/dist/docx/vmlImageParser.js +145 -1
  35. package/dist/index.d.ts +5 -2
  36. package/dist/index.js +4 -1
  37. package/dist/layout-bridge/convert/headerFooterLayout.js +16 -2
  38. package/dist/layout-bridge/convert/paragraphFrames.d.ts +7 -0
  39. package/dist/layout-bridge/convert/paragraphFrames.js +136 -0
  40. package/dist/layout-bridge/convert/toFlowBlocks.js +42 -3
  41. package/dist/layout-bridge/engine/hitTest.js +2 -1
  42. package/dist/layout-bridge/engine/selectionRects.js +2 -1
  43. package/dist/layout-engine/headerFooterRefs.d.ts +7 -0
  44. package/dist/layout-engine/headerFooterRefs.js +40 -0
  45. package/dist/layout-engine/index.d.ts +3 -2
  46. package/dist/layout-engine/index.js +36 -82
  47. package/dist/layout-engine/measure/listMarkerWidth.d.ts +3 -1
  48. package/dist/layout-engine/measure/listMarkerWidth.js +23 -4
  49. package/dist/layout-engine/measure/measureBlocks.d.ts +3 -0
  50. package/dist/layout-engine/measure/measureBlocks.js +133 -51
  51. package/dist/layout-engine/measure/measureParagraph.js +13 -4
  52. package/dist/layout-engine/measure/tableCellGrid.d.ts +15 -0
  53. package/dist/layout-engine/measure/tableCellGrid.js +62 -0
  54. package/dist/layout-engine/measure/textBoxParagraphLayout.d.ts +18 -0
  55. package/dist/layout-engine/measure/textBoxParagraphLayout.js +32 -0
  56. package/dist/layout-engine/paginator.d.ts +2 -1
  57. package/dist/layout-engine/paginator.js +7 -6
  58. package/dist/layout-engine/paragraphFrame.d.ts +22 -0
  59. package/dist/layout-engine/paragraphFrame.js +17 -0
  60. package/dist/layout-engine/paragraphSequence.d.ts +7 -0
  61. package/dist/layout-engine/paragraphSequence.js +25 -0
  62. package/dist/layout-engine/paragraphSpacing.d.ts +17 -0
  63. package/dist/layout-engine/paragraphSpacing.js +30 -0
  64. package/dist/layout-engine/renderedBreakReconciliation.d.ts +58 -0
  65. package/dist/layout-engine/renderedBreakReconciliation.js +63 -0
  66. package/dist/layout-engine/types.d.ts +17 -8
  67. package/dist/layout-engine/types.js +15 -2
  68. package/dist/layout-painter/renderPage.js +2 -2
  69. package/dist/layout-painter/renderParagraph.js +6 -5
  70. package/dist/layout-painter/renderTable.js +42 -12
  71. package/dist/layout-painter/renderTextBox.js +17 -7
  72. package/dist/managers/DocumentLoaderManager.js +1 -1
  73. package/dist/paged-layout/sectionBlockWidths.d.ts +3 -0
  74. package/dist/paged-layout/sectionBlockWidths.js +9 -0
  75. package/dist/paged-layout/sectionGeometry.js +1 -1
  76. package/dist/prosemirror/attrs/index.js +11 -0
  77. package/dist/prosemirror/conversion/fromProseDoc.js +2 -0
  78. package/dist/prosemirror/conversion/toProseDoc.js +27 -23
  79. package/dist/prosemirror/extensions/core/ParagraphExtension.js +1 -0
  80. package/dist/prosemirror/extensions/features/ListExtension.js +1 -0
  81. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +68 -16
  82. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +2 -1
  83. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +7 -0
  84. package/dist/prosemirror/schema/nodes.d.ts +4 -2
  85. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  86. package/dist/server.d.ts +4 -2
  87. package/dist/server.js +3 -1
  88. package/dist/types/index.d.ts +2 -1
  89. package/dist/utils/createDocument.js +26 -18
  90. package/dist/utils/hexId.d.ts +8 -1
  91. package/dist/utils/hexId.js +11 -3
  92. package/package.json +1 -1
@@ -604,6 +604,7 @@ function computeListRendering(numPr, numbering) {
604
604
  if (markerFont) rendering.markerFontFamily = markerFont;
605
605
  if (level.rPr?.fontSize) rendering.markerFontSize = level.rPr.fontSize / 2;
606
606
  if (level.rPr?.allCaps) rendering.markerAllCaps = true;
607
+ if (level.lvlJc) rendering.markerAlignment = level.lvlJc;
607
608
  if (level.suffix) rendering.markerSuffix = level.suffix;
608
609
  if (instance?.abstractNumId !== void 0) rendering.abstractNumId = instance.abstractNumId;
609
610
  if (overrideForLevel?.startOverride !== void 0) rendering.startOverride = overrideForLevel.startOverride;
@@ -110,10 +110,18 @@ function parseTabStops(tabs) {
110
110
  function parseFrameProperties(framePr) {
111
111
  if (!framePr) return;
112
112
  const frame = {};
113
+ const dropCap = getAttribute(framePr, "w", "dropCap");
114
+ if (dropCap === "none" || dropCap === "drop" || dropCap === "margin") frame.dropCap = dropCap;
115
+ const lines = parseNumericAttribute(framePr, "w", "lines");
116
+ if (lines !== void 0) frame.lines = lines;
113
117
  const w = parseNumericAttribute(framePr, "w", "w");
114
118
  if (w !== void 0) frame.width = w;
115
119
  const h = parseNumericAttribute(framePr, "w", "h");
116
120
  if (h !== void 0) frame.height = h;
121
+ const hSpace = parseNumericAttribute(framePr, "w", "hSpace");
122
+ if (hSpace !== void 0) frame.hSpace = hSpace;
123
+ const vSpace = parseNumericAttribute(framePr, "w", "vSpace");
124
+ if (vSpace !== void 0) frame.vSpace = vSpace;
117
125
  const hAnchor = getAttribute(framePr, "w", "hAnchor");
118
126
  if (hAnchor === "text" || hAnchor === "margin" || hAnchor === "page") frame.hAnchor = hAnchor;
119
127
  const vAnchor = getAttribute(framePr, "w", "vAnchor");
@@ -974,6 +982,7 @@ function parseParagraph(node, styles, theme, numbering, rels = null, media = nul
974
982
  if (markerFont) listRendering.markerFontFamily = markerFont;
975
983
  if (level.rPr?.fontSize) listRendering.markerFontSize = level.rPr.fontSize / 2;
976
984
  if (level.rPr?.allCaps) listRendering.markerAllCaps = true;
985
+ if (level.lvlJc) listRendering.markerAlignment = level.lvlJc;
977
986
  if (level.suffix) listRendering.markerSuffix = level.suffix;
978
987
  let implicitChildLevelAdvances = 0;
979
988
  const foldedMarkerSuffix = [];
@@ -1,7 +1,77 @@
1
- import { findDeep, getChildElements, getLocalName } from "./xmlParser.js";
1
+ import { findDeep, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
2
+ import { pixelsToEmu } from "../utils/units.js";
2
3
  import { getTextBoxContentElement, isTextBoxDrawing, parseTextBox, parseTextBoxContent } from "./textBoxParser.js";
3
4
  import { parseParagraph } from "./paragraphParser.js";
4
5
  //#region src/docx/paragraphTextBoxEnrichment.ts
6
+ const VML_HORIZONTAL_RELATIVES = /* @__PURE__ */ new Set([
7
+ "character",
8
+ "column",
9
+ "insideMargin",
10
+ "leftMargin",
11
+ "margin",
12
+ "outsideMargin",
13
+ "page",
14
+ "rightMargin"
15
+ ]);
16
+ const VML_VERTICAL_RELATIVES = /* @__PURE__ */ new Set([
17
+ "insideMargin",
18
+ "line",
19
+ "margin",
20
+ "outsideMargin",
21
+ "page",
22
+ "paragraph",
23
+ "topMargin",
24
+ "bottomMargin"
25
+ ]);
26
+ const parseVmlStyle = (value) => {
27
+ const declarations = {};
28
+ for (const declaration of value?.split(";") ?? []) {
29
+ const separator = declaration.indexOf(":");
30
+ if (separator < 0) continue;
31
+ const key = declaration.slice(0, separator).trim().toLowerCase();
32
+ if (key) declarations[key] = declaration.slice(separator + 1).trim();
33
+ }
34
+ return declarations;
35
+ };
36
+ const vmlLengthToPixels = (value) => {
37
+ const match = /^(?<amount>-?(?:\d+(?:\.\d+)?|\.\d+))\s*(?<unit>pt|in|px|cm|mm|pc)?$/iu.exec(value?.trim() ?? "");
38
+ const amount = Number.parseFloat(match?.groups?.["amount"] ?? "");
39
+ if (!Number.isFinite(amount)) return;
40
+ switch (match?.groups?.["unit"]?.toLowerCase()) {
41
+ case "pt": return amount / 72 * 96;
42
+ case "in": return amount * 96;
43
+ case "cm": return amount / 2.54 * 96;
44
+ case "mm": return amount / 25.4 * 96;
45
+ case "pc": return amount * 16;
46
+ case "px":
47
+ case void 0: return amount;
48
+ default: return;
49
+ }
50
+ };
51
+ const horizontalRelativeTo = (value) => {
52
+ for (const relative of VML_HORIZONTAL_RELATIVES) if (relative.toLowerCase() === value?.toLowerCase()) return relative;
53
+ return "character";
54
+ };
55
+ const verticalRelativeTo = (value) => {
56
+ for (const relative of VML_VERTICAL_RELATIVES) if (relative.toLowerCase() === value?.toLowerCase()) return relative;
57
+ return "paragraph";
58
+ };
59
+ const parseVmlInsets = (textBoxEl) => {
60
+ const [left, top, right, bottom, extra] = getAttribute(textBoxEl, null, "inset")?.split(",").map((value) => vmlLengthToPixels(value)) ?? [];
61
+ if (extra !== void 0 || left === void 0 || top === void 0 || right === void 0 || bottom === void 0) return;
62
+ return {
63
+ left: pixelsToEmu(left),
64
+ top: pixelsToEmu(top),
65
+ right: pixelsToEmu(right),
66
+ bottom: pixelsToEmu(bottom)
67
+ };
68
+ };
69
+ const parseVmlFill = (shapeEl) => getAttribute(shapeEl, null, "filled")?.toLowerCase() === "f" ? { type: "none" } : void 0;
70
+ const vmlWrapType = (positioned, zIndex) => {
71
+ if (!positioned) return "inline";
72
+ if (Number.isFinite(zIndex) && zIndex < 0) return "behind";
73
+ return "inFront";
74
+ };
5
75
  const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering, rels, media) => {
6
76
  const xmlChildren = getChildElements(paraXml);
7
77
  let parsedIndex = 0;
@@ -11,7 +81,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
11
81
  if (parsedIndex < paragraph.content.length && paragraph.content[parsedIndex]?.type !== "run") parsedIndex += 1;
12
82
  continue;
13
83
  }
14
- const { textBoxDrawings, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
84
+ const { textBoxDrawings, vmlTextBoxes, hasNonTextBoxContent } = scanRunForTextBoxDrawings(xmlChild);
15
85
  const parsedContent = paragraph.content[parsedIndex];
16
86
  const parsedRun = parsedContent?.type === "run" ? parsedContent : void 0;
17
87
  const targetRun = parsedRun ?? (hasNonTextBoxContent ? lastConsumedRun : void 0);
@@ -33,6 +103,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
33
103
  ...textBox.outline !== void 0 ? { outline: textBox.outline } : {},
34
104
  textBody: {
35
105
  content: textBox.content,
106
+ ...textBox.autoFit !== void 0 ? { autoFit: textBox.autoFit } : {},
36
107
  ...textBox.margins !== void 0 ? { margins: textBox.margins } : {}
37
108
  }
38
109
  };
@@ -52,6 +123,24 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
52
123
  parsedIndex += 1;
53
124
  }
54
125
  }
126
+ for (const pictEl of vmlTextBoxes) {
127
+ const shape = parseVmlTextBoxShape(pictEl, styles, theme, numbering, rels, media);
128
+ if (!shape) continue;
129
+ const shapeContent = {
130
+ type: "shape",
131
+ shape
132
+ };
133
+ if (targetRun && hasNonTextBoxContent) targetRun.content.push(shapeContent);
134
+ else {
135
+ const newRun = {
136
+ type: "run",
137
+ content: [shapeContent]
138
+ };
139
+ paragraph.content.splice(parsedIndex, 0, newRun);
140
+ lastConsumedRun = newRun;
141
+ parsedIndex += 1;
142
+ }
143
+ }
55
144
  if (hasNonTextBoxContent && parsedRun) {
56
145
  lastConsumedRun = parsedRun;
57
146
  parsedIndex += 1;
@@ -60,6 +149,7 @@ const enrichParagraphTextBoxes = (paragraph, paraXml, styles, theme, numbering,
60
149
  };
61
150
  const scanRunForTextBoxDrawings = (xmlRun) => {
62
151
  const textBoxDrawings = [];
152
+ const vmlTextBoxes = [];
63
153
  let hasNonTextBoxContent = false;
64
154
  const visitDrawing = (drawingEl) => {
65
155
  if (isTextBoxDrawing(drawingEl)) {
@@ -75,6 +165,11 @@ const scanRunForTextBoxDrawings = (xmlRun) => {
75
165
  visitDrawing(el);
76
166
  continue;
77
167
  }
168
+ if (name === "pict") {
169
+ if (findDeep(el, "v", "textbox")) vmlTextBoxes.push(el);
170
+ else hasNonTextBoxContent = true;
171
+ continue;
172
+ }
78
173
  if (name === "AlternateContent") {
79
174
  const branches = getChildElements(el);
80
175
  const choice = branches.find((branch) => getLocalName(branch.name ?? "") === "Choice");
@@ -97,8 +192,52 @@ const scanRunForTextBoxDrawings = (xmlRun) => {
97
192
  }
98
193
  return {
99
194
  textBoxDrawings,
195
+ vmlTextBoxes,
100
196
  hasNonTextBoxContent
101
197
  };
102
198
  };
199
+ const parseVmlTextBoxShape = (pictEl, styles, theme, numbering, rels, media) => {
200
+ const shapeEl = findDeep(pictEl, "v", "shape");
201
+ const textBoxEl = shapeEl ? findDeep(shapeEl, "v", "textbox") : null;
202
+ const contentEl = textBoxEl ? findDeep(textBoxEl, "w", "txbxContent") : null;
203
+ if (!shapeEl || !textBoxEl || !contentEl) return null;
204
+ const style = parseVmlStyle(getAttribute(shapeEl, null, "style"));
205
+ const width = vmlLengthToPixels(style["width"]);
206
+ const height = vmlLengthToPixels(style["height"]);
207
+ if (width === void 0 || height === void 0 || width <= 0 || height <= 0) return null;
208
+ const left = vmlLengthToPixels(style["margin-left"] ?? style["left"]);
209
+ const top = vmlLengthToPixels(style["margin-top"] ?? style["top"]);
210
+ const positioned = style["position"]?.toLowerCase() === "absolute";
211
+ const zIndex = Number.parseInt(style["z-index"] ?? "", 10);
212
+ const margins = parseVmlInsets(textBoxEl);
213
+ const fill = parseVmlFill(shapeEl);
214
+ const shape = {
215
+ type: "shape",
216
+ shapeType: "textBox",
217
+ size: {
218
+ width: pixelsToEmu(width),
219
+ height: pixelsToEmu(height)
220
+ },
221
+ ...fill === void 0 ? {} : { fill },
222
+ wrap: { type: vmlWrapType(positioned, zIndex) },
223
+ textBody: {
224
+ content: parseTextBoxContent(contentEl, parseParagraph, null, styles, theme, numbering, rels ?? void 0, media ?? void 0),
225
+ ...margins === void 0 ? {} : { margins }
226
+ }
227
+ };
228
+ const id = getAttribute(shapeEl, null, "id");
229
+ if (id) shape.id = id;
230
+ if (positioned) shape.position = {
231
+ horizontal: {
232
+ relativeTo: horizontalRelativeTo(style["mso-position-horizontal-relative"]),
233
+ ...left === void 0 ? {} : { posOffset: pixelsToEmu(left) }
234
+ },
235
+ vertical: {
236
+ relativeTo: verticalRelativeTo(style["mso-position-vertical-relative"]),
237
+ ...top === void 0 ? {} : { posOffset: pixelsToEmu(top) }
238
+ }
239
+ };
240
+ return shape;
241
+ };
103
242
  //#endregion
104
243
  export { enrichParagraphTextBoxes };
@@ -11,6 +11,7 @@ import { toArrayBuffer } from "../utils/docxInput.js";
11
11
  import { loadFontsWithMapping } from "../utils/fontLoader.js";
12
12
  import { convertTiffToPngDataUrl, isTiffMimeType } from "../utils/tiffConverter.js";
13
13
  import { normalizeCommentReferences } from "./commentReferenceNormalization.js";
14
+ import { detectDocxConformanceClass } from "./conformance.js";
14
15
  import { extractAllTemplateVariables, parseDocumentBody } from "./documentParser.js";
15
16
  import { normalizeHeaderFooterReferences } from "./headerFooterReferenceNormalization.js";
16
17
  import { extractMetafileRaster, isMetafileMimeType } from "./metafileRaster.js";
@@ -167,6 +168,7 @@ async function parseDocx(input, options = {}) {
167
168
  onProgress("Assembling document...", 95);
168
169
  const document = {
169
170
  package: {
171
+ conformanceClass: detectDocxConformanceClass(raw.documentXml),
170
172
  document: documentBody,
171
173
  settings,
172
174
  ...styleDefinitions !== void 0 ? { styles: styleDefinitions } : {},
@@ -6,6 +6,15 @@
6
6
  * unchanged content byte-for-byte. Uses string offset tracking
7
7
  * with proper tag depth counting (not regex) to handle nested elements.
8
8
  */
9
+ /**
10
+ * Whether `char` ends an element's tag name in XML — a whitespace separator
11
+ * (space, tab, CR, or LF, all valid before attributes per XML 1.0 §3.1), the
12
+ * tag close `>`, or a self-close `/`. Manual tag scanners must accept every
13
+ * whitespace form, not just a literal space, so newline-formatted markup
14
+ * (`<w:p\n w14:paraId="…">`) is still recognized as the element rather than
15
+ * mistaken for a longer-named sibling.
16
+ */
17
+ declare function isXmlNameBoundary(char: string | undefined): boolean;
9
18
  /**
10
19
  * Find the exact string start and end offsets of a <w:p> element
11
20
  * identified by its w14:paraId attribute.
@@ -100,4 +109,4 @@ declare function collectChangedNumberingDefs(baselineXml: string, currentXml: st
100
109
  */
101
110
  declare function buildPatchedNumberingXml(originalXml: string, currentXml: string, changed: ChangedNumberingDefs): string | null;
102
111
  //#endregion
103
- export { ChangedNumberingDefs, PatchSafetyOptions, PatchValidationResult, buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, validatePatchSafety };
112
+ export { ChangedNumberingDefs, PatchSafetyOptions, PatchValidationResult, buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, validatePatchSafety };
@@ -484,4 +484,4 @@ function escapeRegExp(str) {
484
484
  return str.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
485
485
  }
486
486
  //#endregion
487
- export { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, validatePatchSafety };
487
+ export { buildPatchedDocumentXml, buildPatchedNoteXml, buildPatchedNumberingXml, collectChangedNumberingDefs, collectParaIds, countParagraphElements, extractParagraphXml, findParagraphOffsets, isXmlNameBoundary, validatePatchSafety };
@@ -112,8 +112,12 @@ function serializeNumbering(numPr) {
112
112
  function serializeFrameProperties(frame) {
113
113
  if (!frame) return "";
114
114
  const attrs = [];
115
+ if (frame.dropCap) attrs.push(`w:dropCap="${frame.dropCap}"`);
116
+ if (frame.lines !== void 0) attrs.push(`w:lines="${intAttr(frame.lines)}"`);
115
117
  if (frame.width !== void 0) attrs.push(`w:w="${intAttr(frame.width)}"`);
116
118
  if (frame.height !== void 0) attrs.push(`w:h="${intAttr(frame.height)}"`);
119
+ if (frame.hSpace !== void 0) attrs.push(`w:hSpace="${intAttr(frame.hSpace)}"`);
120
+ if (frame.vSpace !== void 0) attrs.push(`w:vSpace="${intAttr(frame.vSpace)}"`);
117
121
  if (frame.hAnchor) attrs.push(`w:hAnchor="${frame.hAnchor}"`);
118
122
  if (frame.vAnchor) attrs.push(`w:vAnchor="${frame.vAnchor}"`);
119
123
  if (frame.x !== void 0) attrs.push(`w:x="${frame.x}"`);
@@ -456,13 +456,18 @@ function serializeShapeContent(content) {
456
456
  if (tb.margins.right != null) bpAttrs.push(`rIns="${intAttr(tb.margins.right)}"`);
457
457
  if (tb.margins.bottom != null) bpAttrs.push(`bIns="${intAttr(tb.margins.bottom)}"`);
458
458
  }
459
+ let autoFitXml = "";
460
+ if (tb.autoFit === "shape") autoFitXml = "<a:spAutoFit/>";
461
+ else if (tb.autoFit === "normal") autoFitXml = "<a:normAutofit/>";
462
+ else if (tb.autoFit === "none") autoFitXml = "<a:noAutofit/>";
463
+ const bodyPrXml = autoFitXml ? `<wps:bodyPr ${bpAttrs.join(" ")}>${autoFitXml}</wps:bodyPr>` : `<wps:bodyPr ${bpAttrs.join(" ")}/>`;
459
464
  if (isTextBox) textBody = [
460
465
  "<wps:txbx><w:txbxContent>",
461
466
  serializeShapeTextBody(tb.content),
462
467
  "</w:txbxContent></wps:txbx>",
463
- `<wps:bodyPr ${bpAttrs.join(" ")}/>`
468
+ bodyPrXml
464
469
  ].join("");
465
- else textBody = [`<wps:bodyPr ${bpAttrs.join(" ")}/>`].join("");
470
+ else textBody = bodyPrXml;
466
471
  }
467
472
  const graphic = [
468
473
  "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">",
@@ -172,6 +172,10 @@ function serializeTablePropertyChange(change) {
172
172
  function serializeTableRowFormatting(formatting, propertyChanges, structuralChange) {
173
173
  const parts = [];
174
174
  if (formatting) {
175
+ if (formatting.gridBefore) parts.push(`<w:gridBefore w:val="${intAttr(formatting.gridBefore)}"/>`);
176
+ if (formatting.widthBefore) parts.push(`<w:wBefore w:w="${intAttr(formatting.widthBefore.value)}" w:type="${formatting.widthBefore.type}"/>`);
177
+ if (formatting.gridAfter) parts.push(`<w:gridAfter w:val="${intAttr(formatting.gridAfter)}"/>`);
178
+ if (formatting.widthAfter) parts.push(`<w:wAfter w:w="${intAttr(formatting.widthAfter.value)}" w:type="${formatting.widthAfter.type}"/>`);
175
179
  if (formatting.cantSplit) parts.push("<w:cantSplit/>");
176
180
  if (formatting.header) parts.push("<w:tblHeader/>");
177
181
  if (formatting.height) {
@@ -353,6 +353,14 @@ function parseTableCellStructuralChange(tcPrElement) {
353
353
  function parseTableRowProperties(trPrElement) {
354
354
  if (!trPrElement) return;
355
355
  const formatting = {};
356
+ const gridBefore = parseNumericAttribute(findChild(trPrElement, "w", "gridBefore"), "w", "val");
357
+ if (gridBefore !== void 0 && gridBefore > 0) formatting.gridBefore = gridBefore;
358
+ const widthBefore = parseTableMeasurement(findChild(trPrElement, "w", "wBefore"));
359
+ if (widthBefore) formatting.widthBefore = widthBefore;
360
+ const gridAfter = parseNumericAttribute(findChild(trPrElement, "w", "gridAfter"), "w", "val");
361
+ if (gridAfter !== void 0 && gridAfter > 0) formatting.gridAfter = gridAfter;
362
+ const widthAfter = parseTableMeasurement(findChild(trPrElement, "w", "wAfter"));
363
+ if (widthAfter) formatting.widthAfter = widthAfter;
356
364
  const heightElement = findChild(trPrElement, "w", "trHeight");
357
365
  if (heightElement) {
358
366
  const heightVal = parseNumericAttribute(heightElement, "w", "val");
@@ -1,4 +1,4 @@
1
- import { findByFullName, findChildrenByLocalName, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
1
+ import { findByFullName, findChildByLocalName, findChildrenByLocalName, getAttribute, getChildElements, parseNumericAttribute } from "./xmlParser.js";
2
2
  import { emuToPixels } from "../utils/units.js";
3
3
  import { parseAnchorPosition, parseAnchorWrap, parseFill, parseOutline, resolveColorValueToHex } from "./drawingUtils.js";
4
4
  //#region src/docx/textBoxParser.ts
@@ -11,6 +11,9 @@ const DEFAULT_MARGIN_EMU = 91440;
11
11
  function parseBodyProperties(bodyPr) {
12
12
  if (!bodyPr) return {};
13
13
  const result = {};
14
+ if (findChildByLocalName(bodyPr, "spAutoFit")) result.autoFit = "shape";
15
+ else if (findChildByLocalName(bodyPr, "normAutofit")) result.autoFit = "normal";
16
+ else if (findChildByLocalName(bodyPr, "noAutofit")) result.autoFit = "none";
14
17
  const lIns = parseNumericAttribute(bodyPr, null, "lIns");
15
18
  const rIns = parseNumericAttribute(bodyPr, null, "rIns");
16
19
  const tIns = parseNumericAttribute(bodyPr, null, "tIns");
@@ -121,6 +124,7 @@ function parseTextBox(drawingEl) {
121
124
  if (fill) textBox.fill = fill;
122
125
  if (outline) textBox.outline = outline;
123
126
  if (bodyProps.margins) textBox.margins = bodyProps.margins;
127
+ if (bodyProps.autoFit) textBox.autoFit = bodyProps.autoFit;
124
128
  if (isAnchor) {
125
129
  const position = parseAnchorPosition(container);
126
130
  if (position) textBox.position = position;
@@ -162,6 +166,7 @@ function parseTextBoxFromShape(wsp, size, position, wrap) {
162
166
  if (fill) textBox.fill = fill;
163
167
  if (outline) textBox.outline = outline;
164
168
  if (bodyProps.margins) textBox.margins = bodyProps.margins;
169
+ if (bodyProps.autoFit) textBox.autoFit = bodyProps.autoFit;
165
170
  if (position) textBox.position = position;
166
171
  if (wrap) textBox.wrap = wrap;
167
172
  return textBox;
@@ -1,8 +1,30 @@
1
- import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, getAttribute } from "./xmlParser.js";
1
+ import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
2
2
  import { pixelsToEmu } from "../utils/units.js";
3
3
  import { resolveImageData } from "./imageParser.js";
4
4
  import { isWatermarkShape } from "./watermarkParser.js";
5
5
  //#region src/docx/vmlImageParser.ts
6
+ const MAX_VML_PREVIEW_SHAPES = 256;
7
+ const MAX_VML_PREVIEW_DIMENSION_PX = 2e4;
8
+ const MAX_VML_SVG_CHARACTERS = 1e6;
9
+ const SAFE_VML_COLORS = /* @__PURE__ */ new Set([
10
+ "black",
11
+ "white",
12
+ "red",
13
+ "green",
14
+ "blue",
15
+ "yellow",
16
+ "gray",
17
+ "grey",
18
+ "silver",
19
+ "maroon",
20
+ "purple",
21
+ "fuchsia",
22
+ "lime",
23
+ "olive",
24
+ "navy",
25
+ "teal",
26
+ "aqua"
27
+ ]);
6
28
  /**
7
29
  * Convert a CSS length (pt/in/px/cm/mm/pc, default px) to pixels. Units are
8
30
  * matched case-insensitively (`2IN`, `2Pt` are valid VML). The numeric part
@@ -40,6 +62,116 @@ function parseStyleAttr(style) {
40
62
  }
41
63
  return out;
42
64
  }
65
+ const finiteNumber = (raw) => {
66
+ if (!raw || !/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(raw.trim())) return;
67
+ const value = Number.parseFloat(raw);
68
+ return Number.isFinite(value) ? value : void 0;
69
+ };
70
+ const coordinatePair = (raw) => {
71
+ const [firstRaw, secondRaw, extra] = raw?.split(",").map((part) => part.trim()) ?? [];
72
+ if (extra !== void 0) return;
73
+ const first = finiteNumber(firstRaw);
74
+ const second = finiteNumber(secondRaw);
75
+ return first === void 0 || second === void 0 ? void 0 : {
76
+ first,
77
+ second
78
+ };
79
+ };
80
+ const safeColor = (raw, fallback) => {
81
+ const normalized = raw?.trim().toLowerCase();
82
+ if (!normalized) return fallback;
83
+ if (SAFE_VML_COLORS.has(normalized)) return normalized;
84
+ if (/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/u.test(normalized)) return normalized;
85
+ return /^[0-9a-f]{6}$/u.test(normalized) ? `#${normalized}` : fallback;
86
+ };
87
+ const validPreviewDimension = (value) => value !== void 0 && value > 0 && value <= MAX_VML_PREVIEW_DIMENSION_PX;
88
+ const svgDataUrl = (svg) => svg.length <= MAX_VML_SVG_CHARACTERS ? `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}` : void 0;
89
+ const vmlShapeSvg = (shape, width, height, x = 0, y = 0) => {
90
+ const fill = safeColor(getAttribute(shape, null, "fillcolor"), "white");
91
+ const stroke = getAttribute(shape, null, "stroked")?.toLowerCase() !== "f" ? safeColor(getAttribute(shape, null, "strokecolor"), "black") : "none";
92
+ const localName = getLocalName(shape.name ?? "");
93
+ if (localName === "oval") return `<ellipse cx="${x + width / 2}" cy="${y + height / 2}" rx="${width / 2}" ry="${height / 2}" fill="${fill}" stroke="${stroke}"/>`;
94
+ return `<rect x="${x}" y="${y}" width="${width}" height="${height}" rx="${localName === "roundrect" ? Math.min(width, height) * .1 : 0}" fill="${fill}" stroke="${stroke}"/>`;
95
+ };
96
+ const previewImage = (pictElement, svg, widthPx, heightPx, style, rootXmlns) => {
97
+ const src = svgDataUrl(svg);
98
+ if (!src) return null;
99
+ const leftPx = cssLengthToPx(style["margin-left"] ?? style["left"]) ?? 0;
100
+ const topPx = cssLengthToPx(style["margin-top"] ?? style["top"]) ?? 0;
101
+ const horizontalRelative = style["mso-position-horizontal-relative"] === "page";
102
+ const verticalRelative = style["mso-position-vertical-relative"] === "page";
103
+ const zIndex = finiteNumber(style["z-index"]);
104
+ return {
105
+ type: "drawing",
106
+ image: {
107
+ type: "image",
108
+ rId: "",
109
+ src,
110
+ mimeType: "image/svg+xml",
111
+ filename: "vml-shape-preview.svg",
112
+ size: {
113
+ width: pixelsToEmu(widthPx),
114
+ height: pixelsToEmu(heightPx)
115
+ },
116
+ wrap: { type: zIndex !== void 0 && zIndex >= 0 ? "inFront" : "behind" },
117
+ position: {
118
+ horizontal: {
119
+ relativeTo: horizontalRelative ? "page" : "character",
120
+ posOffset: pixelsToEmu(leftPx)
121
+ },
122
+ vertical: {
123
+ relativeTo: verticalRelative ? "page" : "paragraph",
124
+ posOffset: pixelsToEmu(topPx)
125
+ }
126
+ }
127
+ },
128
+ rawXml: elementToXml(cloneWithXmlnsDeclarations(pictElement, rootXmlns))
129
+ };
130
+ };
131
+ const parseStandaloneShapePreview = (pictElement, shape, rootXmlns) => {
132
+ const style = parseStyleAttr(getAttribute(shape, null, "style"));
133
+ const widthPx = cssLengthToPx(style["width"]);
134
+ const heightPx = cssLengthToPx(style["height"]);
135
+ if (!validPreviewDimension(widthPx) || !validPreviewDimension(heightPx)) return null;
136
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${widthPx} ${heightPx}" width="${widthPx}" height="${heightPx}">${vmlShapeSvg(shape, widthPx, heightPx)}</svg>`;
137
+ return previewImage(pictElement, svg, widthPx, heightPx, style, rootXmlns);
138
+ };
139
+ const parseGroupPreview = (pictElement, group, rootXmlns) => {
140
+ const style = parseStyleAttr(getAttribute(group, null, "style"));
141
+ const widthPx = cssLengthToPx(style["width"]);
142
+ const heightPx = cssLengthToPx(style["height"]);
143
+ if (!validPreviewDimension(widthPx) || !validPreviewDimension(heightPx)) return null;
144
+ const origin = coordinatePair(getAttribute(group, null, "coordorigin")) ?? {
145
+ first: 0,
146
+ second: 0
147
+ };
148
+ const size = coordinatePair(getAttribute(group, null, "coordsize")) ?? {
149
+ first: widthPx,
150
+ second: heightPx
151
+ };
152
+ if (size.first <= 0 || size.second <= 0) return null;
153
+ const content = getChildElements(group).slice(0, MAX_VML_PREVIEW_SHAPES).map((child) => {
154
+ const localName = getLocalName(child.name ?? "");
155
+ if (localName === "line") {
156
+ const from = coordinatePair(getAttribute(child, null, "from"));
157
+ const to = coordinatePair(getAttribute(child, null, "to"));
158
+ if (!from || !to) return "";
159
+ const stroke = safeColor(getAttribute(child, null, "strokecolor"), "black");
160
+ return `<line x1="${from.first}" y1="${from.second}" x2="${to.first}" y2="${to.second}" stroke="${stroke}"/>`;
161
+ }
162
+ if (localName !== "rect" && localName !== "roundrect" && localName !== "oval") return "";
163
+ const childStyle = parseStyleAttr(getAttribute(child, null, "style"));
164
+ const x = finiteNumber(childStyle["left"]);
165
+ const y = finiteNumber(childStyle["top"]);
166
+ const width = finiteNumber(childStyle["width"]);
167
+ const height = finiteNumber(childStyle["height"]);
168
+ if (x === void 0 || y === void 0 || width === void 0 || height === void 0) return "";
169
+ return vmlShapeSvg(child, width, height, x, y);
170
+ }).join("");
171
+ if (!content) return null;
172
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${origin.first} ${origin.second} ${size.first} ${size.second}" width="${widthPx}" height="${heightPx}">${content}</svg>`;
173
+ return previewImage(pictElement, svg, widthPx, heightPx, style, rootXmlns);
174
+ };
43
175
  /**
44
176
  * Read the relationship id off a `v:imagedata` element. Word writes `r:id`;
45
177
  * some legacy / third-party generators use `r:embed` or the office-namespace
@@ -94,6 +226,18 @@ function parseVmlImageContent(pictElement, rels, media, rootXmlns = {}) {
94
226
  rawXml: elementToXml(cloneWithXmlnsDeclarations(pictElement, rootXmlns))
95
227
  };
96
228
  }
229
+ for (const child of getChildElements(pictElement)) {
230
+ const localName = getLocalName(child.name ?? "");
231
+ if (localName === "group") {
232
+ const preview = parseGroupPreview(pictElement, child, rootXmlns);
233
+ if (preview) return preview;
234
+ continue;
235
+ }
236
+ if (localName === "rect" || localName === "roundrect" || localName === "oval") {
237
+ const preview = parseStandaloneShapePreview(pictElement, child, rootXmlns);
238
+ if (preview) return preview;
239
+ }
240
+ }
97
241
  return null;
98
242
  }
99
243
  //#endregion
package/dist/index.d.ts CHANGED
@@ -11,7 +11,8 @@ import { ResolvedAnchor, isSuggestionStale, resolveSuggestionAnchor } from "./ai
11
11
  import { PositionalText, buildPositionalText } from "./ai-suggestions/text-positions.js";
12
12
  import { CreateEmptyDocumentOptions, createEmptyDocument } from "./utils/createDocument.js";
13
13
  import { createDocx } from "./docx/rezip.js";
14
- import { DocxCompatibility } from "./docx/compatibility.js";
14
+ import { FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, FolioDocxCapabilityHost, FolioDocxCapabilityId, FolioDocxCapabilityManifest, FolioDocxCapabilityOperation, FolioDocxCompatibilityHost, FolioDocxCompatibilityProfile, FolioDocxFeatureCapability, FolioDocxProfile, FolioDocxSupportState, InvalidFolioDocxCapabilityIdError, getFolioDocxCapability, isFolioDocxCapabilityId } from "./docx/capabilities.js";
15
+ import { DocxCompatibility, DocxCompatibilityContext, DocxCompatibilityIssue, DocxCompatibilityLocation, DocxCompatibilityPart, InspectDocxCompatibilityOptions, inspectDocxCompatibility } from "./docx/compatibility.js";
15
16
  import { setAISuggestionsMeta, setFocusedSuggestionMeta } from "./prosemirror/plugins/aiSuggestionDecorations.js";
16
17
  import { scrollFolioPositionIntoView } from "./paged-layout/scrollToPmPosition.js";
17
18
  import { getFolioCaretViewportRect, getFolioSelectionViewportRect } from "./paged-layout/selectionViewportRect.js";
@@ -26,5 +27,7 @@ import { fromMarkdown } from "./markdown/fromMarkdown.js";
26
27
  import { toMarkdown, toMarkdownResult } from "./markdown/index.js";
27
28
  import { EmbeddedFont, EmbeddedFontParts, extractEmbeddedFonts, getEmbeddedFontFaces } from "./fonts/embeddedFonts.js";
28
29
  import { getGoogleFontsEnabled, setGoogleFontsEnabled } from "./utils/fontResolver.js";
30
+ import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
29
31
  type Document = document_d_exports.Document;
30
- export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocxCompatibility, type EmbeddedFont, type EmbeddedFontParts, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type ImageMeta, type ImageRef, InvalidFolioDocumentOperationBatchError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
32
+ type DocxConformanceClass = document_d_exports.DocxConformanceClass;
33
+ export { type AIBarStatus, type AIChatMode, type AICitation, type AICitationRange, type AICitationSource, type AIGenerateInput, type AISuggestion, type AISuggestionApplyMode, type AISuggestionPreset, type AISuggestionSeverity, type AISuggestionStatus, type AcceptAutocompleteResult, type AnonymizationMatch, type AnonymizationTerm, type ApplyFolioDocumentOperationsOptions, type ApplyResult, type AutocompleteSuggestionPluginOptions, type AutocompleteSuggestionState, type AutocompleteSuggestionStatus, type AutocompleteTriggerCheck, type AutocompleteTriggerOptions, type AutocompleteTriggerSkipReason, type CreateEmptyDocumentOptions, DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCX_CONFORMANCE_CLASSES, type DeriveBlockIdInput, type DirectiveKind, type DirectiveRange, type Document, type DocxCompatibility, type DocxCompatibilityContext, type DocxCompatibilityIssue, type DocxCompatibilityLocation, type DocxCompatibilityPart, type DocxConformanceClass, type EmbeddedFont, type EmbeddedFontParts, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, type FolioAIBlock, type FolioAIBlockAnchor, type FolioAIBlockKind, type FolioAIBlockPreviewRun, type FolioAIComment, type FolioAIEditAppliedOperation, type FolioAIEditApplyMode, type FolioAIEditApplyResult, type FolioAIEditOperation, type FolioAIEditPrecondition, type FolioAIEditReviewMeta, type FolioAIEditSeverity, type FolioAIEditSkipReason, type FolioAIEditSkippedOperation, type FolioAIEditSnapshot, type FolioAISignatureParty, type FolioBlockId, type FolioDocumentOperation, type FolioDocumentOperationAffectedTarget, type FolioDocumentOperationBatch, type FolioDocumentOperationCapabilities, type FolioDocumentOperationIssue, type FolioDocumentOperationMode, type FolioDocumentOperationPrecondition, type FolioDocumentOperationReceipt, type FolioDocumentOperationRecovery, type FolioDocumentOperationResult, type FolioDocumentOperationStatus, type FolioDocumentOperationType, type FolioDocumentOperationUndoFailureReason, type FolioDocumentOperationUndoHandle, type FolioDocumentOperationUndoResult, type FolioDocxCapabilityHost, type FolioDocxCapabilityId, type FolioDocxCapabilityManifest, type FolioDocxCapabilityOperation, type FolioDocxCompatibilityHost, type FolioDocxCompatibilityProfile, type FolioDocxFeatureCapability, type FolioDocxProfile, type FolioDocxSupportState, type ImageMeta, type ImageRef, type InspectDocxCompatibilityOptions, InvalidFolioDocumentOperationBatchError, InvalidFolioDocxCapabilityIdError, type MarkdownOptions, type MarkdownResult, type PositionalText, type ResolvedAnchor, type TemplatePreviewSpan, type TemplatePreviewValue, type TemplatePreviewValues, type TemplateSlashMenuKeyAction, type TemplateSlashMenuState, UnsupportedFolioDocumentOperationVersionError, type WordDiffSegment, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocxCapability, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocxCompatibility, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocxCapabilityId, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
package/dist/index.js CHANGED
@@ -5,6 +5,8 @@ import { applyFolioAIEditOperations } from "./ai-edits/apply.js";
5
5
  import { FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, applyFolioDocumentOperations, assertSupportedFolioDocumentOperationVersion, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, isFolioDocumentOperationModeSupported, isSupportedFolioDocumentOperationVersion, parseFolioDocumentOperationBatch } from "./document-operations.js";
6
6
  import { createEmptyDocument } from "./utils/createDocument.js";
7
7
  import { createDocx } from "./docx/rezip.js";
8
+ import { FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, InvalidFolioDocxCapabilityIdError, getFolioDocxCapability, isFolioDocxCapabilityId } from "./docx/capabilities.js";
9
+ import { inspectDocxCompatibility } from "./docx/compatibility.js";
8
10
  import { DEFAULT_AI_SUGGESTION_PRESETS } from "./ai-suggestions/types.js";
9
11
  import { buildPositionalText } from "./ai-suggestions/text-positions.js";
10
12
  import { isSuggestionStale, resolveSuggestionAnchor } from "./ai-suggestions/conflict.js";
@@ -22,4 +24,5 @@ import { DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, acceptAutocompleteSuggestion, acc
22
24
  import { fromMarkdown } from "./markdown/fromMarkdown.js";
23
25
  import { toMarkdown, toMarkdownResult } from "./markdown/index.js";
24
26
  import { extractEmbeddedFonts, getEmbeddedFontFaces } from "./fonts/embeddedFonts.js";
25
- export { DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, InvalidFolioDocumentOperationBatchError, UnsupportedFolioDocumentOperationVersionError, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, isFolioBlockId, isFolioDocumentOperationModeSupported, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };
27
+ import { DOCX_CONFORMANCE_CLASSES } from "@stll/docx-core/model";
28
+ export { DEFAULT_AI_SUGGESTION_PRESETS, DEFAULT_AUTOCOMPLETE_DEAD_ZONE_NODES, DOCX_CONFORMANCE_CLASSES, FOLIO_DOCUMENT_OPERATION_BATCH_MODES, FOLIO_DOCUMENT_OPERATION_CONTRACT_VERSION, FOLIO_DOCUMENT_OPERATION_MODES, FOLIO_DOCUMENT_OPERATION_MODES_BY_TYPE, FOLIO_DOCUMENT_OPERATION_PRECONDITIONS, FOLIO_DOCUMENT_OPERATION_STORIES, FOLIO_DOCUMENT_OPERATION_TYPES, FOLIO_DOCX_CAPABILITY_HOSTS, FOLIO_DOCX_CAPABILITY_IDS, FOLIO_DOCX_CAPABILITY_MANIFEST, FOLIO_DOCX_CAPABILITY_MANIFEST_VERSION, FOLIO_DOCX_CAPABILITY_OPERATIONS, FOLIO_DOCX_COMPATIBILITY_HOSTS, FOLIO_DOCX_COMPATIBILITY_PROFILES, FOLIO_DOCX_PROFILES, FOLIO_DOCX_SUPPORT_STATES, InvalidFolioDocumentOperationBatchError, InvalidFolioDocxCapabilityIdError, UnsupportedFolioDocumentOperationVersionError, acceptAutocompleteSuggestion, acceptAutocompleteWord, anonymizationDecorationsKey, appendAutocompleteToken, applyFolioAIEditOperations, applyFolioDocumentOperations, applySuggestions, assertSupportedFolioDocumentOperationVersion, autocompleteSuggestionKey, autocompleteSuggestionPlugin, buildPositionalText, clearAutocompleteSuggestion, clearTemplateSlashMenu, consumeTemplateSlashQuery, createAICitationDecorationsPlugin, createDocx, createEmptyDocument, createFolioAIEditSnapshot, deriveBlockId, diffWordSegments, extractEmbeddedFonts, finishAutocompleteSuggestion, fromMarkdown, getAnonymizationMatches, getAutocompleteSuggestion, getEmbeddedFontFaces, getFolioCaretViewportRect, getFolioDocumentOperationCapabilities, getFolioDocumentOperationIssues, getFolioDocumentOperationReceipts, getFolioDocxCapability, getFolioParaIdFromBlockId, getFolioSelectionViewportRect, getGoogleFontsEnabled, getTemplateDirectives, getTemplateSlashMenu, hashFolioAIBlockText, inspectDocxCompatibility, isFolioBlockId, isFolioDocumentOperationModeSupported, isFolioDocxCapabilityId, isSequentialFolioBlockId, isSuggestionStale, isSupportedFolioDocumentOperationVersion, normalizeFolioAIBlockText, parseFolioDocumentOperationBatch, resetTemplateSlashQuery, resolveSuggestionAnchor, scanDirectives, scrollFolioPositionIntoView, setAICitationsMeta, setAISuggestionsMeta, setActiveCitationMeta, setAnonymizationTermsMeta, setFocusedSuggestionMeta, setGoogleFontsEnabled, setTemplatePreviewValues, shouldTriggerAutocomplete, startAutocompleteSuggestion, templateSlashMenuKey, toMarkdown, toMarkdownResult };