@zumer/snapdom 1.9.12-dev.1 → 1.9.12-dev.3
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/snapdom.js +603 -185
- package/dist/snapdom.min.js +5 -5
- package/dist/snapdom.min.mjs +4 -4
- package/dist/snapdom.mjs +598 -181
- package/package.json +1 -1
package/dist/snapdom.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/*
|
|
3
3
|
* snapdom
|
|
4
|
-
* v.1.9.12-dev.
|
|
4
|
+
* v.1.9.12-dev.3
|
|
5
5
|
* Author Juan Martin Muda
|
|
6
6
|
* License MIT
|
|
7
7
|
**/
|
|
@@ -628,17 +628,6 @@
|
|
|
628
628
|
}
|
|
629
629
|
return map.get(pseudo);
|
|
630
630
|
}
|
|
631
|
-
function parseContent(content) {
|
|
632
|
-
let clean = content.replace(/^['"]|['"]$/g, "");
|
|
633
|
-
if (clean.startsWith("\\")) {
|
|
634
|
-
try {
|
|
635
|
-
return String.fromCharCode(parseInt(clean.replace("\\", ""), 16));
|
|
636
|
-
} catch (e) {
|
|
637
|
-
return clean;
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
return clean;
|
|
641
|
-
}
|
|
642
631
|
function snapshotComputedStyle(style) {
|
|
643
632
|
const snap = {};
|
|
644
633
|
for (let prop of style) {
|
|
@@ -757,6 +746,7 @@
|
|
|
757
746
|
if (rec && rec.epoch === __epoch) return rec.snapshot;
|
|
758
747
|
const style = preStyle || getComputedStyle(el);
|
|
759
748
|
const snap = snapshotComputedStyleFull(style, options);
|
|
749
|
+
stripHeightForWrappers(el, style, snap);
|
|
760
750
|
snapshotCache.set(el, { epoch: __epoch, snapshot: snap });
|
|
761
751
|
return snap;
|
|
762
752
|
}
|
|
@@ -823,6 +813,49 @@
|
|
|
823
813
|
session.styleMap.set(clone, key);
|
|
824
814
|
});
|
|
825
815
|
}
|
|
816
|
+
function isReplaced(el) {
|
|
817
|
+
return el instanceof HTMLImageElement || el instanceof HTMLCanvasElement || el instanceof HTMLVideoElement || el instanceof HTMLIFrameElement || el instanceof SVGElement || el instanceof HTMLObjectElement || el instanceof HTMLEmbedElement;
|
|
818
|
+
}
|
|
819
|
+
function hasBox(cs) {
|
|
820
|
+
if (cs.backgroundImage && cs.backgroundImage !== "none") return true;
|
|
821
|
+
if (cs.backgroundColor && cs.backgroundColor !== "rgba(0, 0, 0, 0)" && cs.backgroundColor !== "transparent") return true;
|
|
822
|
+
if ((parseFloat(cs.borderTopWidth) || 0) > 0) return true;
|
|
823
|
+
if ((parseFloat(cs.borderBottomWidth) || 0) > 0) return true;
|
|
824
|
+
if ((parseFloat(cs.paddingTop) || 0) > 0) return true;
|
|
825
|
+
if ((parseFloat(cs.paddingBottom) || 0) > 0) return true;
|
|
826
|
+
const ob = cs.overflowBlock || cs.overflowY || "visible";
|
|
827
|
+
return ob !== "visible";
|
|
828
|
+
}
|
|
829
|
+
function isFlexOrGridItem(el) {
|
|
830
|
+
const p = el.parentElement;
|
|
831
|
+
if (!p) return false;
|
|
832
|
+
const pd = getComputedStyle(p).display || "";
|
|
833
|
+
return pd.includes("flex") || pd.includes("grid");
|
|
834
|
+
}
|
|
835
|
+
function hasFlowFast(el, cs) {
|
|
836
|
+
if (el.textContent && /\S/.test(el.textContent)) return true;
|
|
837
|
+
const f = el.firstElementChild, l = el.lastElementChild;
|
|
838
|
+
if (f && f.tagName === "BR" || l && l.tagName === "BR") return true;
|
|
839
|
+
const sh = el.scrollHeight;
|
|
840
|
+
if (sh === 0) return false;
|
|
841
|
+
const pt = parseFloat(cs.paddingTop) || 0;
|
|
842
|
+
const pb = parseFloat(cs.paddingBottom) || 0;
|
|
843
|
+
return sh > pt + pb;
|
|
844
|
+
}
|
|
845
|
+
function stripHeightForWrappers(el, cs, snap) {
|
|
846
|
+
if (el instanceof HTMLElement && el.style && el.style.height) return;
|
|
847
|
+
const disp = cs.display || "";
|
|
848
|
+
if (disp.includes("flex") || disp.includes("grid")) return;
|
|
849
|
+
if (isReplaced(el)) return;
|
|
850
|
+
const pos = cs.position;
|
|
851
|
+
if (pos === "absolute" || pos === "fixed" || pos === "sticky") return;
|
|
852
|
+
if (cs.transform !== "none") return;
|
|
853
|
+
if (hasBox(cs)) return;
|
|
854
|
+
if (isFlexOrGridItem(el)) return;
|
|
855
|
+
if (!hasFlowFast(el, cs)) return;
|
|
856
|
+
delete snap.height;
|
|
857
|
+
delete snap["block-size"];
|
|
858
|
+
}
|
|
826
859
|
|
|
827
860
|
// src/core/clone.js
|
|
828
861
|
function idleCallback(childList, callback, fast) {
|
|
@@ -2128,11 +2161,21 @@
|
|
|
2128
2161
|
const empty = /* @__PURE__ */ new Map();
|
|
2129
2162
|
build(rootEl, empty, empty);
|
|
2130
2163
|
return {
|
|
2164
|
+
/**
|
|
2165
|
+
* Get top value for counter name at given node.
|
|
2166
|
+
* @param {Element} node
|
|
2167
|
+
* @param {string} name
|
|
2168
|
+
*/
|
|
2131
2169
|
get(node, name) {
|
|
2132
2170
|
var _a;
|
|
2133
2171
|
const s = (_a = nodeCounters.get(node)) == null ? void 0 : _a.get(name);
|
|
2134
2172
|
return s && s.length ? s[s.length - 1] : 0;
|
|
2135
2173
|
},
|
|
2174
|
+
/**
|
|
2175
|
+
* Get full stack for counter name at given node.
|
|
2176
|
+
* @param {Element} node
|
|
2177
|
+
* @param {string} name
|
|
2178
|
+
*/
|
|
2136
2179
|
getStack(node, name) {
|
|
2137
2180
|
var _a;
|
|
2138
2181
|
const s = (_a = nodeCounters.get(node)) == null ? void 0 : _a.get(name);
|
|
@@ -2170,10 +2213,111 @@
|
|
|
2170
2213
|
|
|
2171
2214
|
// src/modules/pseudo.js
|
|
2172
2215
|
var counterCtx = null;
|
|
2216
|
+
var __siblingCounters = /* @__PURE__ */ new WeakMap();
|
|
2217
|
+
function unquoteDoubleStrings2(s) {
|
|
2218
|
+
return (s || "").replace(/"([^"]*)"/g, "$1");
|
|
2219
|
+
}
|
|
2220
|
+
function collapseCssContent(raw) {
|
|
2221
|
+
if (!raw) return "";
|
|
2222
|
+
const tokens = [];
|
|
2223
|
+
const rx = /"([^"]*)"/g;
|
|
2224
|
+
let m;
|
|
2225
|
+
while (m = rx.exec(raw)) tokens.push(m[1]);
|
|
2226
|
+
if (tokens.length) return tokens.join("");
|
|
2227
|
+
return unquoteDoubleStrings2(raw);
|
|
2228
|
+
}
|
|
2229
|
+
function withSiblingOverrides(node, base) {
|
|
2230
|
+
const parent = node.parentElement;
|
|
2231
|
+
const map = parent ? __siblingCounters.get(parent) : null;
|
|
2232
|
+
if (!map) return base;
|
|
2233
|
+
return {
|
|
2234
|
+
get(n, name) {
|
|
2235
|
+
const v = base.get(n, name);
|
|
2236
|
+
const ov = map.get(name);
|
|
2237
|
+
return typeof ov === "number" ? Math.max(v, ov) : v;
|
|
2238
|
+
},
|
|
2239
|
+
getStack(n, name) {
|
|
2240
|
+
const s = base.getStack(n, name);
|
|
2241
|
+
if (!s.length) return s;
|
|
2242
|
+
const ov = map.get(name);
|
|
2243
|
+
if (typeof ov === "number") {
|
|
2244
|
+
const out = s.slice();
|
|
2245
|
+
out[out.length - 1] = Math.max(out[out.length - 1], ov);
|
|
2246
|
+
return out;
|
|
2247
|
+
}
|
|
2248
|
+
return s;
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
}
|
|
2252
|
+
function deriveCounterCtxForPseudo(node, pseudoStyle, baseCtx) {
|
|
2253
|
+
const modStacks = /* @__PURE__ */ new Map();
|
|
2254
|
+
function parseListDecl(value) {
|
|
2255
|
+
const out = [];
|
|
2256
|
+
if (!value || value === "none") return out;
|
|
2257
|
+
for (const part of String(value).split(",")) {
|
|
2258
|
+
const toks = part.trim().split(/\s+/);
|
|
2259
|
+
const name = toks[0];
|
|
2260
|
+
const num = Number.isFinite(Number(toks[1])) ? Number(toks[1]) : void 0;
|
|
2261
|
+
if (name) out.push({ name, num });
|
|
2262
|
+
}
|
|
2263
|
+
return out;
|
|
2264
|
+
}
|
|
2265
|
+
const resets = parseListDecl(pseudoStyle == null ? void 0 : pseudoStyle.counterReset);
|
|
2266
|
+
const incs = parseListDecl(pseudoStyle == null ? void 0 : pseudoStyle.counterIncrement);
|
|
2267
|
+
function getStackDerived(name) {
|
|
2268
|
+
if (modStacks.has(name)) return modStacks.get(name).slice();
|
|
2269
|
+
let stack = baseCtx.getStack(node, name);
|
|
2270
|
+
stack = stack.length ? stack.slice() : [];
|
|
2271
|
+
const r = resets.find((x) => x.name === name);
|
|
2272
|
+
if (r) {
|
|
2273
|
+
const val = Number.isFinite(r.num) ? r.num : 0;
|
|
2274
|
+
stack = stack.length ? [...stack, val] : [val];
|
|
2275
|
+
}
|
|
2276
|
+
const inc = incs.find((x) => x.name === name);
|
|
2277
|
+
if (inc) {
|
|
2278
|
+
const by = Number.isFinite(inc.num) ? inc.num : 1;
|
|
2279
|
+
if (stack.length === 0) stack = [0];
|
|
2280
|
+
stack[stack.length - 1] += by;
|
|
2281
|
+
}
|
|
2282
|
+
modStacks.set(name, stack.slice());
|
|
2283
|
+
return stack;
|
|
2284
|
+
}
|
|
2285
|
+
return {
|
|
2286
|
+
get(_node, name) {
|
|
2287
|
+
const s = getStackDerived(name);
|
|
2288
|
+
return s.length ? s[s.length - 1] : 0;
|
|
2289
|
+
},
|
|
2290
|
+
getStack(_node, name) {
|
|
2291
|
+
return getStackDerived(name);
|
|
2292
|
+
},
|
|
2293
|
+
/** expone increments del pseudo para que el caller pueda propagar a hermanos */
|
|
2294
|
+
__incs: incs
|
|
2295
|
+
};
|
|
2296
|
+
}
|
|
2297
|
+
function resolvePseudoContentAndIncs(node, pseudo, baseCtx) {
|
|
2298
|
+
let ps;
|
|
2299
|
+
try {
|
|
2300
|
+
ps = getComputedStyle(node, pseudo);
|
|
2301
|
+
} catch (e) {
|
|
2302
|
+
}
|
|
2303
|
+
const raw = ps == null ? void 0 : ps.content;
|
|
2304
|
+
if (!raw || raw === "none" || raw === "normal") return { text: "", incs: [] };
|
|
2305
|
+
const baseWithSiblings = withSiblingOverrides(node, baseCtx);
|
|
2306
|
+
const derived = deriveCounterCtxForPseudo(node, ps, baseWithSiblings);
|
|
2307
|
+
let resolved = hasCounters(raw) ? resolveCountersInContent(raw, node, derived) : raw;
|
|
2308
|
+
const text = collapseCssContent(resolved);
|
|
2309
|
+
return { text, incs: derived.__incs || [] };
|
|
2310
|
+
}
|
|
2173
2311
|
function inlinePseudoElements(source, clone, sessionCache, options) {
|
|
2174
2312
|
return __async(this, null, function* () {
|
|
2175
2313
|
var _a;
|
|
2176
2314
|
if (!(source instanceof Element) || !(clone instanceof Element)) return;
|
|
2315
|
+
if (!counterCtx) {
|
|
2316
|
+
try {
|
|
2317
|
+
counterCtx = buildCounterContext(source.ownerDocument || document);
|
|
2318
|
+
} catch (e) {
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2177
2321
|
for (const pseudo of ["::before", "::after", "::first-letter"]) {
|
|
2178
2322
|
try {
|
|
2179
2323
|
const style = getStyle(source, pseudo);
|
|
@@ -2207,12 +2351,8 @@
|
|
|
2207
2351
|
clone.insertBefore(span, restNode);
|
|
2208
2352
|
continue;
|
|
2209
2353
|
}
|
|
2210
|
-
const
|
|
2211
|
-
|
|
2212
|
-
if (hasCounters(content)) {
|
|
2213
|
-
counterCtx = buildCounterContext(source.ownerDocument || document);
|
|
2214
|
-
cleanContent = resolveCountersInContent(cleanContent, source, counterCtx);
|
|
2215
|
-
}
|
|
2354
|
+
const rawContent = style.content;
|
|
2355
|
+
const { text: cleanContent, incs } = resolvePseudoContentAndIncs(source, pseudo, counterCtx);
|
|
2216
2356
|
const bg = style.backgroundImage;
|
|
2217
2357
|
const bgColor = style.backgroundColor;
|
|
2218
2358
|
const fontFamily = style.fontFamily;
|
|
@@ -2226,28 +2366,41 @@
|
|
|
2226
2366
|
const borderWidth = parseFloat(style.borderWidth);
|
|
2227
2367
|
const transform = style.transform;
|
|
2228
2368
|
const isIconFont22 = isIconFont2(fontFamily);
|
|
2229
|
-
const hasExplicitContent =
|
|
2369
|
+
const hasExplicitContent = rawContent !== "none" && cleanContent !== "";
|
|
2230
2370
|
const hasBg = bg && bg !== "none";
|
|
2231
2371
|
const hasBgColor = bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)";
|
|
2232
|
-
const
|
|
2372
|
+
const hasBox2 = display !== "inline" && (width > 0 || height > 0);
|
|
2233
2373
|
const hasBorder = borderStyle && borderStyle !== "none" && borderWidth > 0;
|
|
2234
2374
|
const hasTransform = transform && transform !== "none";
|
|
2235
|
-
const shouldRender = hasExplicitContent || hasBg || hasBgColor ||
|
|
2236
|
-
if (!shouldRender)
|
|
2375
|
+
const shouldRender = hasExplicitContent || hasBg || hasBgColor || hasBox2 || hasBorder || hasTransform;
|
|
2376
|
+
if (!shouldRender) {
|
|
2377
|
+
if (incs && incs.length && source.parentElement) {
|
|
2378
|
+
const map = __siblingCounters.get(source.parentElement) || /* @__PURE__ */ new Map();
|
|
2379
|
+
for (const { name, num } of incs) {
|
|
2380
|
+
if (!name) continue;
|
|
2381
|
+
const baseWithSibs = withSiblingOverrides(source, counterCtx);
|
|
2382
|
+
const derived = deriveCounterCtxForPseudo(source, getComputedStyle(source, pseudo), baseWithSibs);
|
|
2383
|
+
const finalVal = derived.get(source, name);
|
|
2384
|
+
map.set(name, finalVal);
|
|
2385
|
+
}
|
|
2386
|
+
__siblingCounters.set(source.parentElement, map);
|
|
2387
|
+
}
|
|
2388
|
+
continue;
|
|
2389
|
+
}
|
|
2237
2390
|
const pseudoEl = document.createElement("span");
|
|
2238
2391
|
pseudoEl.dataset.snapdomPseudo = pseudo;
|
|
2239
2392
|
pseudoEl.style.verticalAlign = "middle";
|
|
2240
2393
|
const snapshot = snapshotComputedStyle(style);
|
|
2241
2394
|
const key = getStyleKey(snapshot, "span");
|
|
2242
2395
|
sessionCache.styleMap.set(pseudoEl, key);
|
|
2243
|
-
if (isIconFont22 && cleanContent.length === 1) {
|
|
2244
|
-
const { dataUrl, width:
|
|
2396
|
+
if (isIconFont22 && cleanContent && cleanContent.length === 1) {
|
|
2397
|
+
const { dataUrl, width: w, height: h } = yield iconToImage(cleanContent, fontFamily, fontWeight, fontSize, color);
|
|
2245
2398
|
const imgEl = document.createElement("img");
|
|
2246
2399
|
imgEl.src = dataUrl;
|
|
2247
|
-
imgEl.style = `height:${fontSize}px;width:${
|
|
2400
|
+
imgEl.style = `height:${fontSize}px;width:${w / h * fontSize}px;object-fit:contain;`;
|
|
2248
2401
|
pseudoEl.appendChild(imgEl);
|
|
2249
2402
|
clone.dataset.snapdomHasIcon = "true";
|
|
2250
|
-
} else if (cleanContent.startsWith("url(")) {
|
|
2403
|
+
} else if (cleanContent && cleanContent.startsWith("url(")) {
|
|
2251
2404
|
const rawUrl = extractURL(cleanContent);
|
|
2252
2405
|
if (rawUrl == null ? void 0 : rawUrl.trim()) {
|
|
2253
2406
|
try {
|
|
@@ -2274,7 +2427,18 @@
|
|
|
2274
2427
|
}
|
|
2275
2428
|
if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
|
|
2276
2429
|
const hasContent2 = pseudoEl.childNodes.length > 0 || ((_a = pseudoEl.textContent) == null ? void 0 : _a.trim()) !== "";
|
|
2277
|
-
const hasVisibleBox = hasContent2 || hasBg || hasBgColor ||
|
|
2430
|
+
const hasVisibleBox = hasContent2 || hasBg || hasBgColor || hasBox2 || hasBorder || hasTransform;
|
|
2431
|
+
if (incs && incs.length && source.parentElement) {
|
|
2432
|
+
const map = __siblingCounters.get(source.parentElement) || /* @__PURE__ */ new Map();
|
|
2433
|
+
const baseWithSibs = withSiblingOverrides(source, counterCtx);
|
|
2434
|
+
const derived = deriveCounterCtxForPseudo(source, getComputedStyle(source, pseudo), baseWithSibs);
|
|
2435
|
+
for (const { name } of incs) {
|
|
2436
|
+
if (!name) continue;
|
|
2437
|
+
const finalVal = derived.get(source, name);
|
|
2438
|
+
map.set(name, finalVal);
|
|
2439
|
+
}
|
|
2440
|
+
__siblingCounters.set(source.parentElement, map);
|
|
2441
|
+
}
|
|
2278
2442
|
if (!hasVisibleBox) continue;
|
|
2279
2443
|
if (pseudo === "::before") {
|
|
2280
2444
|
clone.insertBefore(pseudoEl, clone.firstChild);
|
|
@@ -2424,12 +2588,13 @@
|
|
|
2424
2588
|
sessionCache.styleCache.set(element, computed);
|
|
2425
2589
|
const transform = stripTranslate(computed.transform);
|
|
2426
2590
|
clone.style.margin = "0";
|
|
2427
|
-
clone.style.position = "static";
|
|
2428
2591
|
clone.style.top = "auto";
|
|
2429
2592
|
clone.style.left = "auto";
|
|
2430
2593
|
clone.style.right = "auto";
|
|
2431
2594
|
clone.style.bottom = "auto";
|
|
2432
|
-
clone.style.
|
|
2595
|
+
clone.style.animation = "none";
|
|
2596
|
+
clone.style.transition = "none";
|
|
2597
|
+
clone.style.willChange = "auto";
|
|
2433
2598
|
clone.style.float = "none";
|
|
2434
2599
|
clone.style.clear = "none";
|
|
2435
2600
|
clone.style.transform = transform || "";
|
|
@@ -2842,7 +3007,7 @@
|
|
|
2842
3007
|
idle(() => __async(null, null, function* () {
|
|
2843
3008
|
const required = collectUsedFontVariants(element);
|
|
2844
3009
|
const usedCodepoints = collectUsedCodepoints(element);
|
|
2845
|
-
if (isSafari) {
|
|
3010
|
+
if (isSafari()) {
|
|
2846
3011
|
const families = new Set(
|
|
2847
3012
|
Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
|
|
2848
3013
|
);
|
|
@@ -2874,102 +3039,188 @@
|
|
|
2874
3039
|
}
|
|
2875
3040
|
yield new Promise((resolve) => {
|
|
2876
3041
|
idle(() => {
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
3042
|
+
const csEl = getComputedStyle(element);
|
|
3043
|
+
function parseFilterDropShadows(cs) {
|
|
3044
|
+
var _a;
|
|
3045
|
+
const raw = `${cs.filter || ""} ${cs.webkitFilter || ""}`.trim();
|
|
3046
|
+
if (!raw || raw === "none") {
|
|
3047
|
+
return { bleed: { top: 0, right: 0, bottom: 0, left: 0 }, has: false };
|
|
3048
|
+
}
|
|
3049
|
+
const tokens = raw.match(/drop-shadow\((?:[^()]|\([^()]*\))*\)/gi) || [];
|
|
3050
|
+
let t = 0, r = 0, b = 0, l = 0;
|
|
3051
|
+
let found = false;
|
|
3052
|
+
for (const tok of tokens) {
|
|
3053
|
+
found = true;
|
|
3054
|
+
const nums = ((_a = tok.match(/-?\d+(?:\.\d+)?px/gi)) == null ? void 0 : _a.map((v) => parseFloat(v))) || [];
|
|
3055
|
+
const [ox = 0, oy = 0, blur = 0] = nums;
|
|
3056
|
+
const extX = Math.abs(ox) + blur;
|
|
3057
|
+
const extY = Math.abs(oy) + blur;
|
|
3058
|
+
r = Math.max(r, extX + Math.max(ox, 0));
|
|
3059
|
+
l = Math.max(l, extX + Math.max(-ox, 0));
|
|
3060
|
+
b = Math.max(b, extY + Math.max(oy, 0));
|
|
3061
|
+
t = Math.max(t, extY + Math.max(-oy, 0));
|
|
2896
3062
|
}
|
|
3063
|
+
return {
|
|
3064
|
+
bleed: { top: Math.ceil(t), right: Math.ceil(r), bottom: Math.ceil(b), left: Math.ceil(l) },
|
|
3065
|
+
has: found
|
|
3066
|
+
};
|
|
2897
3067
|
}
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
3068
|
+
function parseBoxShadow(cs) {
|
|
3069
|
+
var _a;
|
|
3070
|
+
const v = cs.boxShadow || "";
|
|
3071
|
+
if (!v || v === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
3072
|
+
const parts = v.split(/\),(?=(?:[^()]*\([^()]*\))*[^()]*$)/).map((s) => s.trim());
|
|
3073
|
+
let t = 0, r = 0, b2 = 0, l = 0;
|
|
3074
|
+
for (const part of parts) {
|
|
3075
|
+
const nums = ((_a = part.match(/-?\d+(\.\d+)?px/g)) == null ? void 0 : _a.map((n) => parseFloat(n))) || [];
|
|
3076
|
+
if (nums.length < 2) continue;
|
|
3077
|
+
const [ox2, oy2, blur = 0, spread = 0] = nums;
|
|
3078
|
+
const extX = Math.abs(ox2) + blur + spread;
|
|
3079
|
+
const extY = Math.abs(oy2) + blur + spread;
|
|
3080
|
+
r = Math.max(r, extX + Math.max(ox2, 0));
|
|
3081
|
+
l = Math.max(l, extX + Math.max(-ox2, 0));
|
|
3082
|
+
b2 = Math.max(b2, extY + Math.max(oy2, 0));
|
|
3083
|
+
t = Math.max(t, extY + Math.max(-oy2, 0));
|
|
3084
|
+
}
|
|
3085
|
+
return { top: Math.ceil(t), right: Math.ceil(r), bottom: Math.ceil(b2), left: Math.ceil(l) };
|
|
3086
|
+
}
|
|
3087
|
+
function parseFilterBlur(cs) {
|
|
3088
|
+
const m = (cs.filter || "").match(/blur\(\s*([0-9.]+)px\s*\)/);
|
|
3089
|
+
const b2 = m ? Math.ceil(parseFloat(m[1]) || 0) : 0;
|
|
3090
|
+
return { top: b2, right: b2, bottom: b2, left: b2 };
|
|
3091
|
+
}
|
|
3092
|
+
function parseOutline(cs) {
|
|
3093
|
+
if ((cs.outlineStyle || "none") === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
3094
|
+
const w2 = Math.ceil(parseFloat(cs.outlineWidth || "0") || 0);
|
|
3095
|
+
return { top: w2, right: w2, bottom: w2, left: w2 };
|
|
3096
|
+
}
|
|
3097
|
+
function bboxWithOriginFull(w2, h2, M, ox2, oy2) {
|
|
3098
|
+
const a2 = M.a, b2 = M.b, c2 = M.c, d2 = M.d, e2 = M.e || 0, f2 = M.f || 0;
|
|
3099
|
+
function pt(x, y) {
|
|
3100
|
+
let X = x - ox2, Y = y - oy2;
|
|
3101
|
+
let X2 = a2 * X + c2 * Y, Y2 = b2 * X + d2 * Y;
|
|
3102
|
+
X2 += ox2 + e2;
|
|
3103
|
+
Y2 += oy2 + f2;
|
|
3104
|
+
return [X2, Y2];
|
|
3105
|
+
}
|
|
3106
|
+
const P = [pt(0, 0), pt(w2, 0), pt(0, h2), pt(w2, h2)];
|
|
3107
|
+
let minX2 = Infinity, minY2 = Infinity, maxX2 = -Infinity, maxY2 = -Infinity;
|
|
3108
|
+
for (const [X, Y] of P) {
|
|
3109
|
+
if (X < minX2) minX2 = X;
|
|
3110
|
+
if (Y < minY2) minY2 = Y;
|
|
3111
|
+
if (X > maxX2) maxX2 = X;
|
|
3112
|
+
if (Y > maxY2) maxY2 = Y;
|
|
3113
|
+
}
|
|
3114
|
+
return { minX: minX2, minY: minY2, maxX: maxX2, maxY: maxY2, width: maxX2 - minX2, height: maxY2 - minY2 };
|
|
3115
|
+
}
|
|
3116
|
+
function hasTFBBox(el) {
|
|
3117
|
+
return hasBBoxAffectingTransform(el);
|
|
3118
|
+
}
|
|
3119
|
+
const rect = element.getBoundingClientRect();
|
|
3120
|
+
const w0 = Math.max(1, Math.ceil(element.offsetWidth || parseFloat(csEl.width) || rect.width || 1));
|
|
3121
|
+
const h0 = Math.max(1, Math.ceil(element.offsetHeight || parseFloat(csEl.height) || rect.height || 1));
|
|
3122
|
+
const coerceNum = (v, def = NaN) => {
|
|
3123
|
+
const n = typeof v === "string" ? parseFloat(v) : v;
|
|
3124
|
+
return Number.isFinite(n) ? n : def;
|
|
3125
|
+
};
|
|
3126
|
+
const optW = coerceNum(options.width);
|
|
3127
|
+
const optH = coerceNum(options.height);
|
|
3128
|
+
let w = w0, h = h0;
|
|
3129
|
+
const hasW = Number.isFinite(optW);
|
|
3130
|
+
const hasH = Number.isFinite(optH);
|
|
3131
|
+
const aspect0 = h0 > 0 ? w0 / h0 : 1;
|
|
3132
|
+
if (hasW && hasH) {
|
|
3133
|
+
w = Math.max(1, Math.ceil(optW));
|
|
3134
|
+
h = Math.max(1, Math.ceil(optH));
|
|
3135
|
+
} else if (hasW) {
|
|
3136
|
+
w = Math.max(1, Math.ceil(optW));
|
|
3137
|
+
h = Math.max(1, Math.ceil(w / (aspect0 || 1)));
|
|
3138
|
+
} else if (hasH) {
|
|
3139
|
+
h = Math.max(1, Math.ceil(optH));
|
|
3140
|
+
w = Math.max(1, Math.ceil(h * (aspect0 || 1)));
|
|
2911
3141
|
} else {
|
|
3142
|
+
w = w0;
|
|
3143
|
+
h = h0;
|
|
3144
|
+
}
|
|
3145
|
+
let minX = 0, minY = 0, maxX = w0, maxY = h0;
|
|
3146
|
+
if (hasTFBBox(element)) {
|
|
3147
|
+
const baseTransform2 = csEl.transform && csEl.transform !== "none" ? csEl.transform : "";
|
|
3148
|
+
const ind2 = readIndividualTransforms(element);
|
|
2912
3149
|
const TOTAL = readTotalTransformMatrix({
|
|
2913
|
-
baseTransform,
|
|
2914
|
-
rotate:
|
|
2915
|
-
scale:
|
|
2916
|
-
translate:
|
|
3150
|
+
baseTransform: baseTransform2,
|
|
3151
|
+
rotate: ind2.rotate || "0deg",
|
|
3152
|
+
scale: ind2.scale,
|
|
3153
|
+
translate: ind2.translate
|
|
2917
3154
|
});
|
|
2918
|
-
const
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
outH = Math.max(1, Math.ceil(bb.height));
|
|
2926
|
-
tx = -bb.minX;
|
|
2927
|
-
ty = -bb.minY;
|
|
3155
|
+
const { ox: ox2, oy: oy2 } = parseTransformOriginPx(csEl, w0, h0);
|
|
3156
|
+
const M = TOTAL.is2D ? TOTAL : new DOMMatrix(TOTAL.toString());
|
|
3157
|
+
const bb = bboxWithOriginFull(w0, h0, M, ox2, oy2);
|
|
3158
|
+
minX = bb.minX;
|
|
3159
|
+
minY = bb.minY;
|
|
3160
|
+
maxX = bb.maxX;
|
|
3161
|
+
maxY = bb.maxY;
|
|
2928
3162
|
}
|
|
3163
|
+
const bleedShadow = parseBoxShadow(csEl);
|
|
3164
|
+
const bleedBlur = parseFilterBlur(csEl);
|
|
3165
|
+
const bleedOutline = parseOutline(csEl);
|
|
3166
|
+
const drop = parseFilterDropShadows(csEl);
|
|
3167
|
+
const bleed = {
|
|
3168
|
+
top: bleedShadow.top + bleedBlur.top + bleedOutline.top + drop.bleed.top,
|
|
3169
|
+
right: bleedShadow.right + bleedBlur.right + bleedOutline.right + drop.bleed.right,
|
|
3170
|
+
bottom: bleedShadow.bottom + bleedBlur.bottom + bleedOutline.bottom + drop.bleed.bottom,
|
|
3171
|
+
left: bleedShadow.left + bleedBlur.left + bleedOutline.left + drop.bleed.left
|
|
3172
|
+
};
|
|
3173
|
+
minX -= bleed.left;
|
|
3174
|
+
minY -= bleed.top;
|
|
3175
|
+
maxX += bleed.right;
|
|
3176
|
+
maxY += bleed.bottom;
|
|
3177
|
+
const vbW0 = Math.max(1, Math.ceil(maxX - minX));
|
|
3178
|
+
const vbH0 = Math.max(1, Math.ceil(maxY - minY));
|
|
3179
|
+
const outW = Math.max(1, Math.round(vbW0 * (hasW || hasH ? w / w0 : 1)));
|
|
3180
|
+
const outH = Math.max(1, Math.round(vbH0 * (hasH || hasW ? h / h0 : 1)));
|
|
2929
3181
|
const svgNS = "http://www.w3.org/2000/svg";
|
|
3182
|
+
const pad = isSafari() ? 1 : 0;
|
|
2930
3183
|
const fo = document.createElementNS(svgNS, "foreignObject");
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
fo.setAttribute("x", String(
|
|
2934
|
-
fo.setAttribute("y", String(
|
|
3184
|
+
const vbMinX = Math.floor(minX);
|
|
3185
|
+
const vbMinY = Math.floor(minY);
|
|
3186
|
+
fo.setAttribute("x", String(-(vbMinX - pad)));
|
|
3187
|
+
fo.setAttribute("y", String(-(vbMinY - pad)));
|
|
3188
|
+
fo.setAttribute("width", String(Math.ceil(w0 + pad * 2)));
|
|
3189
|
+
fo.setAttribute("height", String(Math.ceil(h0 + pad * 2)));
|
|
2935
3190
|
fo.style.overflow = "visible";
|
|
2936
3191
|
const styleTag = document.createElement("style");
|
|
2937
3192
|
styleTag.textContent = baseCSS + fontsCSS + "svg{overflow:visible;} foreignObject{overflow:visible;}" + classCSS;
|
|
2938
3193
|
fo.appendChild(styleTag);
|
|
2939
3194
|
const container = document.createElement("div");
|
|
2940
3195
|
container.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
2941
|
-
container.style.width = `${
|
|
2942
|
-
container.style.height = `${
|
|
3196
|
+
container.style.width = `${w0}px`;
|
|
3197
|
+
container.style.height = `${h0}px`;
|
|
2943
3198
|
container.style.overflow = "visible";
|
|
2944
|
-
container.style.transformOrigin = "0 0";
|
|
2945
|
-
const cancels = [];
|
|
2946
|
-
if (cancelTranslateX || cancelTranslateY) {
|
|
2947
|
-
cancels.push(`translate(${cancelTranslateX}px, ${cancelTranslateY}px)`);
|
|
2948
|
-
}
|
|
2949
|
-
if (!hasScale && (hasW || hasH)) {
|
|
2950
|
-
const sxWH = rect.width ? w / rect.width : 1;
|
|
2951
|
-
const syWH = rect.height ? h / rect.height : 1;
|
|
2952
|
-
cancels.push(`scale(${sxWH}, ${syWH})`);
|
|
2953
|
-
} else if (hasScale) {
|
|
2954
|
-
cancels.push(`scale(${scaleOpt})`);
|
|
2955
|
-
}
|
|
2956
|
-
if (cancels.length) container.style.transform = cancels.join(" ");
|
|
2957
3199
|
clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
2958
|
-
clone.style.transformOrigin = "0 0";
|
|
2959
|
-
clone.style.position = "static";
|
|
2960
|
-
clone.style.left = "0";
|
|
2961
|
-
clone.style.top = "0";
|
|
2962
|
-
if (baseTransform) clone.style.transform = baseTransform;
|
|
2963
|
-
clone.style.rotate = ind.rotate || "0deg";
|
|
2964
|
-
clone.style.scale = ind.scale || "1";
|
|
2965
|
-
clone.style.translate = ind.translate || "0 0";
|
|
2966
3200
|
container.appendChild(clone);
|
|
2967
3201
|
fo.appendChild(container);
|
|
2968
3202
|
const serializer = new XMLSerializer();
|
|
2969
3203
|
const foString = serializer.serializeToString(fo);
|
|
2970
|
-
const
|
|
2971
|
-
const
|
|
2972
|
-
const
|
|
3204
|
+
const vbW = vbW0 + pad * 2;
|
|
3205
|
+
const vbH = vbH0 + pad * 2;
|
|
3206
|
+
const wantsSize = hasW || hasH;
|
|
3207
|
+
options.meta = {
|
|
3208
|
+
w0,
|
|
3209
|
+
// ancho natural del elemento
|
|
3210
|
+
h0,
|
|
3211
|
+
// alto natural
|
|
3212
|
+
vbW,
|
|
3213
|
+
// ancho del viewBox
|
|
3214
|
+
vbH,
|
|
3215
|
+
// alto del viewBox
|
|
3216
|
+
targetW: w,
|
|
3217
|
+
// ancho deseado según options.width
|
|
3218
|
+
targetH: h
|
|
3219
|
+
// alto deseado según options.height
|
|
3220
|
+
};
|
|
3221
|
+
const svgOutW = isSafari() && wantsSize ? vbW : outW + pad * 2;
|
|
3222
|
+
const svgOutH = isSafari() && wantsSize ? vbH : outH + pad * 2;
|
|
3223
|
+
const svgHeader = `<svg xmlns="${svgNS}" width="${svgOutW}" height="${svgOutH}" viewBox="0 0 ${vbW} ${vbH}">`;
|
|
2973
3224
|
const svgFooter = "</svg>";
|
|
2974
3225
|
svgString = svgHeader + foString + svgFooter;
|
|
2975
3226
|
dataURL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;
|
|
@@ -2990,28 +3241,8 @@
|
|
|
2990
3241
|
return new WebKitCSSMatrix(tr);
|
|
2991
3242
|
}
|
|
2992
3243
|
}
|
|
2993
|
-
function matrix2DNoTranslate(M) {
|
|
2994
|
-
return new DOMMatrix([M.a, M.b, M.c, M.d, 0, 0]);
|
|
2995
|
-
}
|
|
2996
|
-
function bboxFromMatrix(w, h, M2D) {
|
|
2997
|
-
const pts = [
|
|
2998
|
-
{ x: 0, y: 0 },
|
|
2999
|
-
{ x: w, y: 0 },
|
|
3000
|
-
{ x: 0, y: h },
|
|
3001
|
-
{ x: w, y: h }
|
|
3002
|
-
];
|
|
3003
|
-
const t = pts.map((p) => ({
|
|
3004
|
-
x: M2D.a * p.x + M2D.c * p.y,
|
|
3005
|
-
y: M2D.b * p.x + M2D.d * p.y
|
|
3006
|
-
}));
|
|
3007
|
-
const minX = Math.min(...t.map((p) => p.x));
|
|
3008
|
-
const maxX = Math.max(...t.map((p) => p.x));
|
|
3009
|
-
const minY = Math.min(...t.map((p) => p.y));
|
|
3010
|
-
const maxY = Math.max(...t.map((p) => p.y));
|
|
3011
|
-
return { minX, minY, width: maxX - minX, height: maxY - minY };
|
|
3012
|
-
}
|
|
3013
3244
|
function readIndividualTransforms(el) {
|
|
3014
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
3245
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3015
3246
|
const out = { rotate: "0deg", scale: null, translate: null };
|
|
3016
3247
|
const map = typeof el.computedStyleMap === "function" ? el.computedStyleMap() : null;
|
|
3017
3248
|
if (map) {
|
|
@@ -3026,26 +3257,37 @@
|
|
|
3026
3257
|
};
|
|
3027
3258
|
const rot = safeGet("rotate");
|
|
3028
3259
|
if (rot) {
|
|
3029
|
-
|
|
3030
|
-
|
|
3260
|
+
if (rot.angle) {
|
|
3261
|
+
const ang = rot.angle;
|
|
3031
3262
|
out.rotate = ang.unit === "rad" ? ang.value * 180 / Math.PI + "deg" : ang.value + ang.unit;
|
|
3263
|
+
} else if (rot.unit) {
|
|
3264
|
+
out.rotate = rot.unit === "rad" ? rot.value * 180 / Math.PI + "deg" : rot.value + rot.unit;
|
|
3032
3265
|
} else {
|
|
3033
3266
|
out.rotate = String(rot);
|
|
3034
3267
|
}
|
|
3268
|
+
} else {
|
|
3269
|
+
const cs2 = getComputedStyle(el);
|
|
3270
|
+
out.rotate = cs2.rotate && cs2.rotate !== "none" ? cs2.rotate : "0deg";
|
|
3035
3271
|
}
|
|
3036
3272
|
const sc = safeGet("scale");
|
|
3037
|
-
if (sc
|
|
3038
|
-
const sx = (
|
|
3039
|
-
const sy =
|
|
3273
|
+
if (sc) {
|
|
3274
|
+
const sx = "x" in sc && ((_a = sc.x) == null ? void 0 : _a.value) != null ? sc.x.value : Array.isArray(sc) ? (_b = sc[0]) == null ? void 0 : _b.value : Number(sc) || 1;
|
|
3275
|
+
const sy = "y" in sc && ((_c = sc.y) == null ? void 0 : _c.value) != null ? sc.y.value : Array.isArray(sc) ? (_d = sc[1]) == null ? void 0 : _d.value : sx;
|
|
3040
3276
|
out.scale = `${sx} ${sy}`;
|
|
3277
|
+
} else {
|
|
3278
|
+
const cs2 = getComputedStyle(el);
|
|
3279
|
+
out.scale = cs2.scale && cs2.scale !== "none" ? cs2.scale : null;
|
|
3041
3280
|
}
|
|
3042
3281
|
const tr = safeGet("translate");
|
|
3043
|
-
if (tr
|
|
3044
|
-
const tx = (
|
|
3045
|
-
const ty = (
|
|
3046
|
-
const ux =
|
|
3047
|
-
const uy =
|
|
3282
|
+
if (tr) {
|
|
3283
|
+
const tx = "x" in tr && "value" in tr.x ? tr.x.value : Array.isArray(tr) ? (_e = tr[0]) == null ? void 0 : _e.value : 0;
|
|
3284
|
+
const ty = "y" in tr && "value" in tr.y ? tr.y.value : Array.isArray(tr) ? (_f = tr[1]) == null ? void 0 : _f.value : 0;
|
|
3285
|
+
const ux = "x" in tr && ((_g = tr.x) == null ? void 0 : _g.unit) ? tr.x.unit : "px";
|
|
3286
|
+
const uy = "y" in tr && ((_h = tr.y) == null ? void 0 : _h.unit) ? tr.y.unit : "px";
|
|
3048
3287
|
out.translate = `${tx}${ux} ${ty}${uy}`;
|
|
3288
|
+
} else {
|
|
3289
|
+
const cs2 = getComputedStyle(el);
|
|
3290
|
+
out.translate = cs2.translate && cs2.translate !== "none" ? cs2.translate : null;
|
|
3049
3291
|
}
|
|
3050
3292
|
return out;
|
|
3051
3293
|
}
|
|
@@ -3056,17 +3298,33 @@
|
|
|
3056
3298
|
return out;
|
|
3057
3299
|
}
|
|
3058
3300
|
function hasBBoxAffectingTransform(el) {
|
|
3059
|
-
const
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
return true;
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3301
|
+
const cs = getComputedStyle(el);
|
|
3302
|
+
const t = cs.transform || "none";
|
|
3303
|
+
const hasMatrix = t !== "none" && !/^matrix\(\s*1\s*,\s*0\s*,\s*0\s*,\s*1\s*,\s*0\s*,\s*0\s*\)$/i.test(t);
|
|
3304
|
+
if (hasMatrix) return true;
|
|
3305
|
+
const r = cs.rotate && cs.rotate !== "none" && cs.rotate !== "0deg";
|
|
3306
|
+
const s = cs.scale && cs.scale !== "none" && cs.scale !== "1";
|
|
3307
|
+
const tr = cs.translate && cs.translate !== "none" && cs.translate !== "0px 0px";
|
|
3308
|
+
return Boolean(r || s || tr);
|
|
3309
|
+
}
|
|
3310
|
+
function parseTransformOriginPx(cs, w, h) {
|
|
3311
|
+
const raw = (cs.transformOrigin || "0 0").trim().split(/\s+/);
|
|
3312
|
+
const [oxRaw, oyRaw] = [raw[0] || "0", raw[1] || "0"];
|
|
3313
|
+
const toPx = (token, size) => {
|
|
3314
|
+
const t = token.toLowerCase();
|
|
3315
|
+
if (t === "left" || t === "top") return 0;
|
|
3316
|
+
if (t === "center") return size / 2;
|
|
3317
|
+
if (t === "right") return size;
|
|
3318
|
+
if (t === "bottom") return size;
|
|
3319
|
+
if (t.endsWith("px")) return parseFloat(t) || 0;
|
|
3320
|
+
if (t.endsWith("%")) return (parseFloat(t) || 0) * size / 100;
|
|
3321
|
+
if (/^-?\d+(\.\d+)?$/.test(t)) return parseFloat(t) || 0;
|
|
3322
|
+
return 0;
|
|
3323
|
+
};
|
|
3324
|
+
return {
|
|
3325
|
+
ox: toPx(oxRaw, w),
|
|
3326
|
+
oy: toPx(oyRaw, h)
|
|
3327
|
+
};
|
|
3070
3328
|
}
|
|
3071
3329
|
var __measureHost = null;
|
|
3072
3330
|
function getMeasureHost() {
|
|
@@ -3155,41 +3413,201 @@
|
|
|
3155
3413
|
};
|
|
3156
3414
|
}
|
|
3157
3415
|
|
|
3158
|
-
// src/exporters/
|
|
3159
|
-
function
|
|
3416
|
+
// src/exporters/toCanvas.js
|
|
3417
|
+
function isSvgDataURL(u) {
|
|
3418
|
+
return typeof u === "string" && /^data:image\/svg\+xml/i.test(u);
|
|
3419
|
+
}
|
|
3420
|
+
function decodeSvgFromDataURL(u) {
|
|
3421
|
+
const i = u.indexOf(",");
|
|
3422
|
+
return i >= 0 ? decodeURIComponent(u.slice(i + 1)) : "";
|
|
3423
|
+
}
|
|
3424
|
+
function encodeSvgToDataURL(svgText) {
|
|
3425
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgText)}`;
|
|
3426
|
+
}
|
|
3427
|
+
function splitDecls(s) {
|
|
3428
|
+
let parts = [], buf = "", depth = 0;
|
|
3429
|
+
for (let i = 0; i < s.length; i++) {
|
|
3430
|
+
const ch = s[i];
|
|
3431
|
+
if (ch === "(") depth++;
|
|
3432
|
+
if (ch === ")") depth = Math.max(0, depth - 1);
|
|
3433
|
+
if (ch === ";" && depth === 0) {
|
|
3434
|
+
parts.push(buf);
|
|
3435
|
+
buf = "";
|
|
3436
|
+
} else buf += ch;
|
|
3437
|
+
}
|
|
3438
|
+
if (buf.trim()) parts.push(buf);
|
|
3439
|
+
return parts.map((x) => x.trim()).filter(Boolean);
|
|
3440
|
+
}
|
|
3441
|
+
function boxShadowToDropShadow(value) {
|
|
3442
|
+
const layers = [];
|
|
3443
|
+
let buf = "", depth = 0;
|
|
3444
|
+
for (let i = 0; i < value.length; i++) {
|
|
3445
|
+
const ch = value[i];
|
|
3446
|
+
if (ch === "(") depth++;
|
|
3447
|
+
if (ch === ")") depth = Math.max(0, depth - 1);
|
|
3448
|
+
if (ch === "," && depth === 0) {
|
|
3449
|
+
layers.push(buf.trim());
|
|
3450
|
+
buf = "";
|
|
3451
|
+
} else buf += ch;
|
|
3452
|
+
}
|
|
3453
|
+
if (buf.trim()) layers.push(buf.trim());
|
|
3454
|
+
const fns = [];
|
|
3455
|
+
for (const layer of layers) {
|
|
3456
|
+
if (/\binset\b/i.test(layer)) continue;
|
|
3457
|
+
const nums = layer.match(/-?\d+(?:\.\d+)?px/gi) || [];
|
|
3458
|
+
const [ox = "0px", oy = "0px", blur = "0px"] = nums;
|
|
3459
|
+
let color = layer.replace(/-?\d+(?:\.\d+)?px/gi, "").replace(/\binset\b/ig, "").trim().replace(/\s{2,}/g, " ");
|
|
3460
|
+
const hasColor = !!color && color !== ",";
|
|
3461
|
+
fns.push(`drop-shadow(${ox} ${oy} ${blur}${hasColor ? ` ${color}` : ""})`);
|
|
3462
|
+
}
|
|
3463
|
+
return fns.join(" ");
|
|
3464
|
+
}
|
|
3465
|
+
function rewriteDeclList(list) {
|
|
3466
|
+
const decls = splitDecls(list);
|
|
3467
|
+
let filter = null, wfilter = null, box = null;
|
|
3468
|
+
const rest = [];
|
|
3469
|
+
for (const d of decls) {
|
|
3470
|
+
const idx = d.indexOf(":");
|
|
3471
|
+
if (idx < 0) continue;
|
|
3472
|
+
const prop = d.slice(0, idx).trim().toLowerCase();
|
|
3473
|
+
const val = d.slice(idx + 1).trim();
|
|
3474
|
+
if (prop === "box-shadow") box = val;
|
|
3475
|
+
else if (prop === "filter") filter = val;
|
|
3476
|
+
else if (prop === "-webkit-filter") wfilter = val;
|
|
3477
|
+
else rest.push([prop, val]);
|
|
3478
|
+
}
|
|
3479
|
+
if (box) {
|
|
3480
|
+
const ds = boxShadowToDropShadow(box);
|
|
3481
|
+
if (ds) {
|
|
3482
|
+
filter = filter ? `${filter} ${ds}` : ds;
|
|
3483
|
+
wfilter = wfilter ? `${wfilter} ${ds}` : ds;
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
const out = [...rest];
|
|
3487
|
+
if (filter) out.push(["filter", filter]);
|
|
3488
|
+
if (wfilter) out.push(["-webkit-filter", wfilter]);
|
|
3489
|
+
return out.map(([k, v]) => `${k}:${v}`).join(";");
|
|
3490
|
+
}
|
|
3491
|
+
function rewriteCssBlock(css) {
|
|
3492
|
+
return css.replace(/([^{}]+)\{([^}]*)\}/g, (_m, sel, body) => `${sel}{${rewriteDeclList(body)}}`);
|
|
3493
|
+
}
|
|
3494
|
+
function rewriteSvgBoxShadowToDropShadow(svgText) {
|
|
3495
|
+
svgText = svgText.replace(
|
|
3496
|
+
/<style[^>]*>([\s\S]*?)<\/style>/gi,
|
|
3497
|
+
(m, css) => m.replace(css, rewriteCssBlock(css))
|
|
3498
|
+
);
|
|
3499
|
+
svgText = svgText.replace(
|
|
3500
|
+
/style=(['"])([\s\S]*?)\1/gi,
|
|
3501
|
+
(m, q, body) => `style=${q}${rewriteDeclList(body)}${q}`
|
|
3502
|
+
);
|
|
3503
|
+
return svgText;
|
|
3504
|
+
}
|
|
3505
|
+
function maybeConvertBoxShadowForSafari(url) {
|
|
3506
|
+
if (!isSafari() || !isSvgDataURL(url)) return url;
|
|
3507
|
+
try {
|
|
3508
|
+
const svg = decodeSvgFromDataURL(url);
|
|
3509
|
+
const fixed = rewriteSvgBoxShadowToDropShadow(svg);
|
|
3510
|
+
return encodeSvgToDataURL(fixed);
|
|
3511
|
+
} catch (e) {
|
|
3512
|
+
return url;
|
|
3513
|
+
}
|
|
3514
|
+
}
|
|
3515
|
+
function toCanvas(url, options) {
|
|
3160
3516
|
return __async(this, null, function* () {
|
|
3517
|
+
let { width: optW, height: optH, scale = 1, dpr = 1, meta = {} } = options;
|
|
3518
|
+
url = maybeConvertBoxShadowForSafari(url);
|
|
3161
3519
|
const img = new Image();
|
|
3520
|
+
img.loading = "eager";
|
|
3521
|
+
img.decoding = "sync";
|
|
3522
|
+
img.crossOrigin = "anonymous";
|
|
3162
3523
|
img.src = url;
|
|
3163
3524
|
yield img.decode();
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3525
|
+
const natW = img.naturalWidth;
|
|
3526
|
+
const natH = img.naturalHeight;
|
|
3527
|
+
const refW = Number.isFinite(meta.w0) ? meta.w0 : natW;
|
|
3528
|
+
const refH = Number.isFinite(meta.h0) ? meta.h0 : natH;
|
|
3529
|
+
let outW, outH;
|
|
3530
|
+
const hasW = Number.isFinite(optW);
|
|
3531
|
+
const hasH = Number.isFinite(optH);
|
|
3532
|
+
if (hasW && hasH) {
|
|
3533
|
+
outW = Math.max(1, optW);
|
|
3534
|
+
outH = Math.max(1, optH);
|
|
3535
|
+
} else if (hasW) {
|
|
3536
|
+
const k = optW / Math.max(1, refW);
|
|
3537
|
+
outW = optW;
|
|
3538
|
+
outH = Math.round(refH * k);
|
|
3539
|
+
} else if (hasH) {
|
|
3540
|
+
const k = optH / Math.max(1, refH);
|
|
3541
|
+
outH = optH;
|
|
3542
|
+
outW = Math.round(refW * k);
|
|
3543
|
+
} else {
|
|
3544
|
+
outW = natW;
|
|
3545
|
+
outH = natH;
|
|
3167
3546
|
}
|
|
3547
|
+
outW = Math.round(outW * scale);
|
|
3548
|
+
outH = Math.round(outH * scale);
|
|
3549
|
+
const canvas = document.createElement("canvas");
|
|
3550
|
+
canvas.width = Math.ceil(outW * dpr);
|
|
3551
|
+
canvas.height = Math.ceil(outH * dpr);
|
|
3552
|
+
canvas.style.width = `${outW}px`;
|
|
3553
|
+
canvas.style.height = `${outH}px`;
|
|
3554
|
+
const ctx = canvas.getContext("2d");
|
|
3555
|
+
if (dpr !== 1) ctx.scale(dpr, dpr);
|
|
3556
|
+
ctx.drawImage(img, 0, 0, outW, outH);
|
|
3557
|
+
return canvas;
|
|
3558
|
+
});
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
// src/modules/rasterize.js
|
|
3562
|
+
function rasterize(url, options) {
|
|
3563
|
+
return __async(this, null, function* () {
|
|
3564
|
+
const canvas = yield toCanvas(url, options);
|
|
3565
|
+
const finalCanvas = options.backgroundColor ? createBackground(canvas, options.backgroundColor) : canvas;
|
|
3566
|
+
const img = new Image();
|
|
3567
|
+
img.src = finalCanvas.toDataURL(`image/${options.format}`, options.quality);
|
|
3568
|
+
yield img.decode();
|
|
3569
|
+
img.style.width = `${finalCanvas.width / options.dpr}px`;
|
|
3570
|
+
img.style.height = `${finalCanvas.height / options.dpr}px`;
|
|
3168
3571
|
return img;
|
|
3169
3572
|
});
|
|
3170
3573
|
}
|
|
3171
3574
|
|
|
3172
|
-
// src/exporters/
|
|
3173
|
-
function
|
|
3575
|
+
// src/exporters/toImg.js
|
|
3576
|
+
function toImg(url, options) {
|
|
3174
3577
|
return __async(this, null, function* () {
|
|
3175
|
-
const { scale,
|
|
3578
|
+
const { scale = 1, width, height, meta = {} } = options;
|
|
3579
|
+
const hasW = Number.isFinite(width);
|
|
3580
|
+
const hasH = Number.isFinite(height);
|
|
3581
|
+
const wantsScale = Number.isFinite(scale) && scale !== 1 || hasW || hasH;
|
|
3582
|
+
if (isSafari() && wantsScale) {
|
|
3583
|
+
const pngUrl = yield rasterize(url, __spreadProps(__spreadValues({}, options), { format: "png", quality: 1, meta }));
|
|
3584
|
+
return pngUrl;
|
|
3585
|
+
}
|
|
3176
3586
|
const img = new Image();
|
|
3177
|
-
img.crossOrigin = "anonymous";
|
|
3178
|
-
img.loading = "eager";
|
|
3179
3587
|
img.decoding = "sync";
|
|
3588
|
+
img.loading = "eager";
|
|
3180
3589
|
img.src = url;
|
|
3181
3590
|
yield img.decode();
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3591
|
+
if (hasW && hasH) {
|
|
3592
|
+
img.style.width = `${width}px`;
|
|
3593
|
+
img.style.height = `${height}px`;
|
|
3594
|
+
} else if (hasW) {
|
|
3595
|
+
const refW = Number.isFinite(meta.w0) ? meta.w0 : img.naturalWidth;
|
|
3596
|
+
const refH = Number.isFinite(meta.h0) ? meta.h0 : img.naturalHeight;
|
|
3597
|
+
const k = width / Math.max(1, refW);
|
|
3598
|
+
img.style.width = `${width}px`;
|
|
3599
|
+
img.style.height = `${Math.round(refH * k)}px`;
|
|
3600
|
+
} else if (hasH) {
|
|
3601
|
+
const refW = Number.isFinite(meta.w0) ? meta.w0 : img.naturalWidth;
|
|
3602
|
+
const refH = Number.isFinite(meta.h0) ? meta.h0 : img.naturalHeight;
|
|
3603
|
+
const k = height / Math.max(1, refH);
|
|
3604
|
+
img.style.height = `${height}px`;
|
|
3605
|
+
img.style.width = `${Math.round(refW * k)}px`;
|
|
3606
|
+
} else if (scale !== 1) {
|
|
3607
|
+
img.style.width = `${Math.round(img.naturalWidth * scale)}px`;
|
|
3608
|
+
img.style.height = `${Math.round(img.naturalHeight * scale)}px`;
|
|
3609
|
+
}
|
|
3610
|
+
return img;
|
|
3193
3611
|
});
|
|
3194
3612
|
}
|
|
3195
3613
|
|
|
@@ -3213,20 +3631,6 @@
|
|
|
3213
3631
|
});
|
|
3214
3632
|
}
|
|
3215
3633
|
|
|
3216
|
-
// src/modules/rasterize.js
|
|
3217
|
-
function rasterize(url, options) {
|
|
3218
|
-
return __async(this, null, function* () {
|
|
3219
|
-
const canvas = yield toCanvas(url, options);
|
|
3220
|
-
const finalCanvas = options.backgroundColor ? createBackground(canvas, options.backgroundColor) : canvas;
|
|
3221
|
-
const img = new Image();
|
|
3222
|
-
img.src = finalCanvas.toDataURL(`image/${options.format}`, options.quality);
|
|
3223
|
-
yield img.decode();
|
|
3224
|
-
img.style.width = `${finalCanvas.width / options.dpr}px`;
|
|
3225
|
-
img.style.height = `${finalCanvas.height / options.dpr}px`;
|
|
3226
|
-
return img;
|
|
3227
|
-
});
|
|
3228
|
-
}
|
|
3229
|
-
|
|
3230
3634
|
// src/exporters/download.js
|
|
3231
3635
|
function download(url, options) {
|
|
3232
3636
|
return __async(this, null, function* () {
|
|
@@ -3256,7 +3660,8 @@
|
|
|
3256
3660
|
function snapdom(element, userOptions) {
|
|
3257
3661
|
return __async(this, null, function* () {
|
|
3258
3662
|
if (!element) throw new Error("Element cannot be null or undefined");
|
|
3259
|
-
|
|
3663
|
+
const context = createContext(userOptions);
|
|
3664
|
+
if (isSafari() && (context.embedFonts === true || hasBackgroundOrMask(element))) {
|
|
3260
3665
|
for (let i = 0; i < 3; i++) {
|
|
3261
3666
|
try {
|
|
3262
3667
|
yield safariWarmup(element, userOptions);
|
|
@@ -3266,7 +3671,6 @@
|
|
|
3266
3671
|
}
|
|
3267
3672
|
}
|
|
3268
3673
|
}
|
|
3269
|
-
const context = createContext(userOptions);
|
|
3270
3674
|
if (context.iconFonts && context.iconFonts.length > 0) extendIconFonts(context.iconFonts);
|
|
3271
3675
|
if (!context.snap) {
|
|
3272
3676
|
context.snap = {
|
|
@@ -3348,6 +3752,20 @@
|
|
|
3348
3752
|
});
|
|
3349
3753
|
});
|
|
3350
3754
|
}
|
|
3755
|
+
function hasBackgroundOrMask(el) {
|
|
3756
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_ELEMENT);
|
|
3757
|
+
while (walker.nextNode()) {
|
|
3758
|
+
const node = (
|
|
3759
|
+
/** @type {Element} */
|
|
3760
|
+
walker.currentNode
|
|
3761
|
+
);
|
|
3762
|
+
const cs = getComputedStyle(node);
|
|
3763
|
+
const bg = cs.backgroundImage && cs.backgroundImage !== "none";
|
|
3764
|
+
const mask = cs.maskImage && cs.maskImage !== "none" || cs.webkitMaskImage && cs.webkitMaskImage !== "none";
|
|
3765
|
+
if (bg || mask) return true;
|
|
3766
|
+
}
|
|
3767
|
+
return false;
|
|
3768
|
+
}
|
|
3351
3769
|
|
|
3352
3770
|
// src/api/preCache.js
|
|
3353
3771
|
function preCache() {
|