@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.
- package/dist/controller/folioEditor.d.ts +28 -1
- package/dist/controller/folioEditor.js +37 -26
- package/dist/controller/fontReadiness.js +28 -24
- package/dist/controller/hiddenEditorManager.d.ts +2 -7
- package/dist/controller/layoutPipeline.js +33 -3
- package/dist/controller/noteEditorManager.d.ts +3 -6
- package/dist/docx/metafileSvg.d.ts +12 -0
- package/dist/docx/metafileSvg.js +462 -0
- package/dist/docx/paragraphTextBoxEnrichment.js +55 -4
- package/dist/docx/parser.d.ts +2 -2
- package/dist/docx/parser.js +26 -0
- package/dist/docx/runParser.js +2 -1
- package/dist/docx/serializer/runSerializer.js +14 -2
- package/dist/docx/server/createBilingualDocument.d.ts +20 -3
- package/dist/docx/server/createBilingualDocument.js +153 -22
- package/dist/docx/styleParser.js +2 -1
- package/dist/docx/textBoxParser.js +14 -0
- package/dist/docx/vmlImageParser.js +72 -152
- package/dist/docx/vmlPreview.d.ts +31 -0
- package/dist/docx/vmlPreview.js +535 -0
- package/dist/docx/wrapTypes.d.ts +2 -36
- package/dist/docx/wrapTypes.js +1 -39
- package/dist/fonts/fontAlternates.d.ts +8 -0
- package/dist/fonts/fontAlternates.js +16 -0
- package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/footnoteLayout.js +34 -3
- package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
- package/dist/layout-bridge/convert/headerFooterLayout.js +5 -0
- package/dist/layout-bridge/convert/toFlowBlocks.d.ts +3 -0
- package/dist/layout-bridge/convert/toFlowBlocks.js +78 -28
- package/dist/layout-bridge/dom/noteStoryDom.d.ts +1 -1
- package/dist/layout-bridge/engine/selectionRects.js +3 -1
- package/dist/layout-engine/index.js +65 -32
- package/dist/layout-engine/justifiedLineFit.d.ts +7 -0
- package/dist/layout-engine/justifiedLineFit.js +6 -0
- package/dist/layout-engine/keep-together.js +15 -10
- package/dist/layout-engine/measure/complexScriptFormatting.d.ts +6 -1
- package/dist/layout-engine/measure/complexScriptFormatting.js +11 -2
- package/dist/layout-engine/measure/floatingTablePosition.d.ts +16 -1
- package/dist/layout-engine/measure/floatingTablePosition.js +29 -6
- package/dist/layout-engine/measure/lineBreakProvider.js +67 -8
- package/dist/layout-engine/measure/listMarkerWidth.d.ts +1 -0
- package/dist/layout-engine/measure/listMarkerWidth.js +23 -10
- package/dist/layout-engine/measure/measureBlocks.d.ts +15 -0
- package/dist/layout-engine/measure/measureBlocks.js +197 -30
- package/dist/layout-engine/measure/measureContainer.js +20 -24
- package/dist/layout-engine/measure/measureHelpers.d.ts +1 -1
- package/dist/layout-engine/measure/measureHelpers.js +14 -8
- package/dist/layout-engine/measure/measureParagraph.js +111 -37
- package/dist/layout-engine/measure/measureTypes.d.ts +3 -0
- package/dist/layout-engine/measure/tabCalculator.d.ts +123 -0
- package/dist/layout-engine/measure/tabCalculator.js +144 -0
- package/dist/layout-engine/measure/tableCellFlow.d.ts +21 -1
- package/dist/layout-engine/measure/tableCellFlow.js +45 -8
- package/dist/layout-engine/measure/tableInlinePlacement.d.ts +10 -2
- package/dist/layout-engine/measure/tableInlinePlacement.js +17 -15
- package/dist/layout-engine/paginator.d.ts +26 -2
- package/dist/layout-engine/paginator.js +76 -14
- package/dist/layout-engine/paragraphSpacing.d.ts +3 -1
- package/dist/layout-engine/paragraphSpacing.js +4 -3
- package/dist/layout-engine/renderedBreakReconciliation.d.ts +14 -3
- package/dist/layout-engine/renderedBreakReconciliation.js +45 -14
- package/dist/layout-engine/section-breaks.d.ts +3 -1
- package/dist/layout-engine/section-breaks.js +6 -2
- package/dist/layout-engine/types.d.ts +18 -1
- package/dist/layout-engine/types.js +1 -1
- package/dist/layout-painter/imageLayout.d.ts +1 -1
- package/dist/layout-painter/renderPage.js +6 -1
- package/dist/layout-painter/renderParagraph.js +169 -82
- package/dist/layout-painter/renderTable.d.ts +1 -1
- package/dist/layout-painter/renderTable.js +18 -7
- package/dist/layout-painter/renderTextBox.d.ts +1 -1
- package/dist/layout-painter/renderTextBox.js +6 -1
- package/dist/model.d.ts +3 -3
- package/dist/model.js +2 -2
- package/dist/paged-layout/sectionBlockWidths.d.ts +14 -0
- package/dist/paged-layout/sectionBlockWidths.js +103 -14
- package/dist/prosemirror/attrs/index.js +12 -1
- package/dist/prosemirror/conversion/fromProseDoc.js +6 -2
- package/dist/prosemirror/conversion/toProseDoc.js +10 -3
- package/dist/prosemirror/extensions/marks/CharacterSpacingExtension.js +9 -5
- package/dist/prosemirror/extensions/nodes/TableExtension.js +2 -0
- package/dist/prosemirror/extensions/nodes/TextBoxExtension.js +6 -2
- package/dist/prosemirror/schema/nodes.d.ts +4 -0
- package/dist/prosemirror/utils/tabCalculator.d.ts +2 -123
- package/dist/prosemirror/utils/tabCalculator.js +1 -140
- package/dist/render-dom/RemoteSelectionOverlay.d.ts +4 -4
- package/dist/server.d.ts +2 -2
- package/dist/server.js +2 -2
- package/dist/types/documentEnumValues.d.ts +4 -1
- package/dist/types/documentEnumValues.js +12 -1
- package/dist/types/editor-story.d.ts +8 -0
- package/dist/types/editor-story.js +0 -0
- package/dist/types/remote-selection.d.ts +11 -0
- package/dist/types/remote-selection.js +0 -0
- package/dist/types/wrap.d.ts +36 -0
- package/dist/types/wrap.js +40 -0
- package/dist/utils/fontResolver.d.ts +1 -1
- package/dist/utils/fontResolver.js +42 -2
- package/dist/utils/formatToStyle.js +4 -2
- package/dist/utils/horizontalScale.d.ts +28 -0
- package/dist/utils/horizontalScale.js +42 -0
- 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,
|
|
6
|
+
import { cloneWithXmlnsDeclarations, elementToXml, findAllDeep, findChild, getAttribute, getChildElements, getLocalName } from "./xmlParser.js";
|
|
6
7
|
//#region src/docx/vmlImageParser.ts
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
return
|
|
83
|
-
|
|
84
|
-
|
|
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 =
|
|
62
|
+
const src = vmlSvgDataUrl(svg);
|
|
105
63
|
if (!src) return null;
|
|
106
|
-
const leftPx =
|
|
107
|
-
const topPx =
|
|
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 =
|
|
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:
|
|
85
|
+
posOffset: pixelsToSafeEmu(leftPx) ?? 0
|
|
128
86
|
},
|
|
129
87
|
vertical: {
|
|
130
88
|
relativeTo: verticalRelative ? "page" : "paragraph",
|
|
131
|
-
posOffset:
|
|
89
|
+
posOffset: pixelsToSafeEmu(topPx) ?? 0
|
|
132
90
|
}
|
|
133
91
|
}
|
|
134
92
|
},
|
|
135
93
|
rawXml: elementToXml(cloneWithXmlnsDeclarations(pictElement, rootXmlns))
|
|
136
94
|
};
|
|
137
95
|
};
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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 =
|
|
216
|
-
const widthPx =
|
|
217
|
-
const heightPx =
|
|
218
|
-
if (getLocalName(pictElement.name ?? "") === "object" && (widthPx !== void 0 && !
|
|
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 ?
|
|
224
|
-
height: heightPx != null ?
|
|
143
|
+
width: widthPx != null ? pixelsToSafeEmu(widthPx) ?? 0 : 0,
|
|
144
|
+
height: heightPx != null ? pixelsToSafeEmu(heightPx) ?? 0 : 0
|
|
225
145
|
},
|
|
226
|
-
|
|
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 =
|
|
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 =
|
|
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 };
|