@antv/infographic 0.2.18 → 0.2.19
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/infographic.min.js +68 -68
- package/dist/infographic.min.js.map +1 -1
- package/esm/exporter/svg.js +129 -49
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/lib/exporter/svg.js +129 -49
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/exporter/svg.ts +187 -59
- package/src/version.ts +1 -1
package/esm/exporter/svg.js
CHANGED
|
@@ -44,38 +44,69 @@ function parseAbsoluteLength(value) {
|
|
|
44
44
|
return Number.NaN;
|
|
45
45
|
return Number.parseFloat(trimmed);
|
|
46
46
|
}
|
|
47
|
-
function
|
|
47
|
+
function parseCoordinate(value) {
|
|
48
|
+
const parsed = parseAbsoluteLength(value);
|
|
49
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
50
|
+
}
|
|
51
|
+
function measureSpanContentDimensions(span, measureWidth) {
|
|
48
52
|
const prevHeight = span.style.height;
|
|
53
|
+
const prevWidth = span.style.width;
|
|
49
54
|
const prevOverflow = span.style.overflow;
|
|
50
55
|
try {
|
|
51
56
|
span.style.height = 'max-content';
|
|
52
57
|
span.style.overflow = 'hidden';
|
|
53
58
|
void span.offsetHeight; // force reflow
|
|
54
|
-
|
|
59
|
+
const scrollHeight = span.scrollHeight;
|
|
60
|
+
const rectHeight = span.getBoundingClientRect().height;
|
|
61
|
+
let width = span.scrollWidth;
|
|
62
|
+
if (measureWidth) {
|
|
63
|
+
span.style.width = 'max-content';
|
|
64
|
+
void span.offsetWidth; // force reflow
|
|
65
|
+
width = span.scrollWidth;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
height: Math.max(scrollHeight, rectHeight),
|
|
69
|
+
width,
|
|
70
|
+
};
|
|
55
71
|
}
|
|
56
72
|
finally {
|
|
57
73
|
span.style.height = prevHeight;
|
|
58
|
-
span.style.overflow = prevOverflow;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
function measureSpanContentWidth(span) {
|
|
62
|
-
const prevWidth = span.style.width;
|
|
63
|
-
const prevOverflow = span.style.overflow;
|
|
64
|
-
try {
|
|
65
|
-
span.style.width = 'max-content';
|
|
66
|
-
span.style.overflow = 'hidden';
|
|
67
|
-
void span.offsetWidth; // force reflow
|
|
68
|
-
return span.scrollWidth;
|
|
69
|
-
}
|
|
70
|
-
finally {
|
|
71
74
|
span.style.width = prevWidth;
|
|
72
75
|
span.style.overflow = prevOverflow;
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
|
-
|
|
78
|
+
function shouldKeepForeignObjectWidth(style) {
|
|
79
|
+
const whiteSpace = style.whiteSpace;
|
|
80
|
+
const flexWrap = style.flexWrap;
|
|
81
|
+
const wordBreak = style.wordBreak;
|
|
82
|
+
const overflowWrap = style.overflowWrap;
|
|
83
|
+
return (flexWrap === 'wrap' ||
|
|
84
|
+
flexWrap === 'wrap-reverse' ||
|
|
85
|
+
whiteSpace === 'pre-wrap' ||
|
|
86
|
+
whiteSpace === 'pre-line' ||
|
|
87
|
+
whiteSpace === 'normal' ||
|
|
88
|
+
overflowWrap === 'break-word' ||
|
|
89
|
+
wordBreak === 'break-word' ||
|
|
90
|
+
wordBreak === 'break-all');
|
|
91
|
+
}
|
|
92
|
+
function createCoordConverter(svg, element) {
|
|
93
|
+
if (typeof element.getScreenCTM !== 'function')
|
|
94
|
+
return null;
|
|
95
|
+
const screenCTM = element.getScreenCTM();
|
|
96
|
+
if (!screenCTM)
|
|
97
|
+
return null;
|
|
98
|
+
const inverseCTM = screenCTM.inverse();
|
|
99
|
+
return (clientX, clientY) => {
|
|
100
|
+
const pt = svg.createSVGPoint();
|
|
101
|
+
pt.x = clientX;
|
|
102
|
+
pt.y = clientY;
|
|
103
|
+
return pt.matrixTransform(inverseCTM);
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
// Returns [left, top, right, bottom] in target coordinates for a foreignObject,
|
|
76
107
|
// accounting for flex alignment: bottom/center-aligned content can overflow,
|
|
77
108
|
// and horizontally aligned content can overflow as well.
|
|
78
|
-
function getFOContentBoundsInSVG(fo,
|
|
109
|
+
function getFOContentBoundsInSVG(fo, toSVGCoord, { contentHeight, contentWidth, keepForeignObjectWidth, }) {
|
|
79
110
|
const foRect = fo.getBoundingClientRect();
|
|
80
111
|
const foTopLeft = toSVGCoord(foRect.left, foRect.top);
|
|
81
112
|
const foBottomRight = toSVGCoord(foRect.right, foRect.bottom);
|
|
@@ -87,16 +118,15 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
|
|
|
87
118
|
const foHeightSVG = foBottomSVG - foTopSVG;
|
|
88
119
|
const svgUnitsPerClientPxY = foRect.height > 0 ? foHeightSVG / foRect.height : 1;
|
|
89
120
|
const svgUnitsPerClientPxX = foRect.width > 0 ? foWidthSVG / foRect.width : 1;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const contentHeightSVG = realScrollHeight > 0
|
|
93
|
-
? realScrollHeight * svgUnitsPerClientPxY
|
|
121
|
+
const contentHeightSVG = contentHeight > 0
|
|
122
|
+
? contentHeight * svgUnitsPerClientPxY
|
|
94
123
|
: foHeightSVG;
|
|
95
|
-
const
|
|
96
|
-
const contentWidthSVG = realScrollWidth > 0 ? realScrollWidth * svgUnitsPerClientPxX : foWidthSVG;
|
|
97
|
-
const computedStyle = window.getComputedStyle(content);
|
|
124
|
+
const computedStyle = window.getComputedStyle(fo.firstElementChild);
|
|
98
125
|
const alignItems = computedStyle.alignItems;
|
|
99
126
|
const justifyContent = computedStyle.justifyContent;
|
|
127
|
+
const contentWidthSVG = keepForeignObjectWidth
|
|
128
|
+
? foWidthSVG
|
|
129
|
+
: Math.max(foWidthSVG, contentWidth * svgUnitsPerClientPxX);
|
|
100
130
|
// Calculate vertical bounds
|
|
101
131
|
let top, bottom;
|
|
102
132
|
if (alignItems === 'flex-end' || alignItems === 'end') {
|
|
@@ -131,38 +161,75 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
|
|
|
131
161
|
}
|
|
132
162
|
return [left, top, right, bottom];
|
|
133
163
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
164
|
+
function collectForeignObjectExportAdjustments(svg) {
|
|
165
|
+
const toSVGCoord = createCoordConverter(svg, svg);
|
|
166
|
+
if (!toSVGCoord)
|
|
167
|
+
return [];
|
|
168
|
+
return Array.from(svg.querySelectorAll('foreignObject')).map((fo) => {
|
|
169
|
+
const content = fo.firstElementChild;
|
|
170
|
+
if (!content)
|
|
171
|
+
return null;
|
|
172
|
+
const computedStyle = window.getComputedStyle(content);
|
|
173
|
+
const keepForeignObjectWidth = shouldKeepForeignObjectWidth(computedStyle);
|
|
174
|
+
const measuredContent = measureSpanContentDimensions(content, !keepForeignObjectWidth);
|
|
175
|
+
const parent = fo.parentElement instanceof SVGGraphicsElement ? fo.parentElement : svg;
|
|
176
|
+
const toParentCoord = createCoordConverter(svg, parent);
|
|
177
|
+
const toLocalCoord = createCoordConverter(svg, fo);
|
|
178
|
+
if (!toParentCoord)
|
|
179
|
+
return null;
|
|
180
|
+
const parentBounds = getFOContentBoundsInSVG(fo, toParentCoord, {
|
|
181
|
+
contentHeight: measuredContent.height,
|
|
182
|
+
contentWidth: measuredContent.width,
|
|
183
|
+
keepForeignObjectWidth,
|
|
184
|
+
});
|
|
185
|
+
const originalX = parseCoordinate(fo.getAttribute('x'));
|
|
186
|
+
const originalY = parseCoordinate(fo.getAttribute('y'));
|
|
187
|
+
const localBounds = toLocalCoord
|
|
188
|
+
? getFOContentBoundsInSVG(fo, toLocalCoord, {
|
|
189
|
+
contentHeight: measuredContent.height,
|
|
190
|
+
contentWidth: measuredContent.width,
|
|
191
|
+
keepForeignObjectWidth,
|
|
192
|
+
})
|
|
193
|
+
: null;
|
|
194
|
+
const hasTransform = fo.hasAttribute('transform');
|
|
195
|
+
if (hasTransform && !localBounds)
|
|
196
|
+
return null;
|
|
197
|
+
const exportBounds = localBounds
|
|
198
|
+
? {
|
|
199
|
+
x: originalX + localBounds[0],
|
|
200
|
+
y: originalY + localBounds[1],
|
|
201
|
+
width: localBounds[2] - localBounds[0],
|
|
202
|
+
height: localBounds[3] - localBounds[1],
|
|
203
|
+
}
|
|
204
|
+
: {
|
|
205
|
+
x: parentBounds[0],
|
|
206
|
+
y: parentBounds[1],
|
|
207
|
+
width: parentBounds[2] - parentBounds[0],
|
|
208
|
+
height: parentBounds[3] - parentBounds[1],
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
rootBounds: getFOContentBoundsInSVG(fo, toSVGCoord, {
|
|
212
|
+
contentHeight: measuredContent.height,
|
|
213
|
+
contentWidth: measuredContent.width,
|
|
214
|
+
keepForeignObjectWidth,
|
|
215
|
+
}),
|
|
216
|
+
exportBounds,
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function computeFullViewBox(svg, adjustments) {
|
|
140
221
|
const viewBox = getExportViewBox(svg);
|
|
141
222
|
if (!viewBox)
|
|
142
223
|
return null;
|
|
143
|
-
if (typeof svg.getScreenCTM !== 'function')
|
|
144
|
-
return null;
|
|
145
|
-
const screenCTM = svg.getScreenCTM();
|
|
146
|
-
if (!screenCTM)
|
|
147
|
-
return null;
|
|
148
|
-
const inverseCTM = screenCTM.inverse();
|
|
149
|
-
const toSVGCoord = (clientX, clientY) => {
|
|
150
|
-
const pt = svg.createSVGPoint();
|
|
151
|
-
pt.x = clientX;
|
|
152
|
-
pt.y = clientY;
|
|
153
|
-
return pt.matrixTransform(inverseCTM);
|
|
154
|
-
};
|
|
155
224
|
let minX = viewBox.x;
|
|
156
225
|
let minY = viewBox.y;
|
|
157
226
|
let maxX = viewBox.x + viewBox.width;
|
|
158
227
|
let maxY = viewBox.y + viewBox.height;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
.forEach((fo) => {
|
|
162
|
-
const content = fo.firstElementChild;
|
|
163
|
-
if (!content)
|
|
228
|
+
adjustments.forEach((adjustment) => {
|
|
229
|
+
if (!adjustment)
|
|
164
230
|
return;
|
|
165
|
-
const
|
|
231
|
+
const { rootBounds } = adjustment;
|
|
232
|
+
const [left, top, right, bottom] = rootBounds;
|
|
166
233
|
minX = Math.min(minX, left);
|
|
167
234
|
minY = Math.min(minY, top);
|
|
168
235
|
maxX = Math.max(maxX, right);
|
|
@@ -179,12 +246,25 @@ function computeFullViewBox(svg) {
|
|
|
179
246
|
return null;
|
|
180
247
|
return `${newX} ${newY} ${newWidth} ${newHeight}`;
|
|
181
248
|
}
|
|
249
|
+
function applyForeignObjectExportAdjustments(svg, adjustments) {
|
|
250
|
+
const clonedForeignObjects = Array.from(svg.querySelectorAll('foreignObject'));
|
|
251
|
+
adjustments.forEach((adjustment, index) => {
|
|
252
|
+
if (!adjustment)
|
|
253
|
+
return;
|
|
254
|
+
const clonedForeignObject = clonedForeignObjects[index];
|
|
255
|
+
if (!clonedForeignObject)
|
|
256
|
+
return;
|
|
257
|
+
setAttributes(clonedForeignObject, adjustment.exportBounds);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
182
260
|
export function exportToSVG(svg_1) {
|
|
183
261
|
return __awaiter(this, arguments, void 0, function* (svg, options = {}) {
|
|
184
262
|
const { removeBackground = false, embedResources = true, removeIds = false, } = options;
|
|
185
263
|
const clonedSVG = svg.cloneNode(true);
|
|
186
264
|
if (typeof document !== 'undefined') {
|
|
187
|
-
const
|
|
265
|
+
const adjustments = collectForeignObjectExportAdjustments(svg);
|
|
266
|
+
applyForeignObjectExportAdjustments(clonedSVG, adjustments);
|
|
267
|
+
const fullViewBox = computeFullViewBox(svg, adjustments);
|
|
188
268
|
if (fullViewBox) {
|
|
189
269
|
clonedSVG.setAttribute('viewBox', fullViewBox);
|
|
190
270
|
}
|
package/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.2.
|
|
1
|
+
export declare const VERSION = "0.2.19";
|
package/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.2.
|
|
1
|
+
export const VERSION = '0.2.19';
|
package/lib/exporter/svg.js
CHANGED
|
@@ -48,38 +48,69 @@ function parseAbsoluteLength(value) {
|
|
|
48
48
|
return Number.NaN;
|
|
49
49
|
return Number.parseFloat(trimmed);
|
|
50
50
|
}
|
|
51
|
-
function
|
|
51
|
+
function parseCoordinate(value) {
|
|
52
|
+
const parsed = parseAbsoluteLength(value);
|
|
53
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
54
|
+
}
|
|
55
|
+
function measureSpanContentDimensions(span, measureWidth) {
|
|
52
56
|
const prevHeight = span.style.height;
|
|
57
|
+
const prevWidth = span.style.width;
|
|
53
58
|
const prevOverflow = span.style.overflow;
|
|
54
59
|
try {
|
|
55
60
|
span.style.height = 'max-content';
|
|
56
61
|
span.style.overflow = 'hidden';
|
|
57
62
|
void span.offsetHeight; // force reflow
|
|
58
|
-
|
|
63
|
+
const scrollHeight = span.scrollHeight;
|
|
64
|
+
const rectHeight = span.getBoundingClientRect().height;
|
|
65
|
+
let width = span.scrollWidth;
|
|
66
|
+
if (measureWidth) {
|
|
67
|
+
span.style.width = 'max-content';
|
|
68
|
+
void span.offsetWidth; // force reflow
|
|
69
|
+
width = span.scrollWidth;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
height: Math.max(scrollHeight, rectHeight),
|
|
73
|
+
width,
|
|
74
|
+
};
|
|
59
75
|
}
|
|
60
76
|
finally {
|
|
61
77
|
span.style.height = prevHeight;
|
|
62
|
-
span.style.overflow = prevOverflow;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
function measureSpanContentWidth(span) {
|
|
66
|
-
const prevWidth = span.style.width;
|
|
67
|
-
const prevOverflow = span.style.overflow;
|
|
68
|
-
try {
|
|
69
|
-
span.style.width = 'max-content';
|
|
70
|
-
span.style.overflow = 'hidden';
|
|
71
|
-
void span.offsetWidth; // force reflow
|
|
72
|
-
return span.scrollWidth;
|
|
73
|
-
}
|
|
74
|
-
finally {
|
|
75
78
|
span.style.width = prevWidth;
|
|
76
79
|
span.style.overflow = prevOverflow;
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
|
-
|
|
82
|
+
function shouldKeepForeignObjectWidth(style) {
|
|
83
|
+
const whiteSpace = style.whiteSpace;
|
|
84
|
+
const flexWrap = style.flexWrap;
|
|
85
|
+
const wordBreak = style.wordBreak;
|
|
86
|
+
const overflowWrap = style.overflowWrap;
|
|
87
|
+
return (flexWrap === 'wrap' ||
|
|
88
|
+
flexWrap === 'wrap-reverse' ||
|
|
89
|
+
whiteSpace === 'pre-wrap' ||
|
|
90
|
+
whiteSpace === 'pre-line' ||
|
|
91
|
+
whiteSpace === 'normal' ||
|
|
92
|
+
overflowWrap === 'break-word' ||
|
|
93
|
+
wordBreak === 'break-word' ||
|
|
94
|
+
wordBreak === 'break-all');
|
|
95
|
+
}
|
|
96
|
+
function createCoordConverter(svg, element) {
|
|
97
|
+
if (typeof element.getScreenCTM !== 'function')
|
|
98
|
+
return null;
|
|
99
|
+
const screenCTM = element.getScreenCTM();
|
|
100
|
+
if (!screenCTM)
|
|
101
|
+
return null;
|
|
102
|
+
const inverseCTM = screenCTM.inverse();
|
|
103
|
+
return (clientX, clientY) => {
|
|
104
|
+
const pt = svg.createSVGPoint();
|
|
105
|
+
pt.x = clientX;
|
|
106
|
+
pt.y = clientY;
|
|
107
|
+
return pt.matrixTransform(inverseCTM);
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Returns [left, top, right, bottom] in target coordinates for a foreignObject,
|
|
80
111
|
// accounting for flex alignment: bottom/center-aligned content can overflow,
|
|
81
112
|
// and horizontally aligned content can overflow as well.
|
|
82
|
-
function getFOContentBoundsInSVG(fo,
|
|
113
|
+
function getFOContentBoundsInSVG(fo, toSVGCoord, { contentHeight, contentWidth, keepForeignObjectWidth, }) {
|
|
83
114
|
const foRect = fo.getBoundingClientRect();
|
|
84
115
|
const foTopLeft = toSVGCoord(foRect.left, foRect.top);
|
|
85
116
|
const foBottomRight = toSVGCoord(foRect.right, foRect.bottom);
|
|
@@ -91,16 +122,15 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
|
|
|
91
122
|
const foHeightSVG = foBottomSVG - foTopSVG;
|
|
92
123
|
const svgUnitsPerClientPxY = foRect.height > 0 ? foHeightSVG / foRect.height : 1;
|
|
93
124
|
const svgUnitsPerClientPxX = foRect.width > 0 ? foWidthSVG / foRect.width : 1;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const contentHeightSVG = realScrollHeight > 0
|
|
97
|
-
? realScrollHeight * svgUnitsPerClientPxY
|
|
125
|
+
const contentHeightSVG = contentHeight > 0
|
|
126
|
+
? contentHeight * svgUnitsPerClientPxY
|
|
98
127
|
: foHeightSVG;
|
|
99
|
-
const
|
|
100
|
-
const contentWidthSVG = realScrollWidth > 0 ? realScrollWidth * svgUnitsPerClientPxX : foWidthSVG;
|
|
101
|
-
const computedStyle = window.getComputedStyle(content);
|
|
128
|
+
const computedStyle = window.getComputedStyle(fo.firstElementChild);
|
|
102
129
|
const alignItems = computedStyle.alignItems;
|
|
103
130
|
const justifyContent = computedStyle.justifyContent;
|
|
131
|
+
const contentWidthSVG = keepForeignObjectWidth
|
|
132
|
+
? foWidthSVG
|
|
133
|
+
: Math.max(foWidthSVG, contentWidth * svgUnitsPerClientPxX);
|
|
104
134
|
// Calculate vertical bounds
|
|
105
135
|
let top, bottom;
|
|
106
136
|
if (alignItems === 'flex-end' || alignItems === 'end') {
|
|
@@ -135,38 +165,75 @@ function getFOContentBoundsInSVG(fo, content, toSVGCoord) {
|
|
|
135
165
|
}
|
|
136
166
|
return [left, top, right, bottom];
|
|
137
167
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
168
|
+
function collectForeignObjectExportAdjustments(svg) {
|
|
169
|
+
const toSVGCoord = createCoordConverter(svg, svg);
|
|
170
|
+
if (!toSVGCoord)
|
|
171
|
+
return [];
|
|
172
|
+
return Array.from(svg.querySelectorAll('foreignObject')).map((fo) => {
|
|
173
|
+
const content = fo.firstElementChild;
|
|
174
|
+
if (!content)
|
|
175
|
+
return null;
|
|
176
|
+
const computedStyle = window.getComputedStyle(content);
|
|
177
|
+
const keepForeignObjectWidth = shouldKeepForeignObjectWidth(computedStyle);
|
|
178
|
+
const measuredContent = measureSpanContentDimensions(content, !keepForeignObjectWidth);
|
|
179
|
+
const parent = fo.parentElement instanceof SVGGraphicsElement ? fo.parentElement : svg;
|
|
180
|
+
const toParentCoord = createCoordConverter(svg, parent);
|
|
181
|
+
const toLocalCoord = createCoordConverter(svg, fo);
|
|
182
|
+
if (!toParentCoord)
|
|
183
|
+
return null;
|
|
184
|
+
const parentBounds = getFOContentBoundsInSVG(fo, toParentCoord, {
|
|
185
|
+
contentHeight: measuredContent.height,
|
|
186
|
+
contentWidth: measuredContent.width,
|
|
187
|
+
keepForeignObjectWidth,
|
|
188
|
+
});
|
|
189
|
+
const originalX = parseCoordinate(fo.getAttribute('x'));
|
|
190
|
+
const originalY = parseCoordinate(fo.getAttribute('y'));
|
|
191
|
+
const localBounds = toLocalCoord
|
|
192
|
+
? getFOContentBoundsInSVG(fo, toLocalCoord, {
|
|
193
|
+
contentHeight: measuredContent.height,
|
|
194
|
+
contentWidth: measuredContent.width,
|
|
195
|
+
keepForeignObjectWidth,
|
|
196
|
+
})
|
|
197
|
+
: null;
|
|
198
|
+
const hasTransform = fo.hasAttribute('transform');
|
|
199
|
+
if (hasTransform && !localBounds)
|
|
200
|
+
return null;
|
|
201
|
+
const exportBounds = localBounds
|
|
202
|
+
? {
|
|
203
|
+
x: originalX + localBounds[0],
|
|
204
|
+
y: originalY + localBounds[1],
|
|
205
|
+
width: localBounds[2] - localBounds[0],
|
|
206
|
+
height: localBounds[3] - localBounds[1],
|
|
207
|
+
}
|
|
208
|
+
: {
|
|
209
|
+
x: parentBounds[0],
|
|
210
|
+
y: parentBounds[1],
|
|
211
|
+
width: parentBounds[2] - parentBounds[0],
|
|
212
|
+
height: parentBounds[3] - parentBounds[1],
|
|
213
|
+
};
|
|
214
|
+
return {
|
|
215
|
+
rootBounds: getFOContentBoundsInSVG(fo, toSVGCoord, {
|
|
216
|
+
contentHeight: measuredContent.height,
|
|
217
|
+
contentWidth: measuredContent.width,
|
|
218
|
+
keepForeignObjectWidth,
|
|
219
|
+
}),
|
|
220
|
+
exportBounds,
|
|
221
|
+
};
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
function computeFullViewBox(svg, adjustments) {
|
|
144
225
|
const viewBox = getExportViewBox(svg);
|
|
145
226
|
if (!viewBox)
|
|
146
227
|
return null;
|
|
147
|
-
if (typeof svg.getScreenCTM !== 'function')
|
|
148
|
-
return null;
|
|
149
|
-
const screenCTM = svg.getScreenCTM();
|
|
150
|
-
if (!screenCTM)
|
|
151
|
-
return null;
|
|
152
|
-
const inverseCTM = screenCTM.inverse();
|
|
153
|
-
const toSVGCoord = (clientX, clientY) => {
|
|
154
|
-
const pt = svg.createSVGPoint();
|
|
155
|
-
pt.x = clientX;
|
|
156
|
-
pt.y = clientY;
|
|
157
|
-
return pt.matrixTransform(inverseCTM);
|
|
158
|
-
};
|
|
159
228
|
let minX = viewBox.x;
|
|
160
229
|
let minY = viewBox.y;
|
|
161
230
|
let maxX = viewBox.x + viewBox.width;
|
|
162
231
|
let maxY = viewBox.y + viewBox.height;
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
.forEach((fo) => {
|
|
166
|
-
const content = fo.firstElementChild;
|
|
167
|
-
if (!content)
|
|
232
|
+
adjustments.forEach((adjustment) => {
|
|
233
|
+
if (!adjustment)
|
|
168
234
|
return;
|
|
169
|
-
const
|
|
235
|
+
const { rootBounds } = adjustment;
|
|
236
|
+
const [left, top, right, bottom] = rootBounds;
|
|
170
237
|
minX = Math.min(minX, left);
|
|
171
238
|
minY = Math.min(minY, top);
|
|
172
239
|
maxX = Math.max(maxX, right);
|
|
@@ -183,12 +250,25 @@ function computeFullViewBox(svg) {
|
|
|
183
250
|
return null;
|
|
184
251
|
return `${newX} ${newY} ${newWidth} ${newHeight}`;
|
|
185
252
|
}
|
|
253
|
+
function applyForeignObjectExportAdjustments(svg, adjustments) {
|
|
254
|
+
const clonedForeignObjects = Array.from(svg.querySelectorAll('foreignObject'));
|
|
255
|
+
adjustments.forEach((adjustment, index) => {
|
|
256
|
+
if (!adjustment)
|
|
257
|
+
return;
|
|
258
|
+
const clonedForeignObject = clonedForeignObjects[index];
|
|
259
|
+
if (!clonedForeignObject)
|
|
260
|
+
return;
|
|
261
|
+
(0, utils_1.setAttributes)(clonedForeignObject, adjustment.exportBounds);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
186
264
|
function exportToSVG(svg_1) {
|
|
187
265
|
return __awaiter(this, arguments, void 0, function* (svg, options = {}) {
|
|
188
266
|
const { removeBackground = false, embedResources = true, removeIds = false, } = options;
|
|
189
267
|
const clonedSVG = svg.cloneNode(true);
|
|
190
268
|
if (typeof document !== 'undefined') {
|
|
191
|
-
const
|
|
269
|
+
const adjustments = collectForeignObjectExportAdjustments(svg);
|
|
270
|
+
applyForeignObjectExportAdjustments(clonedSVG, adjustments);
|
|
271
|
+
const fullViewBox = computeFullViewBox(svg, adjustments);
|
|
192
272
|
if (fullViewBox) {
|
|
193
273
|
clonedSVG.setAttribute('viewBox', fullViewBox);
|
|
194
274
|
}
|
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.2.
|
|
1
|
+
export declare const VERSION = "0.2.19";
|
package/lib/version.js
CHANGED