@stll/folio-core 0.29.0 → 0.31.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 (103) hide show
  1. package/dist/controller/folioEditor.d.ts +28 -1
  2. package/dist/controller/folioEditor.js +37 -26
  3. package/dist/controller/fontReadiness.js +28 -24
  4. package/dist/controller/hiddenEditorManager.d.ts +2 -7
  5. package/dist/controller/layoutPipeline.js +33 -3
  6. package/dist/controller/noteEditorManager.d.ts +3 -6
  7. package/dist/docx/metafileSvg.d.ts +12 -0
  8. package/dist/docx/metafileSvg.js +462 -0
  9. package/dist/docx/paragraphTextBoxEnrichment.js +55 -4
  10. package/dist/docx/parser.d.ts +2 -2
  11. package/dist/docx/parser.js +26 -0
  12. package/dist/docx/runParser.js +2 -1
  13. package/dist/docx/serializer/runSerializer.js +14 -2
  14. package/dist/docx/server/createBilingualDocument.d.ts +20 -3
  15. package/dist/docx/server/createBilingualDocument.js +153 -22
  16. package/dist/docx/styleParser.js +2 -1
  17. package/dist/docx/textBoxParser.js +14 -0
  18. package/dist/docx/vmlImageParser.js +72 -152
  19. package/dist/docx/vmlPreview.d.ts +31 -0
  20. package/dist/docx/vmlPreview.js +535 -0
  21. package/dist/docx/wrapTypes.d.ts +2 -36
  22. package/dist/docx/wrapTypes.js +1 -39
  23. package/dist/fonts/fontAlternates.d.ts +8 -0
  24. package/dist/fonts/fontAlternates.js +16 -0
  25. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  26. package/dist/layout-bridge/convert/footnoteLayout.js +34 -3
  27. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  28. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -0
  29. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -0
  30. package/dist/layout-bridge/convert/toFlowBlocks.js +78 -28
  31. package/dist/layout-bridge/dom/noteStoryDom.d.ts +1 -1
  32. package/dist/layout-bridge/engine/selectionRects.js +3 -1
  33. package/dist/layout-engine/index.js +65 -32
  34. package/dist/layout-engine/justifiedLineFit.d.ts +7 -0
  35. package/dist/layout-engine/justifiedLineFit.js +6 -0
  36. package/dist/layout-engine/keep-together.js +15 -10
  37. package/dist/layout-engine/measure/complexScriptFormatting.d.ts +6 -1
  38. package/dist/layout-engine/measure/complexScriptFormatting.js +11 -2
  39. package/dist/layout-engine/measure/floatingTablePosition.d.ts +16 -1
  40. package/dist/layout-engine/measure/floatingTablePosition.js +29 -6
  41. package/dist/layout-engine/measure/lineBreakProvider.js +67 -8
  42. package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
  43. package/dist/layout-engine/measure/listMarkerWidth.js +23 -10
  44. package/dist/layout-engine/measure/measureBlocks.d.ts +15 -0
  45. package/dist/layout-engine/measure/measureBlocks.js +197 -30
  46. package/dist/layout-engine/measure/measureContainer.js +20 -24
  47. package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
  48. package/dist/layout-engine/measure/measureHelpers.js +14 -8
  49. package/dist/layout-engine/measure/measureParagraph.js +111 -37
  50. package/dist/layout-engine/measure/measureTypes.d.ts +3 -0
  51. package/dist/layout-engine/measure/tabCalculator.d.ts +123 -0
  52. package/dist/layout-engine/measure/tabCalculator.js +144 -0
  53. package/dist/layout-engine/measure/tableCellFlow.d.ts +21 -1
  54. package/dist/layout-engine/measure/tableCellFlow.js +45 -8
  55. package/dist/layout-engine/measure/tableInlinePlacement.d.ts +10 -2
  56. package/dist/layout-engine/measure/tableInlinePlacement.js +17 -15
  57. package/dist/layout-engine/paginator.d.ts +26 -2
  58. package/dist/layout-engine/paginator.js +76 -14
  59. package/dist/layout-engine/paragraphSpacing.d.ts +3 -1
  60. package/dist/layout-engine/paragraphSpacing.js +4 -3
  61. package/dist/layout-engine/renderedBreakReconciliation.d.ts +14 -3
  62. package/dist/layout-engine/renderedBreakReconciliation.js +45 -14
  63. package/dist/layout-engine/section-breaks.d.ts +3 -1
  64. package/dist/layout-engine/section-breaks.js +6 -2
  65. package/dist/layout-engine/types.d.ts +18 -1
  66. package/dist/layout-engine/types.js +1 -1
  67. package/dist/layout-painter/imageLayout.d.ts +1 -1
  68. package/dist/layout-painter/renderPage.js +6 -1
  69. package/dist/layout-painter/renderParagraph.js +169 -82
  70. package/dist/layout-painter/renderTable.d.ts +1 -1
  71. package/dist/layout-painter/renderTable.js +18 -7
  72. package/dist/layout-painter/renderTextBox.d.ts +1 -1
  73. package/dist/layout-painter/renderTextBox.js +6 -1
  74. package/dist/model.d.ts +3 -3
  75. package/dist/model.js +2 -2
  76. package/dist/paged-layout/sectionBlockWidths.d.ts +14 -0
  77. package/dist/paged-layout/sectionBlockWidths.js +103 -14
  78. package/dist/prosemirror/attrs/index.js +12 -1
  79. package/dist/prosemirror/conversion/fromProseDoc.js +6 -2
  80. package/dist/prosemirror/conversion/toProseDoc.js +10 -3
  81. package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +9 -5
  82. package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
  83. package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +6 -2
  84. package/dist/prosemirror/schema/nodes.d.ts +4 -0
  85. package/dist/prosemirror/utils/tabCalculator.d.ts +2 -123
  86. package/dist/prosemirror/utils/tabCalculator.js +1 -140
  87. package/dist/render-dom/RemoteSelectionOverlay.d.ts +4 -4
  88. package/dist/server.d.ts +2 -2
  89. package/dist/server.js +2 -2
  90. package/dist/types/documentEnumValues.d.ts +4 -1
  91. package/dist/types/documentEnumValues.js +12 -1
  92. package/dist/types/editor-story.d.ts +8 -0
  93. package/dist/types/editor-story.js +0 -0
  94. package/dist/types/remote-selection.d.ts +11 -0
  95. package/dist/types/remote-selection.js +0 -0
  96. package/dist/types/wrap.d.ts +36 -0
  97. package/dist/types/wrap.js +40 -0
  98. package/dist/utils/fontResolver.d.ts +1 -1
  99. package/dist/utils/fontResolver.js +42 -2
  100. package/dist/utils/formatToStyle.js +4 -2
  101. package/dist/utils/horizontalScale.d.ts +28 -0
  102. package/dist/utils/horizontalScale.js +42 -0
  103. package/package.json +2 -2
@@ -1,113 +1,71 @@
1
1
  import { sanitizeImageSrc } from "../utils/sanitizeImageSrc.js";
2
2
  import { pixelsToEmu } from "../utils/units.js";
3
3
  import { resolveImageData } from "./imageParser.js";
4
+ import { isValidVmlPreviewDimension, parseVmlNumber, parseVmlStyle, renderStandaloneVmlPreview, renderVmlGroupPreview, vmlCssLengthToPx, vmlSvgDataUrl } from "./vmlPreview.js";
4
5
  import { isWatermarkShape } from "./watermarkParser.js";
5
- import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, findDeep, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
6
+ import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
6
7
  //#region src/docx/vmlImageParser.ts
7
- const MAX_VML_PREVIEW_SHAPES = 256;
8
- const MAX_VML_PREVIEW_DIMENSION_PX = 2e4;
9
- const MAX_VML_SVG_CHARACTERS = 1e6;
10
- const SAFE_VML_COLORS = /* @__PURE__ */ new Set([
11
- "black",
12
- "white",
13
- "red",
14
- "green",
15
- "blue",
16
- "yellow",
17
- "gray",
18
- "grey",
19
- "silver",
20
- "maroon",
21
- "purple",
22
- "fuchsia",
23
- "lime",
24
- "olive",
25
- "navy",
26
- "teal",
27
- "aqua"
28
- ]);
29
- /**
30
- * Convert a CSS length (pt/in/px/cm/mm/pc, default px) to pixels. Units are
31
- * matched case-insensitively (`2IN`, `2Pt` are valid VML). The numeric part
32
- * must be a single well-formed decimal, so malformed input like `1.2.3` is
33
- * rejected rather than truncated to `1.2`.
34
- */
35
- function cssLengthToPx(raw) {
36
- if (!raw) return;
37
- const match = /^(?<amount>-?(?:\d+(?:\.\d+)?|\.\d+))\s*(?<unit>pt|in|px|cm|mm|pc)?$/iu.exec(raw.trim());
38
- const amountText = match?.groups?.["amount"];
39
- if (amountText === void 0) return;
40
- const value = Number.parseFloat(amountText);
41
- if (Number.isNaN(value)) return;
42
- switch (match?.groups?.["unit"]?.toLowerCase()) {
43
- case "pt": return value / 72 * 96;
44
- case "in": return value * 96;
45
- case "cm": return value / 2.54 * 96;
46
- case "mm": return value / 25.4 * 96;
47
- case "pc": return value / 6 * 96;
48
- case "px":
49
- case void 0: return value;
50
- default: return;
8
+ const VML_POSITION_ABSOLUTE = "absolute";
9
+ const IMAGE_WRAP_INLINE = "inline";
10
+ const IMAGE_WRAP_BEHIND = "behind";
11
+ const IMAGE_WRAP_IN_FRONT = "inFront";
12
+ const pixelsToSafeEmu = (pixels) => {
13
+ const emu = pixelsToEmu(pixels);
14
+ return Number.isSafeInteger(emu) ? emu : void 0;
15
+ };
16
+ const horizontalRelativeTo = (value) => {
17
+ switch (value?.toLowerCase()) {
18
+ case "char": return "character";
19
+ case "text": return "column";
20
+ case "margin": return "margin";
21
+ case "page": return "page";
22
+ case "left-margin-area": return "leftMargin";
23
+ case "right-margin-area": return "rightMargin";
24
+ case "inner-margin-area": return "insideMargin";
25
+ case "outer-margin-area": return "outsideMargin";
26
+ default: return "character";
51
27
  }
52
- }
53
- const PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set([
54
- "__proto__",
55
- "constructor",
56
- "prototype"
57
- ]);
58
- /** Read a `style="k1:v1;k2:v2"` attribute into a lowercased key/value record. */
59
- function parseStyleAttr(style) {
60
- const out = Object.create(null);
61
- if (!style) return out;
62
- for (const decl of style.split(";")) {
63
- const colon = decl.indexOf(":");
64
- if (colon < 0) continue;
65
- const key = decl.slice(0, colon).trim().toLowerCase();
66
- const value = decl.slice(colon + 1).trim();
67
- if (!key || PROTOTYPE_POLLUTION_KEYS.has(key)) continue;
68
- out[key] = value;
28
+ };
29
+ const verticalRelativeTo = (value) => {
30
+ switch (value?.toLowerCase()) {
31
+ case "line": return "line";
32
+ case "text": return "paragraph";
33
+ case "margin": return "margin";
34
+ case "page": return "page";
35
+ case "top-margin-area": return "topMargin";
36
+ case "bottom-margin-area": return "bottomMargin";
37
+ case "inner-margin-area": return "insideMargin";
38
+ case "outer-margin-area": return "outsideMargin";
39
+ default: return "paragraph";
69
40
  }
70
- return out;
71
- }
72
- const finiteNumber = (raw) => {
73
- if (!raw || !/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(raw.trim())) return;
74
- const value = Number.parseFloat(raw);
75
- return Number.isFinite(value) ? value : void 0;
76
41
  };
77
- const coordinatePair = (raw) => {
78
- const [firstRaw, secondRaw, extra] = raw?.split(",").map((part) => part.trim()) ?? [];
79
- if (extra !== void 0) return;
80
- const first = finiteNumber(firstRaw);
81
- const second = finiteNumber(secondRaw);
82
- return first === void 0 || second === void 0 ? void 0 : {
83
- first,
84
- second
42
+ const vmlImageLayout = (style) => {
43
+ if (style["position"]?.toLowerCase() !== VML_POSITION_ABSOLUTE) return { wrap: { type: IMAGE_WRAP_INLINE } };
44
+ const leftPx = vmlCssLengthToPx(style["margin-left"] ?? style["left"]) ?? 0;
45
+ const topPx = vmlCssLengthToPx(style["margin-top"] ?? style["top"]) ?? 0;
46
+ const zIndex = parseVmlNumber(style["z-index"]);
47
+ return {
48
+ wrap: { type: zIndex !== void 0 && zIndex < 0 ? IMAGE_WRAP_BEHIND : IMAGE_WRAP_IN_FRONT },
49
+ position: {
50
+ horizontal: {
51
+ relativeTo: horizontalRelativeTo(style["mso-position-horizontal-relative"]),
52
+ posOffset: pixelsToSafeEmu(leftPx) ?? 0
53
+ },
54
+ vertical: {
55
+ relativeTo: verticalRelativeTo(style["mso-position-vertical-relative"]),
56
+ posOffset: pixelsToSafeEmu(topPx) ?? 0
57
+ }
58
+ }
85
59
  };
86
60
  };
87
- const safeColor = (raw, fallback) => {
88
- const normalized = raw?.trim().toLowerCase();
89
- if (!normalized) return fallback;
90
- if (SAFE_VML_COLORS.has(normalized)) return normalized;
91
- if (/^#[0-9a-f]{3}(?:[0-9a-f]{3})?$/u.test(normalized)) return normalized;
92
- return /^[0-9a-f]{6}$/u.test(normalized) ? `#${normalized}` : fallback;
93
- };
94
- const validPreviewDimension = (value) => value !== void 0 && value > 0 && value <= MAX_VML_PREVIEW_DIMENSION_PX;
95
- const svgDataUrl = (svg) => svg.length <= MAX_VML_SVG_CHARACTERS ? `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}` : void 0;
96
- const vmlShapeSvg = (shape, width, height, x = 0, y = 0) => {
97
- const fill = safeColor(getAttribute(shape, null, "fillcolor"), "white");
98
- const stroke = getAttribute(shape, null, "stroked")?.toLowerCase() !== "f" ? safeColor(getAttribute(shape, null, "strokecolor"), "black") : "none";
99
- const localName = getLocalName(shape.name ?? "");
100
- if (localName === "oval") return `<ellipse cx="${x + width / 2}" cy="${y + height / 2}" rx="${width / 2}" ry="${height / 2}" fill="${fill}" stroke="${stroke}"/>`;
101
- return `<rect x="${x}" y="${y}" width="${width}" height="${height}" rx="${localName === "roundrect" ? Math.min(width, height) * .1 : 0}" fill="${fill}" stroke="${stroke}"/>`;
102
- };
103
61
  const previewImage = (pictElement, svg, widthPx, heightPx, style, rootXmlns) => {
104
- const src = svgDataUrl(svg);
62
+ const src = vmlSvgDataUrl(svg);
105
63
  if (!src) return null;
106
- const leftPx = cssLengthToPx(style["margin-left"] ?? style["left"]) ?? 0;
107
- const topPx = cssLengthToPx(style["margin-top"] ?? style["top"]) ?? 0;
64
+ const leftPx = vmlCssLengthToPx(style["margin-left"] ?? style["left"]) ?? 0;
65
+ const topPx = vmlCssLengthToPx(style["margin-top"] ?? style["top"]) ?? 0;
108
66
  const horizontalRelative = style["mso-position-horizontal-relative"] === "page";
109
67
  const verticalRelative = style["mso-position-vertical-relative"] === "page";
110
- const zIndex = finiteNumber(style["z-index"]);
68
+ const zIndex = parseVmlNumber(style["z-index"]);
111
69
  return {
112
70
  type: "drawing",
113
71
  image: {
@@ -124,62 +82,24 @@ const previewImage = (pictElement, svg, widthPx, heightPx, style, rootXmlns) =>
124
82
  position: {
125
83
  horizontal: {
126
84
  relativeTo: horizontalRelative ? "page" : "character",
127
- posOffset: pixelsToEmu(leftPx)
85
+ posOffset: pixelsToSafeEmu(leftPx) ?? 0
128
86
  },
129
87
  vertical: {
130
88
  relativeTo: verticalRelative ? "page" : "paragraph",
131
- posOffset: pixelsToEmu(topPx)
89
+ posOffset: pixelsToSafeEmu(topPx) ?? 0
132
90
  }
133
91
  }
134
92
  },
135
93
  rawXml: elementToXml(cloneWithXmlnsDeclarations(pictElement, rootXmlns))
136
94
  };
137
95
  };
138
- const parseStandaloneShapePreview = (pictElement, shape, rootXmlns) => {
139
- if (findDeep(shape, "v", "textbox")) return null;
140
- const style = parseStyleAttr(getAttribute(shape, null, "style"));
141
- const widthPx = cssLengthToPx(style["width"]);
142
- const heightPx = cssLengthToPx(style["height"]);
143
- if (!validPreviewDimension(widthPx) || !validPreviewDimension(heightPx)) return null;
144
- const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${widthPx} ${heightPx}" width="${widthPx}" height="${heightPx}">${vmlShapeSvg(shape, widthPx, heightPx)}</svg>`;
145
- return previewImage(pictElement, svg, widthPx, heightPx, style, rootXmlns);
146
- };
147
- const parseGroupPreview = (pictElement, group, rootXmlns) => {
148
- const style = parseStyleAttr(getAttribute(group, null, "style"));
149
- const widthPx = cssLengthToPx(style["width"]);
150
- const heightPx = cssLengthToPx(style["height"]);
151
- if (!validPreviewDimension(widthPx) || !validPreviewDimension(heightPx)) return null;
152
- const origin = coordinatePair(getAttribute(group, null, "coordorigin")) ?? {
153
- first: 0,
154
- second: 0
155
- };
156
- const size = coordinatePair(getAttribute(group, null, "coordsize")) ?? {
157
- first: widthPx,
158
- second: heightPx
159
- };
160
- if (size.first <= 0 || size.second <= 0) return null;
161
- const content = getChildElements(group).slice(0, MAX_VML_PREVIEW_SHAPES).map((child) => {
162
- const localName = getLocalName(child.name ?? "");
163
- if (findDeep(child, "v", "textbox")) return "";
164
- if (localName === "line") {
165
- const from = coordinatePair(getAttribute(child, null, "from"));
166
- const to = coordinatePair(getAttribute(child, null, "to"));
167
- if (!from || !to) return "";
168
- const stroke = safeColor(getAttribute(child, null, "strokecolor"), "black");
169
- return `<line x1="${from.first}" y1="${from.second}" x2="${to.first}" y2="${to.second}" stroke="${stroke}"/>`;
170
- }
171
- if (localName !== "rect" && localName !== "roundrect" && localName !== "oval") return "";
172
- const childStyle = parseStyleAttr(getAttribute(child, null, "style"));
173
- const x = finiteNumber(childStyle["left"]);
174
- const y = finiteNumber(childStyle["top"]);
175
- const width = finiteNumber(childStyle["width"]);
176
- const height = finiteNumber(childStyle["height"]);
177
- if (x === void 0 || y === void 0 || width === void 0 || height === void 0) return "";
178
- return vmlShapeSvg(child, width, height, x, y);
179
- }).join("");
180
- if (!content) return null;
181
- 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>`;
182
- return previewImage(pictElement, svg, widthPx, heightPx, style, rootXmlns);
96
+ const previewDrawing = (pictElement, preview, rootXmlns) => {
97
+ switch (preview.type) {
98
+ case "rendered": return previewImage(pictElement, preview.svg, preview.widthPx, preview.heightPx, preview.style, rootXmlns);
99
+ case "empty":
100
+ case "invalid": return null;
101
+ default: return preview;
102
+ }
183
103
  };
184
104
  /**
185
105
  * Read the relationship id off a `v:imagedata` element. Word writes `r:id`;
@@ -212,18 +132,18 @@ function parseVmlImageContent(pictElement, rels, media, rootXmlns = {}) {
212
132
  if (!rId) continue;
213
133
  if (isWatermarkShape(shape)) continue;
214
134
  const { src, mimeType, filename } = resolveImageData(rId, rels ?? void 0, media ?? void 0);
215
- const shapeStyle = parseStyleAttr(getAttribute(shape, null, "style"));
216
- const widthPx = cssLengthToPx(shapeStyle["width"]);
217
- const heightPx = cssLengthToPx(shapeStyle["height"]);
218
- if (getLocalName(pictElement.name ?? "") === "object" && (widthPx !== void 0 && !validPreviewDimension(widthPx) || heightPx !== void 0 && !validPreviewDimension(heightPx))) continue;
135
+ const shapeStyle = parseVmlStyle(getAttribute(shape, null, "style"));
136
+ const widthPx = vmlCssLengthToPx(shapeStyle["width"]);
137
+ const heightPx = vmlCssLengthToPx(shapeStyle["height"]);
138
+ if (getLocalName(pictElement.name ?? "") === "object" && (widthPx !== void 0 && !isValidVmlPreviewDimension(widthPx) || heightPx !== void 0 && !isValidVmlPreviewDimension(heightPx))) continue;
219
139
  const image = {
220
140
  type: "image",
221
141
  rId,
222
142
  size: {
223
- width: widthPx != null ? pixelsToEmu(widthPx) : 0,
224
- height: heightPx != null ? pixelsToEmu(heightPx) : 0
143
+ width: widthPx != null ? pixelsToSafeEmu(widthPx) ?? 0 : 0,
144
+ height: heightPx != null ? pixelsToSafeEmu(heightPx) ?? 0 : 0
225
145
  },
226
- wrap: { type: "inline" }
146
+ ...vmlImageLayout(shapeStyle)
227
147
  };
228
148
  const safeSrc = sanitizeImageSrc(src);
229
149
  if (safeSrc) image.src = safeSrc;
@@ -240,12 +160,12 @@ function parseVmlImageContent(pictElement, rels, media, rootXmlns = {}) {
240
160
  for (const child of getChildElements(pictElement)) {
241
161
  const localName = getLocalName(child.name ?? "");
242
162
  if (localName === "group") {
243
- const preview = parseGroupPreview(pictElement, child, rootXmlns);
163
+ const preview = previewDrawing(pictElement, renderVmlGroupPreview(child), rootXmlns);
244
164
  if (preview) return preview;
245
165
  continue;
246
166
  }
247
167
  if (localName === "rect" || localName === "roundrect" || localName === "oval") {
248
- const preview = parseStandaloneShapePreview(pictElement, child, rootXmlns);
168
+ const preview = previewDrawing(pictElement, renderStandaloneVmlPreview(child), rootXmlns);
249
169
  if (preview) return preview;
250
170
  }
251
171
  }
@@ -0,0 +1,31 @@
1
+ import { XmlElement } from "./xmlParser.js";
2
+ //#region src/docx/vmlPreview.d.ts
3
+ type VmlPreviewResult = {
4
+ type: "rendered";
5
+ svg: string;
6
+ widthPx: number;
7
+ heightPx: number;
8
+ style: Record<string, string>;
9
+ } | {
10
+ type: "empty";
11
+ } | {
12
+ type: "invalid";
13
+ };
14
+ /** Parse a VML/CSS length into CSS pixels without accepting partial numbers. */
15
+ declare const vmlCssLengthToPx: (raw: string | undefined) => number | undefined;
16
+ /** Read a VML `style` attribute into a prototype-free lowercased record. */
17
+ declare const parseVmlStyle: (style: string | null) => Record<string, string>;
18
+ /** Parse a finite VML number without exponent or partial-number coercion. */
19
+ declare const parseVmlNumber: (raw: string | null | undefined) => number | undefined;
20
+ /** Check a physical preview dimension against the retained SVG layout bound. */
21
+ declare const isValidVmlPreviewDimension: (value: number | undefined) => value is number;
22
+ /** Encode a generated, already-sanitized SVG without exceeding its output cap. */
23
+ declare const vmlSvgDataUrl: (svg: string) => string | undefined;
24
+ /** Render a bounded standalone VML rectangle or oval preview. */
25
+ declare const renderStandaloneVmlPreview: (shape: XmlElement) => VmlPreviewResult;
26
+ /** Render a VML group through bounded, non-clipping local-coordinate transforms. */
27
+ declare const renderVmlGroupPreview: (group: XmlElement) => VmlPreviewResult;
28
+ /** Bound retained synthetic VML previews while preserving their raw replay nodes. */
29
+ declare const enforcePackageVmlPreviewBudget: (root: unknown, maxCharacters?: number) => void;
30
+ //#endregion
31
+ export { VmlPreviewResult, enforcePackageVmlPreviewBudget, isValidVmlPreviewDimension, parseVmlNumber, parseVmlStyle, renderStandaloneVmlPreview, renderVmlGroupPreview, vmlCssLengthToPx, vmlSvgDataUrl };