@zumer/snapdom 2.0.0-dev.2 → 2.0.0-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 +718 -561
- package/dist/snapdom.min.js +8 -8
- package/dist/snapdom.min.mjs +8 -8
- package/dist/snapdom.mjs +711 -554
- package/package.json +1 -1
package/dist/snapdom.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/*
|
|
3
3
|
* snapdom
|
|
4
|
-
* v.2.0.0-dev.
|
|
4
|
+
* v.2.0.0-dev.3
|
|
5
5
|
* Author Juan Martin Muda
|
|
6
6
|
* License MIT
|
|
7
7
|
**/
|
|
@@ -972,7 +972,7 @@
|
|
|
972
972
|
}
|
|
973
973
|
}
|
|
974
974
|
|
|
975
|
-
// src/
|
|
975
|
+
// src/utils/clone.helpers.js
|
|
976
976
|
function idleCallback(childList, callback, fast) {
|
|
977
977
|
return Promise.all(childList.map((child) => {
|
|
978
978
|
return new Promise((resolve) => {
|
|
@@ -1189,6 +1189,143 @@
|
|
|
1189
1189
|
return wrapper;
|
|
1190
1190
|
});
|
|
1191
1191
|
}
|
|
1192
|
+
var _blobToDataUrlCache = /* @__PURE__ */ new Map();
|
|
1193
|
+
function blobUrlToDataUrl(blobUrl) {
|
|
1194
|
+
return __async(this, null, function* () {
|
|
1195
|
+
var _a;
|
|
1196
|
+
if ((_a = cache.resource) == null ? void 0 : _a.has(blobUrl)) return cache.resource.get(blobUrl);
|
|
1197
|
+
if (_blobToDataUrlCache.has(blobUrl)) return _blobToDataUrlCache.get(blobUrl);
|
|
1198
|
+
const p = (() => __async(null, null, function* () {
|
|
1199
|
+
var _a2;
|
|
1200
|
+
const r = yield snapFetch(blobUrl, { as: "dataURL", silent: true });
|
|
1201
|
+
if (!r.ok || typeof r.data !== "string") {
|
|
1202
|
+
throw new Error(`[snapDOM] Failed to read blob URL: ${blobUrl}`);
|
|
1203
|
+
}
|
|
1204
|
+
(_a2 = cache.resource) == null ? void 0 : _a2.set(blobUrl, r.data);
|
|
1205
|
+
return r.data;
|
|
1206
|
+
}))();
|
|
1207
|
+
_blobToDataUrlCache.set(blobUrl, p);
|
|
1208
|
+
try {
|
|
1209
|
+
const data = yield p;
|
|
1210
|
+
_blobToDataUrlCache.set(blobUrl, data);
|
|
1211
|
+
return data;
|
|
1212
|
+
} catch (e) {
|
|
1213
|
+
_blobToDataUrlCache.delete(blobUrl);
|
|
1214
|
+
throw e;
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
var BLOB_URL_RE = /\bblob:[^)"'\s]+/g;
|
|
1219
|
+
function replaceBlobUrlsInCssText(cssText) {
|
|
1220
|
+
return __async(this, null, function* () {
|
|
1221
|
+
if (!cssText || cssText.indexOf("blob:") === -1) return cssText;
|
|
1222
|
+
const uniques = Array.from(new Set(cssText.match(BLOB_URL_RE) || []));
|
|
1223
|
+
if (uniques.length === 0) return cssText;
|
|
1224
|
+
let out = cssText;
|
|
1225
|
+
for (const u of uniques) {
|
|
1226
|
+
try {
|
|
1227
|
+
const d = yield blobUrlToDataUrl(u);
|
|
1228
|
+
out = out.split(u).join(d);
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return out;
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
function isBlobUrl(u) {
|
|
1236
|
+
return typeof u === "string" && u.startsWith("blob:");
|
|
1237
|
+
}
|
|
1238
|
+
function parseSrcset(srcset) {
|
|
1239
|
+
return (srcset || "").split(",").map((s) => s.trim()).filter(Boolean).map((item) => {
|
|
1240
|
+
const m = item.match(/^(\S+)(\s+.+)?$/);
|
|
1241
|
+
return m ? { url: m[1], desc: m[2] || "" } : null;
|
|
1242
|
+
}).filter(Boolean);
|
|
1243
|
+
}
|
|
1244
|
+
function stringifySrcset(parts) {
|
|
1245
|
+
return parts.map((p) => p.desc ? `${p.url} ${p.desc.trim()}` : p.url).join(", ");
|
|
1246
|
+
}
|
|
1247
|
+
function resolveBlobUrlsInTree(root) {
|
|
1248
|
+
return __async(this, null, function* () {
|
|
1249
|
+
var _a, _b;
|
|
1250
|
+
if (!root) return;
|
|
1251
|
+
const imgs = root.querySelectorAll ? root.querySelectorAll("img") : [];
|
|
1252
|
+
for (const img of imgs) {
|
|
1253
|
+
try {
|
|
1254
|
+
const srcAttr = img.getAttribute("src");
|
|
1255
|
+
const effective = srcAttr || img.currentSrc || "";
|
|
1256
|
+
if (isBlobUrl(effective)) {
|
|
1257
|
+
const data = yield blobUrlToDataUrl(effective);
|
|
1258
|
+
img.setAttribute("src", data);
|
|
1259
|
+
}
|
|
1260
|
+
const srcset = img.getAttribute("srcset");
|
|
1261
|
+
if (srcset && srcset.includes("blob:")) {
|
|
1262
|
+
const parts = parseSrcset(srcset);
|
|
1263
|
+
let changed = false;
|
|
1264
|
+
for (const p of parts) {
|
|
1265
|
+
if (isBlobUrl(p.url)) {
|
|
1266
|
+
try {
|
|
1267
|
+
p.url = yield blobUrlToDataUrl(p.url);
|
|
1268
|
+
changed = true;
|
|
1269
|
+
} catch (e) {
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
if (changed) img.setAttribute("srcset", stringifySrcset(parts));
|
|
1274
|
+
}
|
|
1275
|
+
} catch (e) {
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
const svgImages = root.querySelectorAll ? root.querySelectorAll("image") : [];
|
|
1279
|
+
for (const node of svgImages) {
|
|
1280
|
+
try {
|
|
1281
|
+
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
1282
|
+
const href = node.getAttribute("href") || ((_a = node.getAttributeNS) == null ? void 0 : _a.call(node, XLINK_NS, "href"));
|
|
1283
|
+
if (isBlobUrl(href)) {
|
|
1284
|
+
const d = yield blobUrlToDataUrl(href);
|
|
1285
|
+
node.setAttribute("href", d);
|
|
1286
|
+
(_b = node.removeAttributeNS) == null ? void 0 : _b.call(node, XLINK_NS, "href");
|
|
1287
|
+
}
|
|
1288
|
+
} catch (e) {
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
const styled = root.querySelectorAll ? root.querySelectorAll("[style*='blob:']") : [];
|
|
1292
|
+
for (const el of styled) {
|
|
1293
|
+
try {
|
|
1294
|
+
const styleText = el.getAttribute("style");
|
|
1295
|
+
if (styleText && styleText.includes("blob:")) {
|
|
1296
|
+
const replaced = yield replaceBlobUrlsInCssText(styleText);
|
|
1297
|
+
el.setAttribute("style", replaced);
|
|
1298
|
+
}
|
|
1299
|
+
} catch (e) {
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
const styleTags = root.querySelectorAll ? root.querySelectorAll("style") : [];
|
|
1303
|
+
for (const s of styleTags) {
|
|
1304
|
+
try {
|
|
1305
|
+
const css = s.textContent || "";
|
|
1306
|
+
if (css.includes("blob:")) {
|
|
1307
|
+
s.textContent = yield replaceBlobUrlsInCssText(css);
|
|
1308
|
+
}
|
|
1309
|
+
} catch (e) {
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
const urlAttrs = ["poster"];
|
|
1313
|
+
for (const attr of urlAttrs) {
|
|
1314
|
+
const nodes = root.querySelectorAll ? root.querySelectorAll(`[${attr}^='blob:']`) : [];
|
|
1315
|
+
for (const n of nodes) {
|
|
1316
|
+
try {
|
|
1317
|
+
const u = n.getAttribute(attr);
|
|
1318
|
+
if (isBlobUrl(u)) {
|
|
1319
|
+
n.setAttribute(attr, yield blobUrlToDataUrl(u));
|
|
1320
|
+
}
|
|
1321
|
+
} catch (e) {
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/core/clone.js
|
|
1192
1329
|
function deepClone(node, sessionCache, options) {
|
|
1193
1330
|
return __async(this, null, function* () {
|
|
1194
1331
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -2691,6 +2828,152 @@ ${imported}
|
|
|
2691
2828
|
}
|
|
2692
2829
|
|
|
2693
2830
|
// src/modules/pseudo.js
|
|
2831
|
+
var __preflightMemo = /* @__PURE__ */ new WeakMap();
|
|
2832
|
+
var CSS_RULE_SCAN_BUDGET = 300;
|
|
2833
|
+
function preflightWithFp(doc, sessionCache) {
|
|
2834
|
+
const fp = styleFingerprint(doc);
|
|
2835
|
+
if (!sessionCache) return shouldProcessPseudos(doc);
|
|
2836
|
+
if (sessionCache.__pseudoPreflightFp !== fp) {
|
|
2837
|
+
sessionCache.__pseudoPreflight = shouldProcessPseudos(doc);
|
|
2838
|
+
sessionCache.__pseudoPreflightFp = fp;
|
|
2839
|
+
}
|
|
2840
|
+
return !!sessionCache.__pseudoPreflight;
|
|
2841
|
+
}
|
|
2842
|
+
function safeRules(sheet) {
|
|
2843
|
+
try {
|
|
2844
|
+
return sheet && sheet.cssRules ? sheet.cssRules : null;
|
|
2845
|
+
} catch (e) {
|
|
2846
|
+
return null;
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
function styleFingerprint(doc) {
|
|
2850
|
+
const nodes = doc.querySelectorAll('style,link[rel~="stylesheet"]');
|
|
2851
|
+
let fp = `n:${nodes.length}|`;
|
|
2852
|
+
let totalRules = 0;
|
|
2853
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2854
|
+
const n = nodes[i];
|
|
2855
|
+
if (n.tagName === "STYLE") {
|
|
2856
|
+
const len = n.textContent ? n.textContent.length : 0;
|
|
2857
|
+
fp += `S${len}|`;
|
|
2858
|
+
const sheet = (
|
|
2859
|
+
/** @type {HTMLStyleElement} */
|
|
2860
|
+
n.sheet
|
|
2861
|
+
);
|
|
2862
|
+
const rules = sheet ? safeRules(sheet) : null;
|
|
2863
|
+
if (rules) totalRules += rules.length;
|
|
2864
|
+
} else {
|
|
2865
|
+
const href = n.getAttribute("href") || "";
|
|
2866
|
+
const media = n.getAttribute("media") || "all";
|
|
2867
|
+
fp += `L${href}|m:${media}|`;
|
|
2868
|
+
const sheet = (
|
|
2869
|
+
/** @type {HTMLLinkElement} */
|
|
2870
|
+
n.sheet
|
|
2871
|
+
);
|
|
2872
|
+
const rules = sheet ? safeRules(sheet) : null;
|
|
2873
|
+
if (rules) totalRules += rules.length;
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
const ass = (
|
|
2877
|
+
/** @type {any} */
|
|
2878
|
+
doc.adoptedStyleSheets
|
|
2879
|
+
);
|
|
2880
|
+
fp += `ass:${Array.isArray(ass) ? ass.length : 0}|tr:${totalRules}`;
|
|
2881
|
+
return fp;
|
|
2882
|
+
}
|
|
2883
|
+
function sheetHasNeedles(sheet, needles, state) {
|
|
2884
|
+
const rules = safeRules(sheet);
|
|
2885
|
+
if (!rules) return false;
|
|
2886
|
+
for (let i = 0; i < rules.length; i++) {
|
|
2887
|
+
if (state.budget <= 0) return false;
|
|
2888
|
+
const rule = rules[i];
|
|
2889
|
+
const css = rule && rule.cssText ? rule.cssText : "";
|
|
2890
|
+
state.budget--;
|
|
2891
|
+
for (const k of needles) {
|
|
2892
|
+
if (css.includes(k)) return true;
|
|
2893
|
+
}
|
|
2894
|
+
if (rule && rule.cssRules && rule.cssRules.length) {
|
|
2895
|
+
for (let j = 0; j < rule.cssRules.length && state.budget > 0; j++) {
|
|
2896
|
+
const inner = rule.cssRules[j];
|
|
2897
|
+
const innerCss = inner && inner.cssText ? inner.cssText : "";
|
|
2898
|
+
state.budget--;
|
|
2899
|
+
for (const k of needles) {
|
|
2900
|
+
if (innerCss.includes(k)) return true;
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
if (state.budget <= 0) return false;
|
|
2905
|
+
}
|
|
2906
|
+
return false;
|
|
2907
|
+
}
|
|
2908
|
+
function shouldProcessPseudos(doc = document) {
|
|
2909
|
+
const fp = styleFingerprint(doc);
|
|
2910
|
+
const memo = __preflightMemo.get(doc);
|
|
2911
|
+
if (memo && memo.fingerprint === fp) return memo.result;
|
|
2912
|
+
const NEEDLES = [
|
|
2913
|
+
// double-colon
|
|
2914
|
+
"::before",
|
|
2915
|
+
"::after",
|
|
2916
|
+
"::first-letter",
|
|
2917
|
+
// single-colon robustness
|
|
2918
|
+
":before",
|
|
2919
|
+
":after",
|
|
2920
|
+
":first-letter",
|
|
2921
|
+
// counters
|
|
2922
|
+
"counter(",
|
|
2923
|
+
"counters(",
|
|
2924
|
+
"counter-increment",
|
|
2925
|
+
"counter-reset"
|
|
2926
|
+
];
|
|
2927
|
+
const styleEls = doc.querySelectorAll("style");
|
|
2928
|
+
for (let i = 0; i < styleEls.length; i++) {
|
|
2929
|
+
const t = styleEls[i].textContent || "";
|
|
2930
|
+
for (const k of NEEDLES) if (t.includes(k)) {
|
|
2931
|
+
__preflightMemo.set(doc, { fingerprint: fp, result: true });
|
|
2932
|
+
return true;
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
const ass = (
|
|
2936
|
+
/** @type {any} */
|
|
2937
|
+
doc.adoptedStyleSheets
|
|
2938
|
+
);
|
|
2939
|
+
if (Array.isArray(ass) && ass.length) {
|
|
2940
|
+
const state = { budget: CSS_RULE_SCAN_BUDGET };
|
|
2941
|
+
try {
|
|
2942
|
+
for (const sheet of ass) {
|
|
2943
|
+
if (sheetHasNeedles(sheet, NEEDLES, state)) {
|
|
2944
|
+
__preflightMemo.set(doc, { fingerprint: fp, result: true });
|
|
2945
|
+
return true;
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
} catch (e) {
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
{
|
|
2952
|
+
const nodes = doc.querySelectorAll('style,link[rel~="stylesheet"]');
|
|
2953
|
+
const state = { budget: CSS_RULE_SCAN_BUDGET };
|
|
2954
|
+
for (let i = 0; i < nodes.length && state.budget > 0; i++) {
|
|
2955
|
+
const n = nodes[i];
|
|
2956
|
+
let sheet = null;
|
|
2957
|
+
if (n.tagName === "STYLE") {
|
|
2958
|
+
sheet = /** @type {HTMLStyleElement} */
|
|
2959
|
+
n.sheet || null;
|
|
2960
|
+
} else {
|
|
2961
|
+
sheet = /** @type {HTMLLinkElement} */
|
|
2962
|
+
n.sheet || null;
|
|
2963
|
+
}
|
|
2964
|
+
if (sheet && sheetHasNeedles(sheet, NEEDLES, state)) {
|
|
2965
|
+
__preflightMemo.set(doc, { fingerprint: fp, result: true });
|
|
2966
|
+
return true;
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
}
|
|
2970
|
+
if (doc.querySelector('[style*="counter("], [style*="counters("]')) {
|
|
2971
|
+
__preflightMemo.set(doc, { fingerprint: fp, result: true });
|
|
2972
|
+
return true;
|
|
2973
|
+
}
|
|
2974
|
+
__preflightMemo.set(doc, { fingerprint: fp, result: false });
|
|
2975
|
+
return false;
|
|
2976
|
+
}
|
|
2694
2977
|
var __siblingCounters = /* @__PURE__ */ new WeakMap();
|
|
2695
2978
|
var __pseudoEpoch = -1;
|
|
2696
2979
|
function unquoteDoubleStrings2(s) {
|
|
@@ -2789,8 +3072,12 @@ ${imported}
|
|
|
2789
3072
|
}
|
|
2790
3073
|
function inlinePseudoElements(source, clone, sessionCache, options) {
|
|
2791
3074
|
return __async(this, null, function* () {
|
|
2792
|
-
var _a, _b, _c, _d;
|
|
3075
|
+
var _a, _b, _c, _d, _e;
|
|
2793
3076
|
if (!(source instanceof Element) || !(clone instanceof Element)) return;
|
|
3077
|
+
const doc = source.ownerDocument || document;
|
|
3078
|
+
if (!preflightWithFp(doc, sessionCache)) {
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
2794
3081
|
const epoch = (_c = (_b = (_a = cache) == null ? void 0 : _a.session) == null ? void 0 : _b.__counterEpoch) != null ? _c : 0;
|
|
2795
3082
|
if (__pseudoEpoch !== epoch) {
|
|
2796
3083
|
__siblingCounters = /* @__PURE__ */ new WeakMap();
|
|
@@ -2807,7 +3094,7 @@ ${imported}
|
|
|
2807
3094
|
for (const pseudo of ["::before", "::after", "::first-letter"]) {
|
|
2808
3095
|
try {
|
|
2809
3096
|
const style = getStyle(source, pseudo);
|
|
2810
|
-
if (!style
|
|
3097
|
+
if (!style) continue;
|
|
2811
3098
|
const isEmptyPseudo = style.content === "none" && style.backgroundImage === "none" && style.backgroundColor === "transparent" && (style.borderStyle === "none" || parseFloat(style.borderWidth) === 0) && (!style.transform || style.transform === "none") && style.display === "inline";
|
|
2812
3099
|
if (isEmptyPseudo) continue;
|
|
2813
3100
|
if (pseudo === "::first-letter") {
|
|
@@ -2837,7 +3124,8 @@ ${imported}
|
|
|
2837
3124
|
clone.insertBefore(span, restNode);
|
|
2838
3125
|
continue;
|
|
2839
3126
|
}
|
|
2840
|
-
const rawContent = style.content;
|
|
3127
|
+
const rawContent = (_d = style.content) != null ? _d : "";
|
|
3128
|
+
const isNoExplicitContent = rawContent === "" || rawContent === "none" || rawContent === "normal";
|
|
2841
3129
|
const { text: cleanContent, incs } = resolvePseudoContentAndIncs(source, pseudo, counterCtx);
|
|
2842
3130
|
const bg = style.backgroundImage;
|
|
2843
3131
|
const bgColor = style.backgroundColor;
|
|
@@ -2849,7 +3137,7 @@ ${imported}
|
|
|
2849
3137
|
const borderWidth = parseFloat(style.borderWidth);
|
|
2850
3138
|
const transform = style.transform;
|
|
2851
3139
|
const isIconFont22 = isIconFont2(fontFamily);
|
|
2852
|
-
const hasExplicitContent =
|
|
3140
|
+
const hasExplicitContent = !isNoExplicitContent && cleanContent !== "";
|
|
2853
3141
|
const hasBg = bg && bg !== "none";
|
|
2854
3142
|
const hasBgColor = bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)";
|
|
2855
3143
|
const hasBorder = borderStyle && borderStyle !== "none" && borderWidth > 0;
|
|
@@ -2871,8 +3159,6 @@ ${imported}
|
|
|
2871
3159
|
}
|
|
2872
3160
|
const pseudoEl = document.createElement("span");
|
|
2873
3161
|
pseudoEl.dataset.snapdomPseudo = pseudo;
|
|
2874
|
-
pseudoEl.style.display = "inline";
|
|
2875
|
-
pseudoEl.style.verticalAlign = "baseline";
|
|
2876
3162
|
pseudoEl.style.pointerEvents = "none";
|
|
2877
3163
|
const snapshot = snapshotComputedStyle(style);
|
|
2878
3164
|
const key = getStyleKey(snapshot, "span");
|
|
@@ -2928,7 +3214,7 @@ ${imported}
|
|
|
2928
3214
|
}
|
|
2929
3215
|
}
|
|
2930
3216
|
if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
|
|
2931
|
-
const hasContent2 = pseudoEl.childNodes.length > 0 || ((
|
|
3217
|
+
const hasContent2 = pseudoEl.childNodes.length > 0 || ((_e = pseudoEl.textContent) == null ? void 0 : _e.trim()) !== "";
|
|
2932
3218
|
const hasVisibleBox = hasContent2 || hasBg || hasBgColor || hasBorder || hasTransform;
|
|
2933
3219
|
if (incs && incs.length && source.parentElement) {
|
|
2934
3220
|
const map = __siblingCounters.get(source.parentElement) || /* @__PURE__ */ new Map();
|
|
@@ -3167,6 +3453,20 @@ ${imported}
|
|
|
3167
3453
|
return out;
|
|
3168
3454
|
}
|
|
3169
3455
|
|
|
3456
|
+
// src/utils/prepare.helpers.js
|
|
3457
|
+
function stabilizeLayout(element) {
|
|
3458
|
+
const style = getComputedStyle(element);
|
|
3459
|
+
const outlineStyle = style.outlineStyle;
|
|
3460
|
+
const outlineWidth = style.outlineWidth;
|
|
3461
|
+
const borderStyle = style.borderStyle;
|
|
3462
|
+
const borderWidth = style.borderWidth;
|
|
3463
|
+
const outlineVisible = outlineStyle !== "none" && parseFloat(outlineWidth) > 0;
|
|
3464
|
+
const borderAbsent = borderStyle === "none" || parseFloat(borderWidth) === 0;
|
|
3465
|
+
if (outlineVisible && borderAbsent) {
|
|
3466
|
+
element.style.border = `${outlineWidth} solid transparent`;
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
|
|
3170
3470
|
// src/core/prepare.js
|
|
3171
3471
|
function prepareClone(_0) {
|
|
3172
3472
|
return __async(this, arguments, function* (element, options = {}) {
|
|
@@ -3270,163 +3570,27 @@ ${imported}
|
|
|
3270
3570
|
return { clone, classCSS, styleCache: sessionCache.styleCache };
|
|
3271
3571
|
});
|
|
3272
3572
|
}
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
const
|
|
3278
|
-
const
|
|
3279
|
-
const
|
|
3280
|
-
const
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
function blobUrlToDataUrl(blobUrl) {
|
|
3287
|
-
return __async(this, null, function* () {
|
|
3288
|
-
var _a;
|
|
3289
|
-
if ((_a = cache.resource) == null ? void 0 : _a.has(blobUrl)) return cache.resource.get(blobUrl);
|
|
3290
|
-
if (_blobToDataUrlCache.has(blobUrl)) return _blobToDataUrlCache.get(blobUrl);
|
|
3291
|
-
const p = (() => __async(null, null, function* () {
|
|
3292
|
-
var _a2;
|
|
3293
|
-
const r = yield snapFetch(blobUrl, { as: "dataURL", silent: true });
|
|
3294
|
-
if (!r.ok || typeof r.data !== "string") {
|
|
3295
|
-
throw new Error(`[snapDOM] Failed to read blob URL: ${blobUrl}`);
|
|
3296
|
-
}
|
|
3297
|
-
(_a2 = cache.resource) == null ? void 0 : _a2.set(blobUrl, r.data);
|
|
3298
|
-
return r.data;
|
|
3299
|
-
}))();
|
|
3300
|
-
_blobToDataUrlCache.set(blobUrl, p);
|
|
3301
|
-
try {
|
|
3302
|
-
const data = yield p;
|
|
3303
|
-
_blobToDataUrlCache.set(blobUrl, data);
|
|
3304
|
-
return data;
|
|
3305
|
-
} catch (e) {
|
|
3306
|
-
_blobToDataUrlCache.delete(blobUrl);
|
|
3307
|
-
throw e;
|
|
3308
|
-
}
|
|
3309
|
-
});
|
|
3573
|
+
|
|
3574
|
+
// src/modules/images.js
|
|
3575
|
+
function extractImageDimensions(img) {
|
|
3576
|
+
var _a, _b, _c, _d;
|
|
3577
|
+
const dsW = parseInt(((_a = img.dataset) == null ? void 0 : _a.snapdomWidth) || "", 10) || 0;
|
|
3578
|
+
const dsH = parseInt(((_b = img.dataset) == null ? void 0 : _b.snapdomHeight) || "", 10) || 0;
|
|
3579
|
+
const attrW = parseInt(img.getAttribute("width") || "", 10) || 0;
|
|
3580
|
+
const attrH = parseInt(img.getAttribute("height") || "", 10) || 0;
|
|
3581
|
+
const styleW = parseFloat(((_c = img.style) == null ? void 0 : _c.width) || "") || 0;
|
|
3582
|
+
const styleH = parseFloat(((_d = img.style) == null ? void 0 : _d.height) || "") || 0;
|
|
3583
|
+
const w = dsW || styleW || attrW || img.width || img.naturalWidth || 100;
|
|
3584
|
+
const h = dsH || styleH || attrH || img.height || img.naturalHeight || 100;
|
|
3585
|
+
return { width: w, height: h };
|
|
3310
3586
|
}
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
for (const u of uniques) {
|
|
3319
|
-
try {
|
|
3320
|
-
const d = yield blobUrlToDataUrl(u);
|
|
3321
|
-
out = out.split(u).join(d);
|
|
3322
|
-
} catch (e) {
|
|
3323
|
-
}
|
|
3324
|
-
}
|
|
3325
|
-
return out;
|
|
3326
|
-
});
|
|
3327
|
-
}
|
|
3328
|
-
function isBlobUrl(u) {
|
|
3329
|
-
return typeof u === "string" && u.startsWith("blob:");
|
|
3330
|
-
}
|
|
3331
|
-
function parseSrcset(srcset) {
|
|
3332
|
-
return (srcset || "").split(",").map((s) => s.trim()).filter(Boolean).map((item) => {
|
|
3333
|
-
const m = item.match(/^(\S+)(\s+.+)?$/);
|
|
3334
|
-
return m ? { url: m[1], desc: m[2] || "" } : null;
|
|
3335
|
-
}).filter(Boolean);
|
|
3336
|
-
}
|
|
3337
|
-
function stringifySrcset(parts) {
|
|
3338
|
-
return parts.map((p) => p.desc ? `${p.url} ${p.desc.trim()}` : p.url).join(", ");
|
|
3339
|
-
}
|
|
3340
|
-
function resolveBlobUrlsInTree(root) {
|
|
3341
|
-
return __async(this, null, function* () {
|
|
3342
|
-
var _a, _b;
|
|
3343
|
-
if (!root) return;
|
|
3344
|
-
const imgs = root.querySelectorAll ? root.querySelectorAll("img") : [];
|
|
3345
|
-
for (const img of imgs) {
|
|
3346
|
-
try {
|
|
3347
|
-
const srcAttr = img.getAttribute("src");
|
|
3348
|
-
const effective = srcAttr || img.currentSrc || "";
|
|
3349
|
-
if (isBlobUrl(effective)) {
|
|
3350
|
-
const data = yield blobUrlToDataUrl(effective);
|
|
3351
|
-
img.setAttribute("src", data);
|
|
3352
|
-
}
|
|
3353
|
-
const srcset = img.getAttribute("srcset");
|
|
3354
|
-
if (srcset && srcset.includes("blob:")) {
|
|
3355
|
-
const parts = parseSrcset(srcset);
|
|
3356
|
-
let changed = false;
|
|
3357
|
-
for (const p of parts) {
|
|
3358
|
-
if (isBlobUrl(p.url)) {
|
|
3359
|
-
try {
|
|
3360
|
-
p.url = yield blobUrlToDataUrl(p.url);
|
|
3361
|
-
changed = true;
|
|
3362
|
-
} catch (e) {
|
|
3363
|
-
}
|
|
3364
|
-
}
|
|
3365
|
-
}
|
|
3366
|
-
if (changed) img.setAttribute("srcset", stringifySrcset(parts));
|
|
3367
|
-
}
|
|
3368
|
-
} catch (e) {
|
|
3369
|
-
}
|
|
3370
|
-
}
|
|
3371
|
-
const svgImages = root.querySelectorAll ? root.querySelectorAll("image") : [];
|
|
3372
|
-
for (const node of svgImages) {
|
|
3373
|
-
try {
|
|
3374
|
-
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
3375
|
-
const href = node.getAttribute("href") || ((_a = node.getAttributeNS) == null ? void 0 : _a.call(node, XLINK_NS, "href"));
|
|
3376
|
-
if (isBlobUrl(href)) {
|
|
3377
|
-
const d = yield blobUrlToDataUrl(href);
|
|
3378
|
-
node.setAttribute("href", d);
|
|
3379
|
-
(_b = node.removeAttributeNS) == null ? void 0 : _b.call(node, XLINK_NS, "href");
|
|
3380
|
-
}
|
|
3381
|
-
} catch (e) {
|
|
3382
|
-
}
|
|
3383
|
-
}
|
|
3384
|
-
const styled = root.querySelectorAll ? root.querySelectorAll("[style*='blob:']") : [];
|
|
3385
|
-
for (const el of styled) {
|
|
3386
|
-
try {
|
|
3387
|
-
const styleText = el.getAttribute("style");
|
|
3388
|
-
if (styleText && styleText.includes("blob:")) {
|
|
3389
|
-
const replaced = yield replaceBlobUrlsInCssText(styleText);
|
|
3390
|
-
el.setAttribute("style", replaced);
|
|
3391
|
-
}
|
|
3392
|
-
} catch (e) {
|
|
3393
|
-
}
|
|
3394
|
-
}
|
|
3395
|
-
const styleTags = root.querySelectorAll ? root.querySelectorAll("style") : [];
|
|
3396
|
-
for (const s of styleTags) {
|
|
3397
|
-
try {
|
|
3398
|
-
const css = s.textContent || "";
|
|
3399
|
-
if (css.includes("blob:")) {
|
|
3400
|
-
s.textContent = yield replaceBlobUrlsInCssText(css);
|
|
3401
|
-
}
|
|
3402
|
-
} catch (e) {
|
|
3403
|
-
}
|
|
3404
|
-
}
|
|
3405
|
-
const urlAttrs = ["poster"];
|
|
3406
|
-
for (const attr of urlAttrs) {
|
|
3407
|
-
const nodes = root.querySelectorAll ? root.querySelectorAll(`[${attr}^='blob:']`) : [];
|
|
3408
|
-
for (const n of nodes) {
|
|
3409
|
-
try {
|
|
3410
|
-
const u = n.getAttribute(attr);
|
|
3411
|
-
if (isBlobUrl(u)) {
|
|
3412
|
-
n.setAttribute(attr, yield blobUrlToDataUrl(u));
|
|
3413
|
-
}
|
|
3414
|
-
} catch (e) {
|
|
3415
|
-
}
|
|
3416
|
-
}
|
|
3417
|
-
}
|
|
3418
|
-
});
|
|
3419
|
-
}
|
|
3420
|
-
|
|
3421
|
-
// src/modules/images.js
|
|
3422
|
-
function inlineImages(_0) {
|
|
3423
|
-
return __async(this, arguments, function* (clone, options = {}) {
|
|
3424
|
-
const imgs = Array.from(clone.querySelectorAll("img"));
|
|
3425
|
-
const processImg = (img) => __async(null, null, function* () {
|
|
3426
|
-
var _a, _b, _c, _d;
|
|
3427
|
-
if (!img.getAttribute("src")) {
|
|
3428
|
-
const eff = img.currentSrc || img.src || "";
|
|
3429
|
-
if (eff) img.setAttribute("src", eff);
|
|
3587
|
+
function inlineImages(_0) {
|
|
3588
|
+
return __async(this, arguments, function* (clone, options = {}) {
|
|
3589
|
+
const imgs = Array.from(clone.querySelectorAll("img"));
|
|
3590
|
+
const processImg = (img) => __async(null, null, function* () {
|
|
3591
|
+
if (!img.getAttribute("src")) {
|
|
3592
|
+
const eff = img.currentSrc || img.src || "";
|
|
3593
|
+
if (eff) img.setAttribute("src", eff);
|
|
3430
3594
|
}
|
|
3431
3595
|
img.removeAttribute("srcset");
|
|
3432
3596
|
img.removeAttribute("sizes");
|
|
@@ -3439,41 +3603,30 @@ ${imported}
|
|
|
3439
3603
|
if (!img.height) img.height = img.naturalHeight || 100;
|
|
3440
3604
|
return;
|
|
3441
3605
|
}
|
|
3606
|
+
const { width: fbW, height: fbH } = extractImageDimensions(img);
|
|
3442
3607
|
const { fallbackURL } = options || {};
|
|
3443
3608
|
if (fallbackURL) {
|
|
3444
3609
|
try {
|
|
3445
|
-
const dsW = parseInt(((_a = img.dataset) == null ? void 0 : _a.snapdomWidth) || "", 10) || 0;
|
|
3446
|
-
const dsH = parseInt(((_b = img.dataset) == null ? void 0 : _b.snapdomHeight) || "", 10) || 0;
|
|
3447
|
-
const attrW = parseInt(img.getAttribute("width") || "", 10) || 0;
|
|
3448
|
-
const attrH = parseInt(img.getAttribute("height") || "", 10) || 0;
|
|
3449
|
-
const styleW = parseFloat(((_c = img.style) == null ? void 0 : _c.width) || "") || 0;
|
|
3450
|
-
const styleH = parseFloat(((_d = img.style) == null ? void 0 : _d.height) || "") || 0;
|
|
3451
|
-
const fbW = dsW || styleW || attrW || img.width || void 0;
|
|
3452
|
-
const fbH = dsH || styleH || attrH || img.height || void 0;
|
|
3453
3610
|
const fallbackUrl = typeof fallbackURL === "function" ? yield fallbackURL({ width: fbW, height: fbH, src, element: img }) : fallbackURL;
|
|
3454
3611
|
if (fallbackUrl) {
|
|
3455
3612
|
const fallbackData = yield snapFetch(fallbackUrl, { as: "dataURL", useProxy: options.useProxy });
|
|
3456
3613
|
img.src = fallbackData.data;
|
|
3457
|
-
if (!img.width
|
|
3458
|
-
if (!img.height
|
|
3459
|
-
if (!img.width) img.width = img.naturalWidth || 100;
|
|
3460
|
-
if (!img.height) img.height = img.naturalHeight || 100;
|
|
3614
|
+
if (!img.width) img.width = fbW;
|
|
3615
|
+
if (!img.height) img.height = fbH;
|
|
3461
3616
|
return;
|
|
3462
3617
|
}
|
|
3463
3618
|
} catch (e) {
|
|
3464
3619
|
}
|
|
3465
3620
|
}
|
|
3466
|
-
const w = img.width || img.naturalWidth || 100;
|
|
3467
|
-
const h = img.height || img.naturalHeight || 100;
|
|
3468
3621
|
if (options.placeholders !== false) {
|
|
3469
3622
|
const fallback = document.createElement("div");
|
|
3470
3623
|
fallback.style.cssText = [
|
|
3471
|
-
`width:${
|
|
3472
|
-
`height:${
|
|
3624
|
+
`width:${fbW}px`,
|
|
3625
|
+
`height:${fbH}px`,
|
|
3473
3626
|
"background:#ccc",
|
|
3474
3627
|
"display:inline-block",
|
|
3475
3628
|
"text-align:center",
|
|
3476
|
-
`line-height:${
|
|
3629
|
+
`line-height:${fbH}px`,
|
|
3477
3630
|
"color:#666",
|
|
3478
3631
|
"font-size:12px",
|
|
3479
3632
|
"overflow:hidden"
|
|
@@ -3482,7 +3635,7 @@ ${imported}
|
|
|
3482
3635
|
img.replaceWith(fallback);
|
|
3483
3636
|
} else {
|
|
3484
3637
|
const spacer = document.createElement("div");
|
|
3485
|
-
spacer.style.cssText = `display:inline-block;width:${
|
|
3638
|
+
spacer.style.cssText = `display:inline-block;width:${fbW}px;height:${fbH}px;visibility:hidden;`;
|
|
3486
3639
|
img.replaceWith(spacer);
|
|
3487
3640
|
}
|
|
3488
3641
|
});
|
|
@@ -3730,7 +3883,7 @@ ${imported}
|
|
|
3730
3883
|
return context;
|
|
3731
3884
|
}
|
|
3732
3885
|
|
|
3733
|
-
// src/
|
|
3886
|
+
// src/utils/capture.helpers.js
|
|
3734
3887
|
function stripRootShadows(originalEl, cloneRoot) {
|
|
3735
3888
|
if (!originalEl || !cloneRoot || !cloneRoot.style) return;
|
|
3736
3889
|
const cs = getComputedStyle(originalEl);
|
|
@@ -3797,288 +3950,136 @@ ${imported}
|
|
|
3797
3950
|
sanitizeAttributesForXHTML(root, opts);
|
|
3798
3951
|
removeAllComments(root);
|
|
3799
3952
|
}
|
|
3800
|
-
function
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3953
|
+
function authorHasExplicitSize(el) {
|
|
3954
|
+
var _a;
|
|
3955
|
+
try {
|
|
3956
|
+
const s = ((_a = el.getAttribute) == null ? void 0 : _a.call(el, "style")) || "";
|
|
3957
|
+
return /\b(height|width|block-size|inline-size)\s*:/.test(s);
|
|
3958
|
+
} catch (e) {
|
|
3959
|
+
return false;
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
function isReplacedElement(el) {
|
|
3963
|
+
return el instanceof HTMLImageElement || el instanceof HTMLCanvasElement || el instanceof HTMLVideoElement || el instanceof HTMLIFrameElement || el instanceof SVGElement || el instanceof HTMLObjectElement || el instanceof HTMLEmbedElement;
|
|
3964
|
+
}
|
|
3965
|
+
function shouldShrinkBox(srcEl, cs) {
|
|
3966
|
+
if (!(srcEl instanceof Element)) return false;
|
|
3967
|
+
if (authorHasExplicitSize(srcEl)) return false;
|
|
3968
|
+
if (isReplacedElement(srcEl)) return false;
|
|
3969
|
+
const pos = cs.position;
|
|
3970
|
+
if (pos === "absolute" || pos === "fixed" || pos === "sticky") return false;
|
|
3971
|
+
const disp = cs.display || "";
|
|
3972
|
+
if (disp.includes("flex") || disp.includes("grid") || disp.startsWith("table")) return false;
|
|
3973
|
+
if (cs.transform && cs.transform !== "none") return false;
|
|
3974
|
+
return true;
|
|
3975
|
+
}
|
|
3976
|
+
function shrinkAutoSizeBoxes(sourceRoot, cloneRoot, styleCache = /* @__PURE__ */ new Map()) {
|
|
3977
|
+
function walk(src, cln) {
|
|
3978
|
+
if (!(src instanceof Element) || !(cln instanceof Element)) return;
|
|
3979
|
+
const lostKids = src.childElementCount > cln.childElementCount;
|
|
3980
|
+
const cs = styleCache.get(src) || getComputedStyle(src);
|
|
3981
|
+
if (!styleCache.has(src)) styleCache.set(src, cs);
|
|
3982
|
+
if (lostKids && shouldShrinkBox(src, cs)) {
|
|
3983
|
+
if (!cln.style.height) cln.style.height = "auto";
|
|
3984
|
+
if (!cln.style.width) cln.style.width = "auto";
|
|
3985
|
+
cln.style.removeProperty("block-size");
|
|
3986
|
+
cln.style.removeProperty("inline-size");
|
|
3987
|
+
if (!cln.style.minHeight) cln.style.minHeight = "0";
|
|
3988
|
+
if (!cln.style.minWidth) cln.style.minWidth = "0";
|
|
3989
|
+
if (!cln.style.maxHeight) cln.style.maxHeight = "none";
|
|
3990
|
+
if (!cln.style.maxWidth) cln.style.maxWidth = "none";
|
|
3991
|
+
const oy = cs.overflowY || cs.overflowBlock || "visible";
|
|
3992
|
+
const ox = cs.overflowX || cs.overflowInline || "visible";
|
|
3993
|
+
if (oy !== "visible" || ox !== "visible") {
|
|
3994
|
+
cln.style.overflow = "visible";
|
|
3825
3995
|
}
|
|
3826
|
-
} finally {
|
|
3827
|
-
undoClamp();
|
|
3828
3996
|
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3997
|
+
const sKids = Array.from(src.children);
|
|
3998
|
+
const cKids = Array.from(cln.children);
|
|
3999
|
+
for (let i = 0; i < Math.min(sKids.length, cKids.length); i++) {
|
|
4000
|
+
walk(sKids[i], cKids[i]);
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
walk(sourceRoot, cloneRoot);
|
|
4004
|
+
}
|
|
4005
|
+
function isInNormalFlow(el) {
|
|
4006
|
+
const cs = getComputedStyle(el);
|
|
4007
|
+
if (cs.display === "none") return false;
|
|
4008
|
+
if (cs.position === "absolute" || cs.position === "fixed" || cs.position === "sticky") return false;
|
|
4009
|
+
if ((cs.cssFloat || cs.float || "none") !== "none") return false;
|
|
4010
|
+
if (cs.transform && cs.transform !== "none") return false;
|
|
4011
|
+
return true;
|
|
4012
|
+
}
|
|
4013
|
+
function willBeExcluded(el, options) {
|
|
4014
|
+
if (!(el instanceof Element)) return false;
|
|
4015
|
+
if (el.getAttribute("data-capture") === "exclude" && (options == null ? void 0 : options.excludeMode) === "remove") return true;
|
|
4016
|
+
if (Array.isArray(options == null ? void 0 : options.exclude)) {
|
|
4017
|
+
for (const sel of options.exclude) {
|
|
3833
4018
|
try {
|
|
3834
|
-
|
|
4019
|
+
if (el.matches(sel)) return options.excludeMode === "remove";
|
|
3835
4020
|
} catch (e) {
|
|
3836
|
-
console.warn("[snapdom] shrink pass failed:", e);
|
|
3837
4021
|
}
|
|
3838
4022
|
}
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
} catch (e) {
|
|
3842
|
-
}
|
|
3843
|
-
yield new Promise((resolve) => {
|
|
3844
|
-
idle(() => __async(null, null, function* () {
|
|
3845
|
-
yield inlineImages(state.clone, state.options);
|
|
3846
|
-
resolve();
|
|
3847
|
-
}), { fast });
|
|
3848
|
-
});
|
|
3849
|
-
yield new Promise((resolve) => {
|
|
3850
|
-
idle(() => __async(null, null, function* () {
|
|
3851
|
-
yield inlineBackgroundImages(state.element, state.clone, state.styleCache, state.options);
|
|
3852
|
-
resolve();
|
|
3853
|
-
}), { fast });
|
|
3854
|
-
});
|
|
3855
|
-
if (options.embedFonts) {
|
|
3856
|
-
yield new Promise((resolve) => {
|
|
3857
|
-
idle(() => __async(null, null, function* () {
|
|
3858
|
-
const required = collectUsedFontVariants(state.element);
|
|
3859
|
-
const usedCodepoints = collectUsedCodepoints(state.element);
|
|
3860
|
-
if (isSafari()) {
|
|
3861
|
-
const families = new Set(
|
|
3862
|
-
Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
|
|
3863
|
-
);
|
|
3864
|
-
yield ensureFontsReady(families, 1);
|
|
3865
|
-
}
|
|
3866
|
-
fontsCSS = yield embedCustomFonts({
|
|
3867
|
-
required,
|
|
3868
|
-
usedCodepoints,
|
|
3869
|
-
preCached: false,
|
|
3870
|
-
exclude: state.options.excludeFonts,
|
|
3871
|
-
useProxy: state.options.useProxy
|
|
3872
|
-
});
|
|
3873
|
-
resolve();
|
|
3874
|
-
}), { fast });
|
|
3875
|
-
});
|
|
3876
|
-
}
|
|
3877
|
-
const usedTags = collectUsedTagNames(state.clone).sort();
|
|
3878
|
-
const tagKey = usedTags.join(",");
|
|
3879
|
-
if (cache.baseStyle.has(tagKey)) {
|
|
3880
|
-
baseCSS = cache.baseStyle.get(tagKey);
|
|
3881
|
-
} else {
|
|
3882
|
-
yield new Promise((resolve) => {
|
|
3883
|
-
idle(() => {
|
|
3884
|
-
baseCSS = generateDedupedBaseCSS(usedTags);
|
|
3885
|
-
cache.baseStyle.set(tagKey, baseCSS);
|
|
3886
|
-
resolve();
|
|
3887
|
-
}, { fast });
|
|
3888
|
-
});
|
|
3889
|
-
}
|
|
3890
|
-
state = __spreadValues({ fontsCSS, baseCSS }, state);
|
|
3891
|
-
yield runHook("beforeRender", state);
|
|
3892
|
-
yield new Promise((resolve) => {
|
|
3893
|
-
idle(() => {
|
|
3894
|
-
var _a2;
|
|
3895
|
-
const csEl = getComputedStyle(state.element);
|
|
3896
|
-
const rect = state.element.getBoundingClientRect();
|
|
3897
|
-
let w0 = Math.max(1, limitDecimals(state.element.offsetWidth || parseFloat(csEl.width) || rect.width || 1));
|
|
3898
|
-
let h0 = Math.max(1, limitDecimals(state.element.offsetHeight || parseFloat(csEl.height) || rect.height || 1));
|
|
3899
|
-
if (((_a2 = state.options) == null ? void 0 : _a2.excludeMode) === "remove") {
|
|
3900
|
-
const hEst = estimateKeptHeight(state.element, state.options);
|
|
3901
|
-
const EPS = 1;
|
|
3902
|
-
if (Number.isFinite(hEst) && hEst > 0) {
|
|
3903
|
-
h0 = Math.max(1, Math.min(h0, limitDecimals(hEst + EPS)));
|
|
3904
|
-
}
|
|
3905
|
-
}
|
|
3906
|
-
const coerceNum = (v, def = NaN) => {
|
|
3907
|
-
const n = typeof v === "string" ? parseFloat(v) : v;
|
|
3908
|
-
return Number.isFinite(n) ? n : def;
|
|
3909
|
-
};
|
|
3910
|
-
const optW = coerceNum(state.options.width);
|
|
3911
|
-
const optH = coerceNum(state.options.height);
|
|
3912
|
-
let w = w0, h = h0;
|
|
3913
|
-
const hasW = Number.isFinite(optW);
|
|
3914
|
-
const hasH = Number.isFinite(optH);
|
|
3915
|
-
const aspect0 = h0 > 0 ? w0 / h0 : 1;
|
|
3916
|
-
if (hasW && hasH) {
|
|
3917
|
-
w = Math.max(1, limitDecimals(optW));
|
|
3918
|
-
h = Math.max(1, limitDecimals(optH));
|
|
3919
|
-
} else if (hasW) {
|
|
3920
|
-
w = Math.max(1, limitDecimals(optW));
|
|
3921
|
-
h = Math.max(1, limitDecimals(w / (aspect0 || 1)));
|
|
3922
|
-
} else if (hasH) {
|
|
3923
|
-
h = Math.max(1, limitDecimals(optH));
|
|
3924
|
-
w = Math.max(1, limitDecimals(h * (aspect0 || 1)));
|
|
3925
|
-
} else {
|
|
3926
|
-
w = w0;
|
|
3927
|
-
h = h0;
|
|
3928
|
-
}
|
|
3929
|
-
let minX = 0, minY = 0, maxX = w0, maxY = h0;
|
|
3930
|
-
if (!outerTransforms && rootTransform2D && Number.isFinite(rootTransform2D.a)) {
|
|
3931
|
-
const M2 = {
|
|
3932
|
-
a: rootTransform2D.a,
|
|
3933
|
-
b: rootTransform2D.b || 0,
|
|
3934
|
-
c: rootTransform2D.c || 0,
|
|
3935
|
-
d: rootTransform2D.d || 1,
|
|
3936
|
-
e: 0,
|
|
3937
|
-
f: 0
|
|
3938
|
-
};
|
|
3939
|
-
const bb2 = bboxWithOriginFull(w0, h0, M2, 0, 0);
|
|
3940
|
-
minX = limitDecimals(bb2.minX);
|
|
3941
|
-
minY = limitDecimals(bb2.minY);
|
|
3942
|
-
maxX = limitDecimals(bb2.maxX);
|
|
3943
|
-
maxY = limitDecimals(bb2.maxY);
|
|
3944
|
-
} else {
|
|
3945
|
-
const useTFBBox = outerTransforms && hasTFBBox(state.element);
|
|
3946
|
-
if (useTFBBox) {
|
|
3947
|
-
const baseTransform2 = csEl.transform && csEl.transform !== "none" ? csEl.transform : "";
|
|
3948
|
-
const ind2 = readIndividualTransforms(state.element);
|
|
3949
|
-
const TOTAL = readTotalTransformMatrix({
|
|
3950
|
-
baseTransform: baseTransform2,
|
|
3951
|
-
rotate: ind2.rotate || "0deg",
|
|
3952
|
-
scale: ind2.scale,
|
|
3953
|
-
translate: ind2.translate
|
|
3954
|
-
});
|
|
3955
|
-
const { ox: ox2, oy: oy2 } = parseTransformOriginPx(csEl, w0, h0);
|
|
3956
|
-
const M = TOTAL.is2D ? TOTAL : new DOMMatrix(TOTAL.toString());
|
|
3957
|
-
const bb = bboxWithOriginFull(w0, h0, M, ox2, oy2);
|
|
3958
|
-
minX = limitDecimals(bb.minX);
|
|
3959
|
-
minY = limitDecimals(bb.minY);
|
|
3960
|
-
maxX = limitDecimals(bb.maxX);
|
|
3961
|
-
maxY = limitDecimals(bb.maxY);
|
|
3962
|
-
}
|
|
3963
|
-
}
|
|
3964
|
-
const bleedShadow = parseBoxShadow(csEl);
|
|
3965
|
-
const bleedBlur = parseFilterBlur(csEl);
|
|
3966
|
-
const bleedOutline = parseOutline(csEl);
|
|
3967
|
-
const drop = parseFilterDropShadows(csEl);
|
|
3968
|
-
const bleed = !outerShadows ? { top: 0, right: 0, bottom: 0, left: 0 } : {
|
|
3969
|
-
top: limitDecimals(bleedShadow.top + bleedBlur.top + bleedOutline.top + drop.bleed.top),
|
|
3970
|
-
right: limitDecimals(bleedShadow.right + bleedBlur.right + bleedOutline.right + drop.bleed.right),
|
|
3971
|
-
bottom: limitDecimals(bleedShadow.bottom + bleedBlur.bottom + bleedOutline.bottom + drop.bleed.bottom),
|
|
3972
|
-
left: limitDecimals(bleedShadow.left + bleedBlur.left + bleedOutline.left + drop.bleed.left)
|
|
3973
|
-
};
|
|
3974
|
-
minX = limitDecimals(minX - bleed.left);
|
|
3975
|
-
minY = limitDecimals(minY - bleed.top);
|
|
3976
|
-
maxX = limitDecimals(maxX + bleed.right);
|
|
3977
|
-
maxY = limitDecimals(maxY + bleed.bottom);
|
|
3978
|
-
const vbW0 = Math.max(1, limitDecimals(maxX - minX));
|
|
3979
|
-
const vbH0 = Math.max(1, limitDecimals(maxY - minY));
|
|
3980
|
-
const scaleW = hasW || hasH ? limitDecimals(w / w0) : 1;
|
|
3981
|
-
const scaleH = hasH || hasW ? limitDecimals(h / h0) : 1;
|
|
3982
|
-
const outW = Math.max(1, limitDecimals(vbW0 * scaleW));
|
|
3983
|
-
const outH = Math.max(1, limitDecimals(vbH0 * scaleH));
|
|
3984
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
3985
|
-
const basePad = isSafari() ? 1 : 0;
|
|
3986
|
-
const extraPad = !outerTransforms ? 1 : 0;
|
|
3987
|
-
const pad = limitDecimals(basePad + extraPad);
|
|
3988
|
-
const fo = document.createElementNS(svgNS, "foreignObject");
|
|
3989
|
-
const vbMinX = limitDecimals(minX);
|
|
3990
|
-
const vbMinY = limitDecimals(minY);
|
|
3991
|
-
fo.setAttribute("x", String(limitDecimals(-(vbMinX - pad))));
|
|
3992
|
-
fo.setAttribute("y", String(limitDecimals(-(vbMinY - pad))));
|
|
3993
|
-
fo.setAttribute("width", String(limitDecimals(w0 + pad * 2)));
|
|
3994
|
-
fo.setAttribute("height", String(limitDecimals(h0 + pad * 2)));
|
|
3995
|
-
fo.style.overflow = "visible";
|
|
3996
|
-
const styleTag = document.createElement("style");
|
|
3997
|
-
styleTag.textContent = state.baseCSS + state.fontsCSS + "svg{overflow:visible;} foreignObject{overflow:visible;}" + state.classCSS;
|
|
3998
|
-
fo.appendChild(styleTag);
|
|
3999
|
-
const container = document.createElement("div");
|
|
4000
|
-
container.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
4001
|
-
container.style.width = `${limitDecimals(w0)}px`;
|
|
4002
|
-
container.style.height = `${limitDecimals(h0)}px`;
|
|
4003
|
-
container.style.overflow = "visible";
|
|
4004
|
-
state.clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
4005
|
-
container.appendChild(state.clone);
|
|
4006
|
-
fo.appendChild(container);
|
|
4007
|
-
const serializer = new XMLSerializer();
|
|
4008
|
-
const foString = serializer.serializeToString(fo);
|
|
4009
|
-
const vbW = limitDecimals(vbW0 + pad * 2);
|
|
4010
|
-
const vbH = limitDecimals(vbH0 + pad * 2);
|
|
4011
|
-
const wantsSize = hasW || hasH;
|
|
4012
|
-
options.meta = { w0, h0, vbW, vbH, targetW: w, targetH: h };
|
|
4013
|
-
const svgOutW = isSafari() && wantsSize ? vbW : limitDecimals(outW + pad * 2);
|
|
4014
|
-
const svgOutH = isSafari() && wantsSize ? vbH : limitDecimals(outH + pad * 2);
|
|
4015
|
-
const svgHeader = `<svg xmlns="${svgNS}" width="${svgOutW}" height="${svgOutH}" viewBox="0 0 ${vbW} ${vbH}">`;
|
|
4016
|
-
const svgFooter = "</svg>";
|
|
4017
|
-
svgString = svgHeader + foString + svgFooter;
|
|
4018
|
-
dataURL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;
|
|
4019
|
-
state = __spreadValues({ svgString, dataURL }, state);
|
|
4020
|
-
resolve();
|
|
4021
|
-
}, { fast });
|
|
4022
|
-
});
|
|
4023
|
-
yield runHook("afterRender", state);
|
|
4024
|
-
const sandbox = document.getElementById("snapdom-sandbox");
|
|
4025
|
-
if (sandbox && sandbox.style.position === "absolute") sandbox.remove();
|
|
4026
|
-
return state.dataURL;
|
|
4027
|
-
});
|
|
4023
|
+
}
|
|
4024
|
+
return false;
|
|
4028
4025
|
}
|
|
4029
|
-
function
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4026
|
+
function estimateKeptHeight(container, options) {
|
|
4027
|
+
const csC = getComputedStyle(container);
|
|
4028
|
+
const rC = container.getBoundingClientRect();
|
|
4029
|
+
let minTop = Infinity;
|
|
4030
|
+
let maxBottom = -Infinity;
|
|
4031
|
+
let found = false;
|
|
4032
|
+
const kids = Array.from(container.children);
|
|
4033
|
+
for (const k of kids) {
|
|
4034
|
+
if (willBeExcluded(k, options)) continue;
|
|
4035
|
+
if (!isInNormalFlow(k)) continue;
|
|
4036
|
+
const rk = k.getBoundingClientRect();
|
|
4037
|
+
const top = rk.top - rC.top;
|
|
4038
|
+
const bottom = rk.bottom - rC.top;
|
|
4039
|
+
if (bottom <= top) continue;
|
|
4040
|
+
if (top < minTop) minTop = top;
|
|
4041
|
+
if (bottom > maxBottom) maxBottom = bottom;
|
|
4042
|
+
found = true;
|
|
4036
4043
|
}
|
|
4044
|
+
const contentSpan = found ? Math.max(0, maxBottom - minTop) : 0;
|
|
4045
|
+
const bt = parseFloat(csC.borderTopWidth) || 0;
|
|
4046
|
+
const bb = parseFloat(csC.borderBottomWidth) || 0;
|
|
4047
|
+
const pt = parseFloat(csC.paddingTop) || 0;
|
|
4048
|
+
const pb = parseFloat(csC.paddingBottom) || 0;
|
|
4049
|
+
return bt + bb + pt + pb + contentSpan;
|
|
4037
4050
|
}
|
|
4038
|
-
|
|
4039
|
-
|
|
4051
|
+
var limitDecimals = (v, n = 3) => Number.isFinite(v) ? Math.round(v * __pow(10, n)) / __pow(10, n) : v;
|
|
4052
|
+
|
|
4053
|
+
// src/utils/transforms.helpers.js
|
|
4054
|
+
function parseBoxShadow(cs) {
|
|
4055
|
+
var _a;
|
|
4056
|
+
const v = cs.boxShadow || "";
|
|
4057
|
+
if (!v || v === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4058
|
+
const parts = v.split(/\),(?=(?:[^()]*\([^()]*\))*[^()]*$)/).map((s) => s.trim());
|
|
4059
|
+
let t = 0, r = 0, b2 = 0, l = 0;
|
|
4060
|
+
for (const part of parts) {
|
|
4061
|
+
const nums = ((_a = part.match(/-?\d+(\.\d+)?px/g)) == null ? void 0 : _a.map((n) => parseFloat(n))) || [];
|
|
4062
|
+
if (nums.length < 2) continue;
|
|
4063
|
+
const [ox2, oy2, blur = 0, spread = 0] = nums;
|
|
4064
|
+
const extX = Math.abs(ox2) + blur + spread;
|
|
4065
|
+
const extY = Math.abs(oy2) + blur + spread;
|
|
4066
|
+
r = Math.max(r, extX + Math.max(ox2, 0));
|
|
4067
|
+
l = Math.max(l, extX + Math.max(-ox2, 0));
|
|
4068
|
+
b2 = Math.max(b2, extY + Math.max(oy2, 0));
|
|
4069
|
+
t = Math.max(t, extY + Math.max(-oy2, 0));
|
|
4070
|
+
}
|
|
4071
|
+
return { top: Math.ceil(t), right: Math.ceil(r), bottom: Math.ceil(b2), left: Math.ceil(l) };
|
|
4040
4072
|
}
|
|
4041
|
-
function
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
const pos = cs.position;
|
|
4046
|
-
if (pos === "absolute" || pos === "fixed" || pos === "sticky") return false;
|
|
4047
|
-
const disp = cs.display || "";
|
|
4048
|
-
if (disp.includes("flex") || disp.includes("grid") || disp.startsWith("table")) return false;
|
|
4049
|
-
if (cs.transform && cs.transform !== "none") return false;
|
|
4050
|
-
return true;
|
|
4073
|
+
function parseFilterBlur(cs) {
|
|
4074
|
+
const m = (cs.filter || "").match(/blur\(\s*([0-9.]+)px\s*\)/);
|
|
4075
|
+
const b2 = m ? Math.ceil(parseFloat(m[1]) || 0) : 0;
|
|
4076
|
+
return { top: b2, right: b2, bottom: b2, left: b2 };
|
|
4051
4077
|
}
|
|
4052
|
-
function
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
const cs = styleCache.get(src) || getComputedStyle(src);
|
|
4057
|
-
if (!styleCache.has(src)) styleCache.set(src, cs);
|
|
4058
|
-
if (lostKids && shouldShrinkBox(src, cs)) {
|
|
4059
|
-
if (!cln.style.height) cln.style.height = "auto";
|
|
4060
|
-
if (!cln.style.width) cln.style.width = "auto";
|
|
4061
|
-
cln.style.removeProperty("block-size");
|
|
4062
|
-
cln.style.removeProperty("inline-size");
|
|
4063
|
-
if (!cln.style.minHeight) cln.style.minHeight = "0";
|
|
4064
|
-
if (!cln.style.minWidth) cln.style.minWidth = "0";
|
|
4065
|
-
if (!cln.style.maxHeight) cln.style.maxHeight = "none";
|
|
4066
|
-
if (!cln.style.maxWidth) cln.style.maxWidth = "none";
|
|
4067
|
-
const oy = cs.overflowY || cs.overflowBlock || "visible";
|
|
4068
|
-
const ox = cs.overflowX || cs.overflowInline || "visible";
|
|
4069
|
-
if (oy !== "visible" || ox !== "visible") {
|
|
4070
|
-
cln.style.overflow = "visible";
|
|
4071
|
-
}
|
|
4072
|
-
}
|
|
4073
|
-
const sKids = Array.from(src.children);
|
|
4074
|
-
const cKids = Array.from(cln.children);
|
|
4075
|
-
for (let i = 0; i < Math.min(sKids.length, cKids.length); i++) {
|
|
4076
|
-
walk(sKids[i], cKids[i]);
|
|
4077
|
-
}
|
|
4078
|
-
}
|
|
4079
|
-
walk(sourceRoot, cloneRoot);
|
|
4078
|
+
function parseOutline(cs) {
|
|
4079
|
+
if ((cs.outlineStyle || "none") === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4080
|
+
const w2 = Math.ceil(parseFloat(cs.outlineWidth || "0") || 0);
|
|
4081
|
+
return { top: w2, right: w2, bottom: w2, left: w2 };
|
|
4080
4082
|
}
|
|
4081
|
-
var limitDecimals = (v, n = 3) => Number.isFinite(v) ? Math.round(v * __pow(10, n)) / __pow(10, n) : v;
|
|
4082
4083
|
function parseFilterDropShadows(cs) {
|
|
4083
4084
|
var _a;
|
|
4084
4085
|
const raw = `${cs.filter || ""} ${cs.webkitFilter || ""}`.trim();
|
|
@@ -4168,35 +4169,6 @@ ${imported}
|
|
|
4168
4169
|
return null;
|
|
4169
4170
|
}
|
|
4170
4171
|
}
|
|
4171
|
-
function parseBoxShadow(cs) {
|
|
4172
|
-
var _a;
|
|
4173
|
-
const v = cs.boxShadow || "";
|
|
4174
|
-
if (!v || v === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4175
|
-
const parts = v.split(/\),(?=(?:[^()]*\([^()]*\))*[^()]*$)/).map((s) => s.trim());
|
|
4176
|
-
let t = 0, r = 0, b2 = 0, l = 0;
|
|
4177
|
-
for (const part of parts) {
|
|
4178
|
-
const nums = ((_a = part.match(/-?\d+(\.\d+)?px/g)) == null ? void 0 : _a.map((n) => parseFloat(n))) || [];
|
|
4179
|
-
if (nums.length < 2) continue;
|
|
4180
|
-
const [ox2, oy2, blur = 0, spread = 0] = nums;
|
|
4181
|
-
const extX = Math.abs(ox2) + blur + spread;
|
|
4182
|
-
const extY = Math.abs(oy2) + blur + spread;
|
|
4183
|
-
r = Math.max(r, extX + Math.max(ox2, 0));
|
|
4184
|
-
l = Math.max(l, extX + Math.max(-ox2, 0));
|
|
4185
|
-
b2 = Math.max(b2, extY + Math.max(oy2, 0));
|
|
4186
|
-
t = Math.max(t, extY + Math.max(-oy2, 0));
|
|
4187
|
-
}
|
|
4188
|
-
return { top: Math.ceil(t), right: Math.ceil(r), bottom: Math.ceil(b2), left: Math.ceil(l) };
|
|
4189
|
-
}
|
|
4190
|
-
function parseFilterBlur(cs) {
|
|
4191
|
-
const m = (cs.filter || "").match(/blur\(\s*([0-9.]+)px\s*\)/);
|
|
4192
|
-
const b2 = m ? Math.ceil(parseFloat(m[1]) || 0) : 0;
|
|
4193
|
-
return { top: b2, right: b2, bottom: b2, left: b2 };
|
|
4194
|
-
}
|
|
4195
|
-
function parseOutline(cs) {
|
|
4196
|
-
if ((cs.outlineStyle || "none") === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4197
|
-
const w2 = Math.ceil(parseFloat(cs.outlineWidth || "0") || 0);
|
|
4198
|
-
return { top: w2, right: w2, bottom: w2, left: w2 };
|
|
4199
|
-
}
|
|
4200
4172
|
function bboxWithOriginFull(w2, h2, M, ox2, oy2) {
|
|
4201
4173
|
const a2 = M.a, b2 = M.b, c2 = M.c, d2 = M.d, e2 = M.e || 0, f2 = M.f || 0;
|
|
4202
4174
|
function pt(x, y) {
|
|
@@ -4216,17 +4188,24 @@ ${imported}
|
|
|
4216
4188
|
}
|
|
4217
4189
|
return { minX: minX2, minY: minY2, maxX: maxX2, maxY: maxY2, width: maxX2 - minX2, height: maxY2 - minY2 };
|
|
4218
4190
|
}
|
|
4219
|
-
function
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
return
|
|
4229
|
-
|
|
4191
|
+
function parseTransformOriginPx(cs, w, h) {
|
|
4192
|
+
const raw = (cs.transformOrigin || "0 0").trim().split(/\s+/);
|
|
4193
|
+
const [oxRaw, oyRaw] = [raw[0] || "0", raw[1] || "0"];
|
|
4194
|
+
const toPx = (token, size) => {
|
|
4195
|
+
const t = token.toLowerCase();
|
|
4196
|
+
if (t === "left" || t === "top") return 0;
|
|
4197
|
+
if (t === "center") return size / 2;
|
|
4198
|
+
if (t === "right") return size;
|
|
4199
|
+
if (t === "bottom") return size;
|
|
4200
|
+
if (t.endsWith("px")) return parseFloat(t) || 0;
|
|
4201
|
+
if (t.endsWith("%")) return (parseFloat(t) || 0) * size / 100;
|
|
4202
|
+
if (/^-?\d+(\.\d+)?$/.test(t)) return parseFloat(t) || 0;
|
|
4203
|
+
return 0;
|
|
4204
|
+
};
|
|
4205
|
+
return {
|
|
4206
|
+
ox: toPx(oxRaw, w),
|
|
4207
|
+
oy: toPx(oyRaw, h)
|
|
4208
|
+
};
|
|
4230
4209
|
}
|
|
4231
4210
|
function readIndividualTransforms(el) {
|
|
4232
4211
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -4284,35 +4263,6 @@ ${imported}
|
|
|
4284
4263
|
out.translate = cs.translate && cs.translate !== "none" ? cs.translate : null;
|
|
4285
4264
|
return out;
|
|
4286
4265
|
}
|
|
4287
|
-
function hasBBoxAffectingTransform(el) {
|
|
4288
|
-
const cs = getComputedStyle(el);
|
|
4289
|
-
const t = cs.transform || "none";
|
|
4290
|
-
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);
|
|
4291
|
-
if (hasMatrix) return true;
|
|
4292
|
-
const r = cs.rotate && cs.rotate !== "none" && cs.rotate !== "0deg";
|
|
4293
|
-
const s = cs.scale && cs.scale !== "none" && cs.scale !== "1";
|
|
4294
|
-
const tr = cs.translate && cs.translate !== "none" && cs.translate !== "0px 0px";
|
|
4295
|
-
return Boolean(r || s || tr);
|
|
4296
|
-
}
|
|
4297
|
-
function parseTransformOriginPx(cs, w, h) {
|
|
4298
|
-
const raw = (cs.transformOrigin || "0 0").trim().split(/\s+/);
|
|
4299
|
-
const [oxRaw, oyRaw] = [raw[0] || "0", raw[1] || "0"];
|
|
4300
|
-
const toPx = (token, size) => {
|
|
4301
|
-
const t = token.toLowerCase();
|
|
4302
|
-
if (t === "left" || t === "top") return 0;
|
|
4303
|
-
if (t === "center") return size / 2;
|
|
4304
|
-
if (t === "right") return size;
|
|
4305
|
-
if (t === "bottom") return size;
|
|
4306
|
-
if (t.endsWith("px")) return parseFloat(t) || 0;
|
|
4307
|
-
if (t.endsWith("%")) return (parseFloat(t) || 0) * size / 100;
|
|
4308
|
-
if (/^-?\d+(\.\d+)?$/.test(t)) return parseFloat(t) || 0;
|
|
4309
|
-
return 0;
|
|
4310
|
-
};
|
|
4311
|
-
return {
|
|
4312
|
-
ox: toPx(oxRaw, w),
|
|
4313
|
-
oy: toPx(oyRaw, h)
|
|
4314
|
-
};
|
|
4315
|
-
}
|
|
4316
4266
|
var __measureHost = null;
|
|
4317
4267
|
function getMeasureHost() {
|
|
4318
4268
|
if (__measureHost) return __measureHost;
|
|
@@ -4347,51 +4297,258 @@ ${imported}
|
|
|
4347
4297
|
host.removeChild(tmp);
|
|
4348
4298
|
return M;
|
|
4349
4299
|
}
|
|
4350
|
-
function
|
|
4300
|
+
function hasBBoxAffectingTransform(el) {
|
|
4351
4301
|
const cs = getComputedStyle(el);
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
if (
|
|
4355
|
-
|
|
4356
|
-
|
|
4302
|
+
const t = cs.transform || "none";
|
|
4303
|
+
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);
|
|
4304
|
+
if (hasMatrix) return true;
|
|
4305
|
+
const r = cs.rotate && cs.rotate !== "none" && cs.rotate !== "0deg";
|
|
4306
|
+
const s = cs.scale && cs.scale !== "none" && cs.scale !== "1";
|
|
4307
|
+
const tr = cs.translate && cs.translate !== "none" && cs.translate !== "0px 0px";
|
|
4308
|
+
return Boolean(r || s || tr);
|
|
4357
4309
|
}
|
|
4358
|
-
function
|
|
4359
|
-
|
|
4360
|
-
if (
|
|
4361
|
-
|
|
4362
|
-
|
|
4310
|
+
function matrixFromComputed(el) {
|
|
4311
|
+
const tr = getComputedStyle(el).transform;
|
|
4312
|
+
if (!tr || tr === "none") return new DOMMatrix();
|
|
4313
|
+
try {
|
|
4314
|
+
return new DOMMatrix(tr);
|
|
4315
|
+
} catch (e) {
|
|
4316
|
+
return new WebKitCSSMatrix(tr);
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
|
|
4320
|
+
// src/core/capture.js
|
|
4321
|
+
function captureDOM(element, options) {
|
|
4322
|
+
return __async(this, null, function* () {
|
|
4323
|
+
var _a;
|
|
4324
|
+
if (!element) throw new Error("Element cannot be null or undefined");
|
|
4325
|
+
applyCachePolicy(options.cache);
|
|
4326
|
+
const fast = options.fast;
|
|
4327
|
+
const outerTransforms = options.outerTransforms !== false;
|
|
4328
|
+
const outerShadows = !!options.outerShadows;
|
|
4329
|
+
let state = { element, options, plugins: options.plugins };
|
|
4330
|
+
let clone, classCSS, styleCache;
|
|
4331
|
+
let fontsCSS = "";
|
|
4332
|
+
let baseCSS = "";
|
|
4333
|
+
let dataURL;
|
|
4334
|
+
let svgString;
|
|
4335
|
+
let rootTransform2D = null;
|
|
4336
|
+
yield runHook("beforeSnap", state);
|
|
4337
|
+
yield runHook("beforeClone", state);
|
|
4338
|
+
const undoClamp = lineClamp(state.element);
|
|
4339
|
+
try {
|
|
4340
|
+
({ clone, classCSS, styleCache } = yield prepareClone(state.element, state.options));
|
|
4341
|
+
if (!outerTransforms && clone) {
|
|
4342
|
+
rootTransform2D = normalizeRootTransforms(state.element, clone);
|
|
4343
|
+
}
|
|
4344
|
+
if (!outerShadows && clone) {
|
|
4345
|
+
stripRootShadows(state.element, clone);
|
|
4346
|
+
}
|
|
4347
|
+
} finally {
|
|
4348
|
+
undoClamp();
|
|
4349
|
+
}
|
|
4350
|
+
state = __spreadValues({ clone, classCSS, styleCache }, state);
|
|
4351
|
+
yield runHook("afterClone", state);
|
|
4352
|
+
sanitizeCloneForXHTML(state.clone);
|
|
4353
|
+
if (((_a = state.options) == null ? void 0 : _a.excludeMode) === "remove") {
|
|
4363
4354
|
try {
|
|
4364
|
-
|
|
4355
|
+
shrinkAutoSizeBoxes(state.element, state.clone, state.styleCache);
|
|
4365
4356
|
} catch (e) {
|
|
4357
|
+
console.warn("[snapdom] shrink pass failed:", e);
|
|
4366
4358
|
}
|
|
4367
4359
|
}
|
|
4368
|
-
|
|
4369
|
-
|
|
4360
|
+
try {
|
|
4361
|
+
yield ligatureIconToImage(state.clone, state.element);
|
|
4362
|
+
} catch (e) {
|
|
4363
|
+
}
|
|
4364
|
+
yield new Promise((resolve) => {
|
|
4365
|
+
idle(() => __async(null, null, function* () {
|
|
4366
|
+
yield inlineImages(state.clone, state.options);
|
|
4367
|
+
resolve();
|
|
4368
|
+
}), { fast });
|
|
4369
|
+
});
|
|
4370
|
+
yield new Promise((resolve) => {
|
|
4371
|
+
idle(() => __async(null, null, function* () {
|
|
4372
|
+
yield inlineBackgroundImages(state.element, state.clone, state.styleCache, state.options);
|
|
4373
|
+
resolve();
|
|
4374
|
+
}), { fast });
|
|
4375
|
+
});
|
|
4376
|
+
if (options.embedFonts) {
|
|
4377
|
+
yield new Promise((resolve) => {
|
|
4378
|
+
idle(() => __async(null, null, function* () {
|
|
4379
|
+
const required = collectUsedFontVariants(state.element);
|
|
4380
|
+
const usedCodepoints = collectUsedCodepoints(state.element);
|
|
4381
|
+
if (isSafari()) {
|
|
4382
|
+
const families = new Set(
|
|
4383
|
+
Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
|
|
4384
|
+
);
|
|
4385
|
+
yield ensureFontsReady(families, 1);
|
|
4386
|
+
}
|
|
4387
|
+
fontsCSS = yield embedCustomFonts({
|
|
4388
|
+
required,
|
|
4389
|
+
usedCodepoints,
|
|
4390
|
+
preCached: false,
|
|
4391
|
+
exclude: state.options.excludeFonts,
|
|
4392
|
+
useProxy: state.options.useProxy
|
|
4393
|
+
});
|
|
4394
|
+
resolve();
|
|
4395
|
+
}), { fast });
|
|
4396
|
+
});
|
|
4397
|
+
}
|
|
4398
|
+
const usedTags = collectUsedTagNames(state.clone).sort();
|
|
4399
|
+
const tagKey = usedTags.join(",");
|
|
4400
|
+
if (cache.baseStyle.has(tagKey)) {
|
|
4401
|
+
baseCSS = cache.baseStyle.get(tagKey);
|
|
4402
|
+
} else {
|
|
4403
|
+
yield new Promise((resolve) => {
|
|
4404
|
+
idle(() => {
|
|
4405
|
+
baseCSS = generateDedupedBaseCSS(usedTags);
|
|
4406
|
+
cache.baseStyle.set(tagKey, baseCSS);
|
|
4407
|
+
resolve();
|
|
4408
|
+
}, { fast });
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4411
|
+
state = __spreadValues({ fontsCSS, baseCSS }, state);
|
|
4412
|
+
yield runHook("beforeRender", state);
|
|
4413
|
+
yield new Promise((resolve) => {
|
|
4414
|
+
idle(() => {
|
|
4415
|
+
var _a2;
|
|
4416
|
+
const csEl = getComputedStyle(state.element);
|
|
4417
|
+
const rect = state.element.getBoundingClientRect();
|
|
4418
|
+
let w0 = Math.max(1, limitDecimals(state.element.offsetWidth || parseFloat(csEl.width) || rect.width || 1));
|
|
4419
|
+
let h0 = Math.max(1, limitDecimals(state.element.offsetHeight || parseFloat(csEl.height) || rect.height || 1));
|
|
4420
|
+
if (((_a2 = state.options) == null ? void 0 : _a2.excludeMode) === "remove") {
|
|
4421
|
+
const hEst = estimateKeptHeight(state.element, state.options);
|
|
4422
|
+
const EPS = 1;
|
|
4423
|
+
if (Number.isFinite(hEst) && hEst > 0) {
|
|
4424
|
+
h0 = Math.max(1, Math.min(h0, limitDecimals(hEst + EPS)));
|
|
4425
|
+
}
|
|
4426
|
+
}
|
|
4427
|
+
const coerceNum = (v, def = NaN) => {
|
|
4428
|
+
const n = typeof v === "string" ? parseFloat(v) : v;
|
|
4429
|
+
return Number.isFinite(n) ? n : def;
|
|
4430
|
+
};
|
|
4431
|
+
const optW = coerceNum(state.options.width);
|
|
4432
|
+
const optH = coerceNum(state.options.height);
|
|
4433
|
+
let w = w0, h = h0;
|
|
4434
|
+
const hasW = Number.isFinite(optW);
|
|
4435
|
+
const hasH = Number.isFinite(optH);
|
|
4436
|
+
const aspect0 = h0 > 0 ? w0 / h0 : 1;
|
|
4437
|
+
if (hasW && hasH) {
|
|
4438
|
+
w = Math.max(1, limitDecimals(optW));
|
|
4439
|
+
h = Math.max(1, limitDecimals(optH));
|
|
4440
|
+
} else if (hasW) {
|
|
4441
|
+
w = Math.max(1, limitDecimals(optW));
|
|
4442
|
+
h = Math.max(1, limitDecimals(w / (aspect0 || 1)));
|
|
4443
|
+
} else if (hasH) {
|
|
4444
|
+
h = Math.max(1, limitDecimals(optH));
|
|
4445
|
+
w = Math.max(1, limitDecimals(h * (aspect0 || 1)));
|
|
4446
|
+
} else {
|
|
4447
|
+
w = w0;
|
|
4448
|
+
h = h0;
|
|
4449
|
+
}
|
|
4450
|
+
let minX = 0, minY = 0, maxX = w0, maxY = h0;
|
|
4451
|
+
if (!outerTransforms && rootTransform2D && Number.isFinite(rootTransform2D.a)) {
|
|
4452
|
+
const M2 = {
|
|
4453
|
+
a: rootTransform2D.a,
|
|
4454
|
+
b: rootTransform2D.b || 0,
|
|
4455
|
+
c: rootTransform2D.c || 0,
|
|
4456
|
+
d: rootTransform2D.d || 1,
|
|
4457
|
+
e: 0,
|
|
4458
|
+
f: 0
|
|
4459
|
+
};
|
|
4460
|
+
const bb2 = bboxWithOriginFull(w0, h0, M2, 0, 0);
|
|
4461
|
+
minX = limitDecimals(bb2.minX);
|
|
4462
|
+
minY = limitDecimals(bb2.minY);
|
|
4463
|
+
maxX = limitDecimals(bb2.maxX);
|
|
4464
|
+
maxY = limitDecimals(bb2.maxY);
|
|
4465
|
+
} else {
|
|
4466
|
+
const useTFBBox = outerTransforms && hasTFBBox(state.element);
|
|
4467
|
+
if (useTFBBox) {
|
|
4468
|
+
const baseTransform2 = csEl.transform && csEl.transform !== "none" ? csEl.transform : "";
|
|
4469
|
+
const ind2 = readIndividualTransforms(state.element);
|
|
4470
|
+
const TOTAL = readTotalTransformMatrix({
|
|
4471
|
+
baseTransform: baseTransform2,
|
|
4472
|
+
rotate: ind2.rotate || "0deg",
|
|
4473
|
+
scale: ind2.scale,
|
|
4474
|
+
translate: ind2.translate
|
|
4475
|
+
});
|
|
4476
|
+
const { ox: ox2, oy: oy2 } = parseTransformOriginPx(csEl, w0, h0);
|
|
4477
|
+
const M = TOTAL.is2D ? TOTAL : new DOMMatrix(TOTAL.toString());
|
|
4478
|
+
const bb = bboxWithOriginFull(w0, h0, M, ox2, oy2);
|
|
4479
|
+
minX = limitDecimals(bb.minX);
|
|
4480
|
+
minY = limitDecimals(bb.minY);
|
|
4481
|
+
maxX = limitDecimals(bb.maxX);
|
|
4482
|
+
maxY = limitDecimals(bb.maxY);
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
const bleedShadow = parseBoxShadow(csEl);
|
|
4486
|
+
const bleedBlur = parseFilterBlur(csEl);
|
|
4487
|
+
const bleedOutline = parseOutline(csEl);
|
|
4488
|
+
const drop = parseFilterDropShadows(csEl);
|
|
4489
|
+
const bleed = !outerShadows ? { top: 0, right: 0, bottom: 0, left: 0 } : {
|
|
4490
|
+
top: limitDecimals(bleedShadow.top + bleedBlur.top + bleedOutline.top + drop.bleed.top),
|
|
4491
|
+
right: limitDecimals(bleedShadow.right + bleedBlur.right + bleedOutline.right + drop.bleed.right),
|
|
4492
|
+
bottom: limitDecimals(bleedShadow.bottom + bleedBlur.bottom + bleedOutline.bottom + drop.bleed.bottom),
|
|
4493
|
+
left: limitDecimals(bleedShadow.left + bleedBlur.left + bleedOutline.left + drop.bleed.left)
|
|
4494
|
+
};
|
|
4495
|
+
minX = limitDecimals(minX - bleed.left);
|
|
4496
|
+
minY = limitDecimals(minY - bleed.top);
|
|
4497
|
+
maxX = limitDecimals(maxX + bleed.right);
|
|
4498
|
+
maxY = limitDecimals(maxY + bleed.bottom);
|
|
4499
|
+
const vbW0 = Math.max(1, limitDecimals(maxX - minX));
|
|
4500
|
+
const vbH0 = Math.max(1, limitDecimals(maxY - minY));
|
|
4501
|
+
const scaleW = hasW || hasH ? limitDecimals(w / w0) : 1;
|
|
4502
|
+
const scaleH = hasH || hasW ? limitDecimals(h / h0) : 1;
|
|
4503
|
+
const outW = Math.max(1, limitDecimals(vbW0 * scaleW));
|
|
4504
|
+
const outH = Math.max(1, limitDecimals(vbH0 * scaleH));
|
|
4505
|
+
const svgNS = "http://www.w3.org/2000/svg";
|
|
4506
|
+
const basePad = isSafari() ? 1 : 0;
|
|
4507
|
+
const extraPad = !outerTransforms ? 1 : 0;
|
|
4508
|
+
const pad = limitDecimals(basePad + extraPad);
|
|
4509
|
+
const fo = document.createElementNS(svgNS, "foreignObject");
|
|
4510
|
+
const vbMinX = limitDecimals(minX);
|
|
4511
|
+
const vbMinY = limitDecimals(minY);
|
|
4512
|
+
fo.setAttribute("x", String(limitDecimals(-(vbMinX - pad))));
|
|
4513
|
+
fo.setAttribute("y", String(limitDecimals(-(vbMinY - pad))));
|
|
4514
|
+
fo.setAttribute("width", String(limitDecimals(w0 + pad * 2)));
|
|
4515
|
+
fo.setAttribute("height", String(limitDecimals(h0 + pad * 2)));
|
|
4516
|
+
fo.style.overflow = "visible";
|
|
4517
|
+
const styleTag = document.createElement("style");
|
|
4518
|
+
styleTag.textContent = state.baseCSS + state.fontsCSS + "svg{overflow:visible;} foreignObject{overflow:visible;}" + state.classCSS;
|
|
4519
|
+
fo.appendChild(styleTag);
|
|
4520
|
+
const container = document.createElement("div");
|
|
4521
|
+
container.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
4522
|
+
container.style.width = `${limitDecimals(w0)}px`;
|
|
4523
|
+
container.style.height = `${limitDecimals(h0)}px`;
|
|
4524
|
+
container.style.overflow = "visible";
|
|
4525
|
+
state.clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
4526
|
+
container.appendChild(state.clone);
|
|
4527
|
+
fo.appendChild(container);
|
|
4528
|
+
const serializer = new XMLSerializer();
|
|
4529
|
+
const foString = serializer.serializeToString(fo);
|
|
4530
|
+
const vbW = limitDecimals(vbW0 + pad * 2);
|
|
4531
|
+
const vbH = limitDecimals(vbH0 + pad * 2);
|
|
4532
|
+
const wantsSize = hasW || hasH;
|
|
4533
|
+
options.meta = { w0, h0, vbW, vbH, targetW: w, targetH: h };
|
|
4534
|
+
const svgOutW = isSafari() && wantsSize ? vbW : limitDecimals(outW + pad * 2);
|
|
4535
|
+
const svgOutH = isSafari() && wantsSize ? vbH : limitDecimals(outH + pad * 2);
|
|
4536
|
+
const svgHeader = `<svg xmlns="${svgNS}" width="${svgOutW}" height="${svgOutH}" viewBox="0 0 ${vbW} ${vbH}">`;
|
|
4537
|
+
const svgFooter = "</svg>";
|
|
4538
|
+
svgString = svgHeader + foString + svgFooter;
|
|
4539
|
+
dataURL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;
|
|
4540
|
+
state = __spreadValues({ svgString, dataURL }, state);
|
|
4541
|
+
resolve();
|
|
4542
|
+
}, { fast });
|
|
4543
|
+
});
|
|
4544
|
+
yield runHook("afterRender", state);
|
|
4545
|
+
const sandbox = document.getElementById("snapdom-sandbox");
|
|
4546
|
+
if (sandbox && sandbox.style.position === "absolute") sandbox.remove();
|
|
4547
|
+
return state.dataURL;
|
|
4548
|
+
});
|
|
4370
4549
|
}
|
|
4371
|
-
function
|
|
4372
|
-
|
|
4373
|
-
const rC = container.getBoundingClientRect();
|
|
4374
|
-
let minTop = Infinity;
|
|
4375
|
-
let maxBottom = -Infinity;
|
|
4376
|
-
let found = false;
|
|
4377
|
-
const kids = Array.from(container.children);
|
|
4378
|
-
for (const k of kids) {
|
|
4379
|
-
if (willBeExcluded(k, options)) continue;
|
|
4380
|
-
if (!isInNormalFlow(k)) continue;
|
|
4381
|
-
const rk = k.getBoundingClientRect();
|
|
4382
|
-
const top = rk.top - rC.top;
|
|
4383
|
-
const bottom = rk.bottom - rC.top;
|
|
4384
|
-
if (bottom <= top) continue;
|
|
4385
|
-
if (top < minTop) minTop = top;
|
|
4386
|
-
if (bottom > maxBottom) maxBottom = bottom;
|
|
4387
|
-
found = true;
|
|
4388
|
-
}
|
|
4389
|
-
const contentSpan = found ? Math.max(0, maxBottom - minTop) : 0;
|
|
4390
|
-
const bt = parseFloat(csC.borderTopWidth) || 0;
|
|
4391
|
-
const bb = parseFloat(csC.borderBottomWidth) || 0;
|
|
4392
|
-
const pt = parseFloat(csC.paddingTop) || 0;
|
|
4393
|
-
const pb = parseFloat(csC.paddingBottom) || 0;
|
|
4394
|
-
return bt + bb + pt + pb + contentSpan;
|
|
4550
|
+
function hasTFBBox(el) {
|
|
4551
|
+
return hasBBoxAffectingTransform(el);
|
|
4395
4552
|
}
|
|
4396
4553
|
|
|
4397
4554
|
// src/core/context.js
|