@zumer/snapdom 2.0.0-dev.1 → 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/README.md +5 -2
- package/dist/snapdom.js +901 -515
- package/dist/snapdom.min.js +7 -7
- package/dist/snapdom.min.mjs +8 -8
- package/dist/snapdom.mjs +878 -498
- 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
|
**/
|
|
@@ -374,19 +374,6 @@
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
// src/utils/image.js
|
|
377
|
-
function createBackground(baseCanvas, backgroundColor) {
|
|
378
|
-
if (!backgroundColor || !baseCanvas.width || !baseCanvas.height) {
|
|
379
|
-
return baseCanvas;
|
|
380
|
-
}
|
|
381
|
-
const temp = document.createElement("canvas");
|
|
382
|
-
temp.width = baseCanvas.width;
|
|
383
|
-
temp.height = baseCanvas.height;
|
|
384
|
-
const ctx = temp.getContext("2d");
|
|
385
|
-
ctx.fillStyle = backgroundColor;
|
|
386
|
-
ctx.fillRect(0, 0, temp.width, temp.height);
|
|
387
|
-
ctx.drawImage(baseCanvas, 0, 0);
|
|
388
|
-
return temp;
|
|
389
|
-
}
|
|
390
377
|
function inlineSingleBackgroundEntry(_0) {
|
|
391
378
|
return __async(this, arguments, function* (entry, options = {}) {
|
|
392
379
|
const isGradient = /^((repeating-)?(linear|radial|conic)-gradient)\(/i.test(entry);
|
|
@@ -664,11 +651,20 @@
|
|
|
664
651
|
}
|
|
665
652
|
}
|
|
666
653
|
function isSafari() {
|
|
667
|
-
|
|
668
|
-
const
|
|
669
|
-
const
|
|
670
|
-
const
|
|
671
|
-
|
|
654
|
+
if (typeof navigator === "undefined") return false;
|
|
655
|
+
const ua = navigator.userAgent || "";
|
|
656
|
+
const uaLower = ua.toLowerCase();
|
|
657
|
+
const isSafariUA = uaLower.includes("safari") && !uaLower.includes("chrome") && !uaLower.includes("crios") && // Chrome on iOS
|
|
658
|
+
!uaLower.includes("fxios") && // Firefox on iOS
|
|
659
|
+
!uaLower.includes("android");
|
|
660
|
+
const isWebKit = /applewebkit/i.test(ua);
|
|
661
|
+
const isMobile = /mobile/i.test(ua);
|
|
662
|
+
const missingSafariToken = !/safari/i.test(ua);
|
|
663
|
+
const isUIWebView = isWebKit && isMobile && missingSafariToken;
|
|
664
|
+
const isWeChatUA = /(micromessenger|wxwork|wecom|windowswechat|macwechat)/i.test(ua);
|
|
665
|
+
const isBaiduUA = /(baiduboxapp|baidubrowser|baidusearch|baiduboxlite)/i.test(uaLower);
|
|
666
|
+
const isIOSWebKit = /ipad|iphone|ipod/.test(uaLower) && isWebKit;
|
|
667
|
+
return isSafariUA || isUIWebView || isWeChatUA || isBaiduUA || isIOSWebKit;
|
|
672
668
|
}
|
|
673
669
|
|
|
674
670
|
// src/modules/styles.js
|
|
@@ -714,6 +710,22 @@
|
|
|
714
710
|
}
|
|
715
711
|
out[prop] = val;
|
|
716
712
|
}
|
|
713
|
+
const EXTRA_TEXT_DECORATION_PROPS = [
|
|
714
|
+
"text-decoration-line",
|
|
715
|
+
"text-decoration-color",
|
|
716
|
+
"text-decoration-style",
|
|
717
|
+
"text-decoration-thickness",
|
|
718
|
+
"text-underline-offset",
|
|
719
|
+
"text-decoration-skip-ink"
|
|
720
|
+
];
|
|
721
|
+
for (const prop of EXTRA_TEXT_DECORATION_PROPS) {
|
|
722
|
+
if (out[prop]) continue;
|
|
723
|
+
try {
|
|
724
|
+
const v = style.getPropertyValue(prop);
|
|
725
|
+
if (v) out[prop] = v;
|
|
726
|
+
} catch (e) {
|
|
727
|
+
}
|
|
728
|
+
}
|
|
717
729
|
if (options.embedFonts) {
|
|
718
730
|
const EXTRA_FONT_PROPS = [
|
|
719
731
|
"font-feature-settings",
|
|
@@ -960,7 +972,7 @@
|
|
|
960
972
|
}
|
|
961
973
|
}
|
|
962
974
|
|
|
963
|
-
// src/
|
|
975
|
+
// src/utils/clone.helpers.js
|
|
964
976
|
function idleCallback(childList, callback, fast) {
|
|
965
977
|
return Promise.all(childList.map((child) => {
|
|
966
978
|
return new Promise((resolve) => {
|
|
@@ -1177,6 +1189,143 @@
|
|
|
1177
1189
|
return wrapper;
|
|
1178
1190
|
});
|
|
1179
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
|
|
1180
1329
|
function deepClone(node, sessionCache, options) {
|
|
1181
1330
|
return __async(this, null, function* () {
|
|
1182
1331
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -1482,17 +1631,19 @@
|
|
|
1482
1631
|
/layui/i,
|
|
1483
1632
|
/lucide/i
|
|
1484
1633
|
];
|
|
1634
|
+
var ICON_FONT_URLS = Object.assign({
|
|
1635
|
+
materialIconsFilled: "https://fonts.gstatic.com/s/materialicons/v48/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2",
|
|
1636
|
+
materialIconsOutlined: "https://fonts.gstatic.com/s/materialiconsoutlined/v110/gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2",
|
|
1637
|
+
materialIconsRound: "https://fonts.gstatic.com/s/materialiconsround/v109/LDItaoyNOAY6Uewc665JcIzCKsKc_M9flwmPq_HTTw.woff2",
|
|
1638
|
+
materialIconsSharp: "https://fonts.gstatic.com/s/materialiconssharp/v110/oPWQ_lt5nv4pWNJpghLP75WiFR4kLh3kvmvRImcycg.woff2"
|
|
1639
|
+
}, typeof window !== "undefined" && window.__SNAPDOM_ICON_FONTS__ || {});
|
|
1485
1640
|
var userIconFonts = [];
|
|
1486
1641
|
function extendIconFonts(fonts) {
|
|
1487
1642
|
const list = Array.isArray(fonts) ? fonts : [fonts];
|
|
1488
1643
|
for (const f of list) {
|
|
1489
|
-
if (f instanceof RegExp)
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
userIconFonts.push(new RegExp(f, "i"));
|
|
1493
|
-
} else {
|
|
1494
|
-
console.warn("[snapdom] Ignored invalid iconFont value:", f);
|
|
1495
|
-
}
|
|
1644
|
+
if (f instanceof RegExp) userIconFonts.push(f);
|
|
1645
|
+
else if (typeof f === "string") userIconFonts.push(new RegExp(f, "i"));
|
|
1646
|
+
else console.warn("[snapdom] Ignored invalid iconFont value:", f);
|
|
1496
1647
|
}
|
|
1497
1648
|
}
|
|
1498
1649
|
function isIconFont2(input) {
|
|
@@ -1508,11 +1659,66 @@
|
|
|
1508
1659
|
const s = String(family).toLowerCase();
|
|
1509
1660
|
return /\bmaterial\s*icons\b/.test(s) || /\bmaterial\s*symbols\b/.test(s);
|
|
1510
1661
|
}
|
|
1662
|
+
var loadedCanvasFamilies = /* @__PURE__ */ new Map();
|
|
1663
|
+
function parseAxes(variation = "") {
|
|
1664
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
1665
|
+
const v = String(variation || "");
|
|
1666
|
+
const rx = /['"]?\s*([A-Za-z]{3,4})\s*['"]?\s*([+-]?\d+(?:\.\d+)?)\s*/g;
|
|
1667
|
+
let m;
|
|
1668
|
+
while (m = rx.exec(v)) out[m[1].toUpperCase()] = Number(m[2]);
|
|
1669
|
+
return out;
|
|
1670
|
+
}
|
|
1671
|
+
function ensureLigatureCanvasFont(cssFamily, className, axes) {
|
|
1672
|
+
return __async(this, null, function* () {
|
|
1673
|
+
var _a;
|
|
1674
|
+
const fam = String(cssFamily || "");
|
|
1675
|
+
const lowerFam = fam.toLowerCase();
|
|
1676
|
+
const cls = String(className || "").toLowerCase();
|
|
1677
|
+
if (/\bmaterial\s*icons\b/.test(lowerFam) && !/\bsymbols\b/.test(lowerFam)) {
|
|
1678
|
+
return { familyForMeasure: fam, familyForCanvas: fam };
|
|
1679
|
+
}
|
|
1680
|
+
const isSymbols = /\bmaterial\s*symbols\b/.test(lowerFam);
|
|
1681
|
+
if (!isSymbols) {
|
|
1682
|
+
return { familyForMeasure: fam, familyForCanvas: fam };
|
|
1683
|
+
}
|
|
1684
|
+
const FILL = axes && ((_a = axes.FILL) != null ? _a : axes.fill);
|
|
1685
|
+
let style = "outlined";
|
|
1686
|
+
if (/\brounded\b/.test(cls) || /\bround\b/.test(cls)) style = "rounded";
|
|
1687
|
+
else if (/\bsharp\b/.test(cls)) style = "sharp";
|
|
1688
|
+
else if (/\boutlined\b/.test(cls)) style = "outlined";
|
|
1689
|
+
const filled = FILL === 1;
|
|
1690
|
+
let pick = null;
|
|
1691
|
+
if (filled) {
|
|
1692
|
+
if (style === "outlined" && ICON_FONT_URLS.materialIconsFilled) {
|
|
1693
|
+
pick = { url: ICON_FONT_URLS.materialIconsFilled, alias: "snapdom-mi-filled" };
|
|
1694
|
+
} else if (style === "rounded" && ICON_FONT_URLS.materialIconsRound) {
|
|
1695
|
+
pick = { url: ICON_FONT_URLS.materialIconsRound, alias: "snapdom-mi-round" };
|
|
1696
|
+
} else if (style === "sharp" && ICON_FONT_URLS.materialIconsSharp) {
|
|
1697
|
+
pick = { url: ICON_FONT_URLS.materialIconsSharp, alias: "snapdom-mi-sharp" };
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
if (!pick) {
|
|
1701
|
+
return { familyForMeasure: fam, familyForCanvas: fam };
|
|
1702
|
+
}
|
|
1703
|
+
if (!loadedCanvasFamilies.has(pick.alias)) {
|
|
1704
|
+
try {
|
|
1705
|
+
const ff = new FontFace(pick.alias, `url(${pick.url})`, { style: "normal", weight: "400" });
|
|
1706
|
+
document.fonts.add(ff);
|
|
1707
|
+
yield ff.load();
|
|
1708
|
+
loadedCanvasFamilies.set(pick.alias, true);
|
|
1709
|
+
} catch (e) {
|
|
1710
|
+
return { familyForMeasure: fam, familyForCanvas: fam };
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1713
|
+
const quoted = `"${pick.alias}"`;
|
|
1714
|
+
return { familyForMeasure: quoted, familyForCanvas: quoted };
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1511
1717
|
function ensureMaterialFontsReady(family = "Material Icons", px = 24) {
|
|
1512
1718
|
return __async(this, null, function* () {
|
|
1513
1719
|
try {
|
|
1514
1720
|
yield Promise.all([
|
|
1515
|
-
document.fonts.load(`400 ${px}px "${family.replace(/["']/g, "")}"`),
|
|
1721
|
+
document.fonts.load(`400 ${px}px "${String(family).replace(/["']/g, "")}"`),
|
|
1516
1722
|
document.fonts.ready
|
|
1517
1723
|
]);
|
|
1518
1724
|
} catch (e) {
|
|
@@ -1522,10 +1728,8 @@
|
|
|
1522
1728
|
function resolvePaintColor(cs) {
|
|
1523
1729
|
var _a, _b;
|
|
1524
1730
|
let fill = ((_a = cs.getPropertyValue("-webkit-text-fill-color")) == null ? void 0 : _a.trim()) || "";
|
|
1525
|
-
const isTransparent = /rgba?\(\s*0\s*,\s*0\s*,\s*0\s*,\s*0\s*\)/i.test(fill);
|
|
1526
|
-
if (fill && !isTransparent && fill.toLowerCase() !== "currentcolor")
|
|
1527
|
-
return fill;
|
|
1528
|
-
}
|
|
1731
|
+
const isTransparent = /^transparent$/i.test(fill) || /rgba?\(\s*0\s*,\s*0\s*,\s*0\s*,\s*0\s*\)/i.test(fill);
|
|
1732
|
+
if (fill && !isTransparent && fill.toLowerCase() !== "currentcolor") return fill;
|
|
1529
1733
|
const c = (_b = cs.color) == null ? void 0 : _b.trim();
|
|
1530
1734
|
return c && c !== "inherit" ? c : "#000";
|
|
1531
1735
|
}
|
|
@@ -1535,18 +1739,21 @@
|
|
|
1535
1739
|
weight = "normal",
|
|
1536
1740
|
fontSize = 32,
|
|
1537
1741
|
color = "#000",
|
|
1538
|
-
variation = ""
|
|
1742
|
+
variation = "",
|
|
1743
|
+
className = ""
|
|
1539
1744
|
} = {}) {
|
|
1540
1745
|
const fam = String(family || "").replace(/^['"]+|['"]+$/g, "");
|
|
1541
1746
|
const dpr = window.devicePixelRatio || 1;
|
|
1542
|
-
|
|
1747
|
+
const axes = parseAxes(variation);
|
|
1748
|
+
const { familyForMeasure, familyForCanvas } = yield ensureLigatureCanvasFont(fam, className, axes);
|
|
1749
|
+
yield ensureMaterialFontsReady(familyForCanvas.replace(/^["']+|["']+$/g, ""), fontSize);
|
|
1543
1750
|
const span = document.createElement("span");
|
|
1544
1751
|
span.textContent = ligatureText;
|
|
1545
1752
|
span.style.position = "absolute";
|
|
1546
1753
|
span.style.visibility = "hidden";
|
|
1547
1754
|
span.style.left = "-99999px";
|
|
1548
1755
|
span.style.whiteSpace = "nowrap";
|
|
1549
|
-
span.style.fontFamily =
|
|
1756
|
+
span.style.fontFamily = familyForMeasure;
|
|
1550
1757
|
span.style.fontWeight = String(weight || "normal");
|
|
1551
1758
|
span.style.fontSize = `${fontSize}px`;
|
|
1552
1759
|
span.style.lineHeight = "1";
|
|
@@ -1554,7 +1761,6 @@
|
|
|
1554
1761
|
span.style.padding = "0";
|
|
1555
1762
|
span.style.fontFeatureSettings = "'liga' 1";
|
|
1556
1763
|
span.style.fontVariantLigatures = "normal";
|
|
1557
|
-
if (variation) span.style.fontVariationSettings = variation;
|
|
1558
1764
|
span.style.color = color;
|
|
1559
1765
|
document.body.appendChild(span);
|
|
1560
1766
|
const rect = span.getBoundingClientRect();
|
|
@@ -1566,7 +1772,7 @@
|
|
|
1566
1772
|
canvas.height = height * dpr;
|
|
1567
1773
|
const ctx = canvas.getContext("2d");
|
|
1568
1774
|
ctx.scale(dpr, dpr);
|
|
1569
|
-
ctx.font = `${weight ? `${weight} ` : ""}${fontSize}px
|
|
1775
|
+
ctx.font = `${weight ? `${weight} ` : ""}${fontSize}px ${familyForCanvas}`;
|
|
1570
1776
|
ctx.textAlign = "left";
|
|
1571
1777
|
ctx.textBaseline = "top";
|
|
1572
1778
|
ctx.fillStyle = color;
|
|
@@ -1596,21 +1802,23 @@
|
|
|
1596
1802
|
const el = cloneNodes[i];
|
|
1597
1803
|
const src = sourceNodes[i] || null;
|
|
1598
1804
|
try {
|
|
1599
|
-
const
|
|
1600
|
-
const family =
|
|
1805
|
+
const cs = src ? getComputedStyle(src) : getComputedStyle(el);
|
|
1806
|
+
const family = cs.fontFamily || "Material Icons";
|
|
1601
1807
|
if (!isMaterialFamily(family)) continue;
|
|
1602
1808
|
const text = (src || el).textContent.trim();
|
|
1603
1809
|
if (!text) continue;
|
|
1604
|
-
const size = parseInt(
|
|
1605
|
-
const weight =
|
|
1606
|
-
const color = resolvePaintColor(
|
|
1607
|
-
const variation =
|
|
1810
|
+
const size = parseInt(cs.fontSize, 10) || 24;
|
|
1811
|
+
const weight = cs.fontWeight && cs.fontWeight !== "normal" ? cs.fontWeight : "normal";
|
|
1812
|
+
const color = resolvePaintColor(cs);
|
|
1813
|
+
const variation = cs.fontVariationSettings && cs.fontVariationSettings !== "normal" ? cs.fontVariationSettings : "";
|
|
1814
|
+
const className = (src || el).className || "";
|
|
1608
1815
|
const { dataUrl, width, height } = yield materialIconToImage(text, {
|
|
1609
1816
|
family,
|
|
1610
1817
|
weight,
|
|
1611
1818
|
fontSize: size,
|
|
1612
1819
|
color,
|
|
1613
|
-
variation
|
|
1820
|
+
variation,
|
|
1821
|
+
className
|
|
1614
1822
|
});
|
|
1615
1823
|
el.textContent = "";
|
|
1616
1824
|
const img = el.ownerDocument.createElement("img");
|
|
@@ -1988,7 +2196,7 @@ ${imported}
|
|
|
1988
2196
|
const styleSpec = (((_c = block.match(/font-style:\s*([^;]+);/i)) == null ? void 0 : _c[1]) || "normal").trim();
|
|
1989
2197
|
const stretchSpec = (((_d = block.match(/font-stretch:\s*([^;]+);/i)) == null ? void 0 : _d[1]) || "100%").trim();
|
|
1990
2198
|
const urange = (((_e = block.match(/unicode-range:\s*([^;]+);/i)) == null ? void 0 : _e[1]) || "").trim();
|
|
1991
|
-
const srcRaw = (((_f = block.match(/src\s*:\s*([^;]+)
|
|
2199
|
+
const srcRaw = (((_f = block.match(/src\s*:\s*([^;}]+)[;}]/i)) == null ? void 0 : _f[1]) || "").trim();
|
|
1992
2200
|
const urls = extractSrcUrls(srcRaw, location.href);
|
|
1993
2201
|
const srcPart = urls.length ? urls.map((u) => String(u).toLowerCase()).sort().join("|") : srcRaw.toLowerCase();
|
|
1994
2202
|
const key = [
|
|
@@ -2200,7 +2408,7 @@ ${imported}
|
|
|
2200
2408
|
const styleSpec = (((_d = face.match(/font-style:\s*([^;]+);/i)) == null ? void 0 : _d[1]) || "normal").trim();
|
|
2201
2409
|
const stretchSpec = (((_e = face.match(/font-stretch:\s*([^;]+);/i)) == null ? void 0 : _e[1]) || "100%").trim();
|
|
2202
2410
|
const urange = (((_f = face.match(/unicode-range:\s*([^;]+);/i)) == null ? void 0 : _f[1]) || "").trim();
|
|
2203
|
-
const srcRaw = (((_g = face.match(/src\s*:\s*([^;]+)
|
|
2411
|
+
const srcRaw = (((_g = face.match(/src\s*:\s*([^;}]+)[;}]/i)) == null ? void 0 : _g[1]) || "").trim();
|
|
2204
2412
|
const srcUrls = extractSrcUrls(srcRaw, link.href);
|
|
2205
2413
|
if (!faceMatchesRequired(family, styleSpec, weightSpec, stretchSpec)) continue;
|
|
2206
2414
|
const ranges = parseUnicodeRange(urange);
|
|
@@ -2620,6 +2828,152 @@ ${imported}
|
|
|
2620
2828
|
}
|
|
2621
2829
|
|
|
2622
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
|
+
}
|
|
2623
2977
|
var __siblingCounters = /* @__PURE__ */ new WeakMap();
|
|
2624
2978
|
var __pseudoEpoch = -1;
|
|
2625
2979
|
function unquoteDoubleStrings2(s) {
|
|
@@ -2718,8 +3072,12 @@ ${imported}
|
|
|
2718
3072
|
}
|
|
2719
3073
|
function inlinePseudoElements(source, clone, sessionCache, options) {
|
|
2720
3074
|
return __async(this, null, function* () {
|
|
2721
|
-
var _a, _b, _c, _d;
|
|
3075
|
+
var _a, _b, _c, _d, _e;
|
|
2722
3076
|
if (!(source instanceof Element) || !(clone instanceof Element)) return;
|
|
3077
|
+
const doc = source.ownerDocument || document;
|
|
3078
|
+
if (!preflightWithFp(doc, sessionCache)) {
|
|
3079
|
+
return;
|
|
3080
|
+
}
|
|
2723
3081
|
const epoch = (_c = (_b = (_a = cache) == null ? void 0 : _a.session) == null ? void 0 : _b.__counterEpoch) != null ? _c : 0;
|
|
2724
3082
|
if (__pseudoEpoch !== epoch) {
|
|
2725
3083
|
__siblingCounters = /* @__PURE__ */ new WeakMap();
|
|
@@ -2736,7 +3094,7 @@ ${imported}
|
|
|
2736
3094
|
for (const pseudo of ["::before", "::after", "::first-letter"]) {
|
|
2737
3095
|
try {
|
|
2738
3096
|
const style = getStyle(source, pseudo);
|
|
2739
|
-
if (!style
|
|
3097
|
+
if (!style) continue;
|
|
2740
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";
|
|
2741
3099
|
if (isEmptyPseudo) continue;
|
|
2742
3100
|
if (pseudo === "::first-letter") {
|
|
@@ -2766,7 +3124,8 @@ ${imported}
|
|
|
2766
3124
|
clone.insertBefore(span, restNode);
|
|
2767
3125
|
continue;
|
|
2768
3126
|
}
|
|
2769
|
-
const rawContent = style.content;
|
|
3127
|
+
const rawContent = (_d = style.content) != null ? _d : "";
|
|
3128
|
+
const isNoExplicitContent = rawContent === "" || rawContent === "none" || rawContent === "normal";
|
|
2770
3129
|
const { text: cleanContent, incs } = resolvePseudoContentAndIncs(source, pseudo, counterCtx);
|
|
2771
3130
|
const bg = style.backgroundImage;
|
|
2772
3131
|
const bgColor = style.backgroundColor;
|
|
@@ -2778,7 +3137,7 @@ ${imported}
|
|
|
2778
3137
|
const borderWidth = parseFloat(style.borderWidth);
|
|
2779
3138
|
const transform = style.transform;
|
|
2780
3139
|
const isIconFont22 = isIconFont2(fontFamily);
|
|
2781
|
-
const hasExplicitContent =
|
|
3140
|
+
const hasExplicitContent = !isNoExplicitContent && cleanContent !== "";
|
|
2782
3141
|
const hasBg = bg && bg !== "none";
|
|
2783
3142
|
const hasBgColor = bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)";
|
|
2784
3143
|
const hasBorder = borderStyle && borderStyle !== "none" && borderWidth > 0;
|
|
@@ -2800,8 +3159,6 @@ ${imported}
|
|
|
2800
3159
|
}
|
|
2801
3160
|
const pseudoEl = document.createElement("span");
|
|
2802
3161
|
pseudoEl.dataset.snapdomPseudo = pseudo;
|
|
2803
|
-
pseudoEl.style.display = "inline";
|
|
2804
|
-
pseudoEl.style.verticalAlign = "baseline";
|
|
2805
3162
|
pseudoEl.style.pointerEvents = "none";
|
|
2806
3163
|
const snapshot = snapshotComputedStyle(style);
|
|
2807
3164
|
const key = getStyleKey(snapshot, "span");
|
|
@@ -2857,7 +3214,7 @@ ${imported}
|
|
|
2857
3214
|
}
|
|
2858
3215
|
}
|
|
2859
3216
|
if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
|
|
2860
|
-
const hasContent2 = pseudoEl.childNodes.length > 0 || ((
|
|
3217
|
+
const hasContent2 = pseudoEl.childNodes.length > 0 || ((_e = pseudoEl.textContent) == null ? void 0 : _e.trim()) !== "";
|
|
2861
3218
|
const hasVisibleBox = hasContent2 || hasBg || hasBgColor || hasBorder || hasTransform;
|
|
2862
3219
|
if (incs && incs.length && source.parentElement) {
|
|
2863
3220
|
const map = __siblingCounters.get(source.parentElement) || /* @__PURE__ */ new Map();
|
|
@@ -3096,6 +3453,20 @@ ${imported}
|
|
|
3096
3453
|
return out;
|
|
3097
3454
|
}
|
|
3098
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
|
+
|
|
3099
3470
|
// src/core/prepare.js
|
|
3100
3471
|
function prepareClone(_0) {
|
|
3101
3472
|
return __async(this, arguments, function* (element, options = {}) {
|
|
@@ -3199,163 +3570,27 @@ ${imported}
|
|
|
3199
3570
|
return { clone, classCSS, styleCache: sessionCache.styleCache };
|
|
3200
3571
|
});
|
|
3201
3572
|
}
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
const
|
|
3207
|
-
const
|
|
3208
|
-
const
|
|
3209
|
-
const
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
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 };
|
|
3213
3586
|
}
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
var _a2;
|
|
3222
|
-
const r = yield snapFetch(blobUrl, { as: "dataURL", silent: true });
|
|
3223
|
-
if (!r.ok || typeof r.data !== "string") {
|
|
3224
|
-
throw new Error(`[snapDOM] Failed to read blob URL: ${blobUrl}`);
|
|
3225
|
-
}
|
|
3226
|
-
(_a2 = cache.resource) == null ? void 0 : _a2.set(blobUrl, r.data);
|
|
3227
|
-
return r.data;
|
|
3228
|
-
}))();
|
|
3229
|
-
_blobToDataUrlCache.set(blobUrl, p);
|
|
3230
|
-
try {
|
|
3231
|
-
const data = yield p;
|
|
3232
|
-
_blobToDataUrlCache.set(blobUrl, data);
|
|
3233
|
-
return data;
|
|
3234
|
-
} catch (e) {
|
|
3235
|
-
_blobToDataUrlCache.delete(blobUrl);
|
|
3236
|
-
throw e;
|
|
3237
|
-
}
|
|
3238
|
-
});
|
|
3239
|
-
}
|
|
3240
|
-
var BLOB_URL_RE = /\bblob:[^)"'\s]+/g;
|
|
3241
|
-
function replaceBlobUrlsInCssText(cssText) {
|
|
3242
|
-
return __async(this, null, function* () {
|
|
3243
|
-
if (!cssText || cssText.indexOf("blob:") === -1) return cssText;
|
|
3244
|
-
const uniques = Array.from(new Set(cssText.match(BLOB_URL_RE) || []));
|
|
3245
|
-
if (uniques.length === 0) return cssText;
|
|
3246
|
-
let out = cssText;
|
|
3247
|
-
for (const u of uniques) {
|
|
3248
|
-
try {
|
|
3249
|
-
const d = yield blobUrlToDataUrl(u);
|
|
3250
|
-
out = out.split(u).join(d);
|
|
3251
|
-
} catch (e) {
|
|
3252
|
-
}
|
|
3253
|
-
}
|
|
3254
|
-
return out;
|
|
3255
|
-
});
|
|
3256
|
-
}
|
|
3257
|
-
function isBlobUrl(u) {
|
|
3258
|
-
return typeof u === "string" && u.startsWith("blob:");
|
|
3259
|
-
}
|
|
3260
|
-
function parseSrcset(srcset) {
|
|
3261
|
-
return (srcset || "").split(",").map((s) => s.trim()).filter(Boolean).map((item) => {
|
|
3262
|
-
const m = item.match(/^(\S+)(\s+.+)?$/);
|
|
3263
|
-
return m ? { url: m[1], desc: m[2] || "" } : null;
|
|
3264
|
-
}).filter(Boolean);
|
|
3265
|
-
}
|
|
3266
|
-
function stringifySrcset(parts) {
|
|
3267
|
-
return parts.map((p) => p.desc ? `${p.url} ${p.desc.trim()}` : p.url).join(", ");
|
|
3268
|
-
}
|
|
3269
|
-
function resolveBlobUrlsInTree(root) {
|
|
3270
|
-
return __async(this, null, function* () {
|
|
3271
|
-
var _a, _b;
|
|
3272
|
-
if (!root) return;
|
|
3273
|
-
const imgs = root.querySelectorAll ? root.querySelectorAll("img") : [];
|
|
3274
|
-
for (const img of imgs) {
|
|
3275
|
-
try {
|
|
3276
|
-
const srcAttr = img.getAttribute("src");
|
|
3277
|
-
const effective = srcAttr || img.currentSrc || "";
|
|
3278
|
-
if (isBlobUrl(effective)) {
|
|
3279
|
-
const data = yield blobUrlToDataUrl(effective);
|
|
3280
|
-
img.setAttribute("src", data);
|
|
3281
|
-
}
|
|
3282
|
-
const srcset = img.getAttribute("srcset");
|
|
3283
|
-
if (srcset && srcset.includes("blob:")) {
|
|
3284
|
-
const parts = parseSrcset(srcset);
|
|
3285
|
-
let changed = false;
|
|
3286
|
-
for (const p of parts) {
|
|
3287
|
-
if (isBlobUrl(p.url)) {
|
|
3288
|
-
try {
|
|
3289
|
-
p.url = yield blobUrlToDataUrl(p.url);
|
|
3290
|
-
changed = true;
|
|
3291
|
-
} catch (e) {
|
|
3292
|
-
}
|
|
3293
|
-
}
|
|
3294
|
-
}
|
|
3295
|
-
if (changed) img.setAttribute("srcset", stringifySrcset(parts));
|
|
3296
|
-
}
|
|
3297
|
-
} catch (e) {
|
|
3298
|
-
}
|
|
3299
|
-
}
|
|
3300
|
-
const svgImages = root.querySelectorAll ? root.querySelectorAll("image") : [];
|
|
3301
|
-
for (const node of svgImages) {
|
|
3302
|
-
try {
|
|
3303
|
-
const XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
3304
|
-
const href = node.getAttribute("href") || ((_a = node.getAttributeNS) == null ? void 0 : _a.call(node, XLINK_NS, "href"));
|
|
3305
|
-
if (isBlobUrl(href)) {
|
|
3306
|
-
const d = yield blobUrlToDataUrl(href);
|
|
3307
|
-
node.setAttribute("href", d);
|
|
3308
|
-
(_b = node.removeAttributeNS) == null ? void 0 : _b.call(node, XLINK_NS, "href");
|
|
3309
|
-
}
|
|
3310
|
-
} catch (e) {
|
|
3311
|
-
}
|
|
3312
|
-
}
|
|
3313
|
-
const styled = root.querySelectorAll ? root.querySelectorAll("[style*='blob:']") : [];
|
|
3314
|
-
for (const el of styled) {
|
|
3315
|
-
try {
|
|
3316
|
-
const styleText = el.getAttribute("style");
|
|
3317
|
-
if (styleText && styleText.includes("blob:")) {
|
|
3318
|
-
const replaced = yield replaceBlobUrlsInCssText(styleText);
|
|
3319
|
-
el.setAttribute("style", replaced);
|
|
3320
|
-
}
|
|
3321
|
-
} catch (e) {
|
|
3322
|
-
}
|
|
3323
|
-
}
|
|
3324
|
-
const styleTags = root.querySelectorAll ? root.querySelectorAll("style") : [];
|
|
3325
|
-
for (const s of styleTags) {
|
|
3326
|
-
try {
|
|
3327
|
-
const css = s.textContent || "";
|
|
3328
|
-
if (css.includes("blob:")) {
|
|
3329
|
-
s.textContent = yield replaceBlobUrlsInCssText(css);
|
|
3330
|
-
}
|
|
3331
|
-
} catch (e) {
|
|
3332
|
-
}
|
|
3333
|
-
}
|
|
3334
|
-
const urlAttrs = ["poster"];
|
|
3335
|
-
for (const attr of urlAttrs) {
|
|
3336
|
-
const nodes = root.querySelectorAll ? root.querySelectorAll(`[${attr}^='blob:']`) : [];
|
|
3337
|
-
for (const n of nodes) {
|
|
3338
|
-
try {
|
|
3339
|
-
const u = n.getAttribute(attr);
|
|
3340
|
-
if (isBlobUrl(u)) {
|
|
3341
|
-
n.setAttribute(attr, yield blobUrlToDataUrl(u));
|
|
3342
|
-
}
|
|
3343
|
-
} catch (e) {
|
|
3344
|
-
}
|
|
3345
|
-
}
|
|
3346
|
-
}
|
|
3347
|
-
});
|
|
3348
|
-
}
|
|
3349
|
-
|
|
3350
|
-
// src/modules/images.js
|
|
3351
|
-
function inlineImages(_0) {
|
|
3352
|
-
return __async(this, arguments, function* (clone, options = {}) {
|
|
3353
|
-
const imgs = Array.from(clone.querySelectorAll("img"));
|
|
3354
|
-
const processImg = (img) => __async(null, null, function* () {
|
|
3355
|
-
var _a, _b, _c, _d;
|
|
3356
|
-
if (!img.getAttribute("src")) {
|
|
3357
|
-
const eff = img.currentSrc || img.src || "";
|
|
3358
|
-
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);
|
|
3359
3594
|
}
|
|
3360
3595
|
img.removeAttribute("srcset");
|
|
3361
3596
|
img.removeAttribute("sizes");
|
|
@@ -3368,41 +3603,30 @@ ${imported}
|
|
|
3368
3603
|
if (!img.height) img.height = img.naturalHeight || 100;
|
|
3369
3604
|
return;
|
|
3370
3605
|
}
|
|
3606
|
+
const { width: fbW, height: fbH } = extractImageDimensions(img);
|
|
3371
3607
|
const { fallbackURL } = options || {};
|
|
3372
3608
|
if (fallbackURL) {
|
|
3373
3609
|
try {
|
|
3374
|
-
const dsW = parseInt(((_a = img.dataset) == null ? void 0 : _a.snapdomWidth) || "", 10) || 0;
|
|
3375
|
-
const dsH = parseInt(((_b = img.dataset) == null ? void 0 : _b.snapdomHeight) || "", 10) || 0;
|
|
3376
|
-
const attrW = parseInt(img.getAttribute("width") || "", 10) || 0;
|
|
3377
|
-
const attrH = parseInt(img.getAttribute("height") || "", 10) || 0;
|
|
3378
|
-
const styleW = parseFloat(((_c = img.style) == null ? void 0 : _c.width) || "") || 0;
|
|
3379
|
-
const styleH = parseFloat(((_d = img.style) == null ? void 0 : _d.height) || "") || 0;
|
|
3380
|
-
const fbW = dsW || styleW || attrW || img.width || void 0;
|
|
3381
|
-
const fbH = dsH || styleH || attrH || img.height || void 0;
|
|
3382
3610
|
const fallbackUrl = typeof fallbackURL === "function" ? yield fallbackURL({ width: fbW, height: fbH, src, element: img }) : fallbackURL;
|
|
3383
3611
|
if (fallbackUrl) {
|
|
3384
3612
|
const fallbackData = yield snapFetch(fallbackUrl, { as: "dataURL", useProxy: options.useProxy });
|
|
3385
3613
|
img.src = fallbackData.data;
|
|
3386
|
-
if (!img.width
|
|
3387
|
-
if (!img.height
|
|
3388
|
-
if (!img.width) img.width = img.naturalWidth || 100;
|
|
3389
|
-
if (!img.height) img.height = img.naturalHeight || 100;
|
|
3614
|
+
if (!img.width) img.width = fbW;
|
|
3615
|
+
if (!img.height) img.height = fbH;
|
|
3390
3616
|
return;
|
|
3391
3617
|
}
|
|
3392
3618
|
} catch (e) {
|
|
3393
3619
|
}
|
|
3394
3620
|
}
|
|
3395
|
-
const w = img.width || img.naturalWidth || 100;
|
|
3396
|
-
const h = img.height || img.naturalHeight || 100;
|
|
3397
3621
|
if (options.placeholders !== false) {
|
|
3398
3622
|
const fallback = document.createElement("div");
|
|
3399
3623
|
fallback.style.cssText = [
|
|
3400
|
-
`width:${
|
|
3401
|
-
`height:${
|
|
3624
|
+
`width:${fbW}px`,
|
|
3625
|
+
`height:${fbH}px`,
|
|
3402
3626
|
"background:#ccc",
|
|
3403
3627
|
"display:inline-block",
|
|
3404
3628
|
"text-align:center",
|
|
3405
|
-
`line-height:${
|
|
3629
|
+
`line-height:${fbH}px`,
|
|
3406
3630
|
"color:#666",
|
|
3407
3631
|
"font-size:12px",
|
|
3408
3632
|
"overflow:hidden"
|
|
@@ -3411,7 +3635,7 @@ ${imported}
|
|
|
3411
3635
|
img.replaceWith(fallback);
|
|
3412
3636
|
} else {
|
|
3413
3637
|
const spacer = document.createElement("div");
|
|
3414
|
-
spacer.style.cssText = `display:inline-block;width:${
|
|
3638
|
+
spacer.style.cssText = `display:inline-block;width:${fbW}px;height:${fbH}px;visibility:hidden;`;
|
|
3415
3639
|
img.replaceWith(spacer);
|
|
3416
3640
|
}
|
|
3417
3641
|
});
|
|
@@ -3659,7 +3883,7 @@ ${imported}
|
|
|
3659
3883
|
return context;
|
|
3660
3884
|
}
|
|
3661
3885
|
|
|
3662
|
-
// src/
|
|
3886
|
+
// src/utils/capture.helpers.js
|
|
3663
3887
|
function stripRootShadows(originalEl, cloneRoot) {
|
|
3664
3888
|
if (!originalEl || !cloneRoot || !cloneRoot.style) return;
|
|
3665
3889
|
const cs = getComputedStyle(originalEl);
|
|
@@ -3682,219 +3906,180 @@ ${imported}
|
|
|
3682
3906
|
} catch (e) {
|
|
3683
3907
|
}
|
|
3684
3908
|
}
|
|
3685
|
-
function
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
try {
|
|
3703
|
-
({ clone, classCSS, styleCache } = yield prepareClone(state.element, state.options));
|
|
3704
|
-
if (!outerTransforms && clone) {
|
|
3705
|
-
rootTransform2D = normalizeRootTransforms(state.element, clone);
|
|
3909
|
+
function removeAllComments(root) {
|
|
3910
|
+
const it = document.createTreeWalker(root, NodeFilter.SHOW_COMMENT);
|
|
3911
|
+
const toRemove = [];
|
|
3912
|
+
while (it.nextNode()) toRemove.push(it.currentNode);
|
|
3913
|
+
for (const n of toRemove) n.remove();
|
|
3914
|
+
}
|
|
3915
|
+
function sanitizeAttributesForXHTML(root, opts = {}) {
|
|
3916
|
+
const { stripFrameworkDirectives = true } = opts;
|
|
3917
|
+
const ALLOWED_PREFIXES = /* @__PURE__ */ new Set(["xml", "xlink"]);
|
|
3918
|
+
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
|
|
3919
|
+
while (walker.nextNode()) {
|
|
3920
|
+
const el = walker.currentNode;
|
|
3921
|
+
for (const attr of Array.from(el.attributes)) {
|
|
3922
|
+
const name = attr.name;
|
|
3923
|
+
if (name.includes("@")) {
|
|
3924
|
+
el.removeAttribute(name);
|
|
3925
|
+
continue;
|
|
3706
3926
|
}
|
|
3707
|
-
if (
|
|
3708
|
-
|
|
3927
|
+
if (name.includes(":")) {
|
|
3928
|
+
const prefix = name.split(":", 1)[0];
|
|
3929
|
+
if (!ALLOWED_PREFIXES.has(prefix)) {
|
|
3930
|
+
el.removeAttribute(name);
|
|
3931
|
+
continue;
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
if (!stripFrameworkDirectives) continue;
|
|
3935
|
+
if (name.startsWith("x-") || // Alpine
|
|
3936
|
+
name.startsWith("v-") || // Vue
|
|
3937
|
+
name.startsWith(":") || // Vue/Alpine shorthand
|
|
3938
|
+
name.startsWith("on:") || // Svelte
|
|
3939
|
+
name.startsWith("bind:") || // Svelte
|
|
3940
|
+
name.startsWith("let:") || // Svelte
|
|
3941
|
+
name.startsWith("class:")) {
|
|
3942
|
+
el.removeAttribute(name);
|
|
3943
|
+
continue;
|
|
3709
3944
|
}
|
|
3710
|
-
} finally {
|
|
3711
|
-
undoClamp();
|
|
3712
3945
|
}
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
function sanitizeCloneForXHTML(root, opts = {}) {
|
|
3949
|
+
if (!root) return;
|
|
3950
|
+
sanitizeAttributesForXHTML(root, opts);
|
|
3951
|
+
removeAllComments(root);
|
|
3952
|
+
}
|
|
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";
|
|
3995
|
+
}
|
|
3718
3996
|
}
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
}), { fast });
|
|
3724
|
-
});
|
|
3725
|
-
yield new Promise((resolve) => {
|
|
3726
|
-
idle(() => __async(null, null, function* () {
|
|
3727
|
-
yield inlineBackgroundImages(state.element, state.clone, state.styleCache, state.options);
|
|
3728
|
-
resolve();
|
|
3729
|
-
}), { fast });
|
|
3730
|
-
});
|
|
3731
|
-
if (options.embedFonts) {
|
|
3732
|
-
yield new Promise((resolve) => {
|
|
3733
|
-
idle(() => __async(null, null, function* () {
|
|
3734
|
-
const required = collectUsedFontVariants(state.element);
|
|
3735
|
-
const usedCodepoints = collectUsedCodepoints(state.element);
|
|
3736
|
-
if (isSafari()) {
|
|
3737
|
-
const families = new Set(
|
|
3738
|
-
Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
|
|
3739
|
-
);
|
|
3740
|
-
yield ensureFontsReady(families, 1);
|
|
3741
|
-
}
|
|
3742
|
-
fontsCSS = yield embedCustomFonts({
|
|
3743
|
-
required,
|
|
3744
|
-
usedCodepoints,
|
|
3745
|
-
preCached: false,
|
|
3746
|
-
exclude: state.options.excludeFonts,
|
|
3747
|
-
useProxy: state.options.useProxy
|
|
3748
|
-
});
|
|
3749
|
-
resolve();
|
|
3750
|
-
}), { fast });
|
|
3751
|
-
});
|
|
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]);
|
|
3752
4001
|
}
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
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) {
|
|
4018
|
+
try {
|
|
4019
|
+
if (el.matches(sel)) return options.excludeMode === "remove";
|
|
4020
|
+
} catch (e) {
|
|
4021
|
+
}
|
|
3765
4022
|
}
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
3790
|
-
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
} else {
|
|
3794
|
-
w = w0;
|
|
3795
|
-
h = h0;
|
|
3796
|
-
}
|
|
3797
|
-
let minX = 0, minY = 0, maxX = w0, maxY = h0;
|
|
3798
|
-
if (!outerTransforms && rootTransform2D && Number.isFinite(rootTransform2D.a)) {
|
|
3799
|
-
const M2 = {
|
|
3800
|
-
a: rootTransform2D.a,
|
|
3801
|
-
b: rootTransform2D.b || 0,
|
|
3802
|
-
c: rootTransform2D.c || 0,
|
|
3803
|
-
d: rootTransform2D.d || 1,
|
|
3804
|
-
e: 0,
|
|
3805
|
-
f: 0
|
|
3806
|
-
};
|
|
3807
|
-
const bb2 = bboxWithOriginFull(w0, h0, M2, 0, 0);
|
|
3808
|
-
minX = limitDecimals(bb2.minX);
|
|
3809
|
-
minY = limitDecimals(bb2.minY);
|
|
3810
|
-
maxX = limitDecimals(bb2.maxX);
|
|
3811
|
-
maxY = limitDecimals(bb2.maxY);
|
|
3812
|
-
} else {
|
|
3813
|
-
const useTFBBox = outerTransforms && hasTFBBox(state.element);
|
|
3814
|
-
if (useTFBBox) {
|
|
3815
|
-
const baseTransform2 = csEl.transform && csEl.transform !== "none" ? csEl.transform : "";
|
|
3816
|
-
const ind2 = readIndividualTransforms(state.element);
|
|
3817
|
-
const TOTAL = readTotalTransformMatrix({
|
|
3818
|
-
baseTransform: baseTransform2,
|
|
3819
|
-
rotate: ind2.rotate || "0deg",
|
|
3820
|
-
scale: ind2.scale,
|
|
3821
|
-
translate: ind2.translate
|
|
3822
|
-
});
|
|
3823
|
-
const { ox: ox2, oy: oy2 } = parseTransformOriginPx(csEl, w0, h0);
|
|
3824
|
-
const M = TOTAL.is2D ? TOTAL : new DOMMatrix(TOTAL.toString());
|
|
3825
|
-
const bb = bboxWithOriginFull(w0, h0, M, ox2, oy2);
|
|
3826
|
-
minX = limitDecimals(bb.minX);
|
|
3827
|
-
minY = limitDecimals(bb.minY);
|
|
3828
|
-
maxX = limitDecimals(bb.maxX);
|
|
3829
|
-
maxY = limitDecimals(bb.maxY);
|
|
3830
|
-
}
|
|
3831
|
-
}
|
|
3832
|
-
const bleedShadow = parseBoxShadow(csEl);
|
|
3833
|
-
const bleedBlur = parseFilterBlur(csEl);
|
|
3834
|
-
const bleedOutline = parseOutline(csEl);
|
|
3835
|
-
const drop = parseFilterDropShadows(csEl);
|
|
3836
|
-
const bleed = !outerShadows ? { top: 0, right: 0, bottom: 0, left: 0 } : {
|
|
3837
|
-
top: limitDecimals(bleedShadow.top + bleedBlur.top + bleedOutline.top + drop.bleed.top),
|
|
3838
|
-
right: limitDecimals(bleedShadow.right + bleedBlur.right + bleedOutline.right + drop.bleed.right),
|
|
3839
|
-
bottom: limitDecimals(bleedShadow.bottom + bleedBlur.bottom + bleedOutline.bottom + drop.bleed.bottom),
|
|
3840
|
-
left: limitDecimals(bleedShadow.left + bleedBlur.left + bleedOutline.left + drop.bleed.left)
|
|
3841
|
-
};
|
|
3842
|
-
minX = limitDecimals(minX - bleed.left);
|
|
3843
|
-
minY = limitDecimals(minY - bleed.top);
|
|
3844
|
-
maxX = limitDecimals(maxX + bleed.right);
|
|
3845
|
-
maxY = limitDecimals(maxY + bleed.bottom);
|
|
3846
|
-
const vbW0 = Math.max(1, limitDecimals(maxX - minX));
|
|
3847
|
-
const vbH0 = Math.max(1, limitDecimals(maxY - minY));
|
|
3848
|
-
const scaleW = hasW || hasH ? limitDecimals(w / w0) : 1;
|
|
3849
|
-
const scaleH = hasH || hasW ? limitDecimals(h / h0) : 1;
|
|
3850
|
-
const outW = Math.max(1, limitDecimals(vbW0 * scaleW));
|
|
3851
|
-
const outH = Math.max(1, limitDecimals(vbH0 * scaleH));
|
|
3852
|
-
const svgNS = "http://www.w3.org/2000/svg";
|
|
3853
|
-
const basePad = isSafari() ? 1 : 0;
|
|
3854
|
-
const extraPad = !outerTransforms ? 1 : 0;
|
|
3855
|
-
const pad = limitDecimals(basePad + extraPad);
|
|
3856
|
-
const fo = document.createElementNS(svgNS, "foreignObject");
|
|
3857
|
-
const vbMinX = limitDecimals(minX);
|
|
3858
|
-
const vbMinY = limitDecimals(minY);
|
|
3859
|
-
fo.setAttribute("x", String(limitDecimals(-(vbMinX - pad))));
|
|
3860
|
-
fo.setAttribute("y", String(limitDecimals(-(vbMinY - pad))));
|
|
3861
|
-
fo.setAttribute("width", String(limitDecimals(w0 + pad * 2)));
|
|
3862
|
-
fo.setAttribute("height", String(limitDecimals(h0 + pad * 2)));
|
|
3863
|
-
fo.style.overflow = "visible";
|
|
3864
|
-
const styleTag = document.createElement("style");
|
|
3865
|
-
styleTag.textContent = state.baseCSS + state.fontsCSS + "svg{overflow:visible;} foreignObject{overflow:visible;}" + state.classCSS;
|
|
3866
|
-
fo.appendChild(styleTag);
|
|
3867
|
-
const container = document.createElement("div");
|
|
3868
|
-
container.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
3869
|
-
container.style.width = `${limitDecimals(w0)}px`;
|
|
3870
|
-
container.style.height = `${limitDecimals(h0)}px`;
|
|
3871
|
-
container.style.overflow = "visible";
|
|
3872
|
-
state.clone.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
|
|
3873
|
-
container.appendChild(state.clone);
|
|
3874
|
-
fo.appendChild(container);
|
|
3875
|
-
const serializer = new XMLSerializer();
|
|
3876
|
-
const foString = serializer.serializeToString(fo);
|
|
3877
|
-
const vbW = limitDecimals(vbW0 + pad * 2);
|
|
3878
|
-
const vbH = limitDecimals(vbH0 + pad * 2);
|
|
3879
|
-
const wantsSize = hasW || hasH;
|
|
3880
|
-
options.meta = { w0, h0, vbW, vbH, targetW: w, targetH: h };
|
|
3881
|
-
const svgOutW = isSafari() && wantsSize ? vbW : limitDecimals(outW + pad * 2);
|
|
3882
|
-
const svgOutH = isSafari() && wantsSize ? vbH : limitDecimals(outH + pad * 2);
|
|
3883
|
-
const svgHeader = `<svg xmlns="${svgNS}" width="${svgOutW}" height="${svgOutH}" viewBox="0 0 ${vbW} ${vbH}">`;
|
|
3884
|
-
const svgFooter = "</svg>";
|
|
3885
|
-
svgString = svgHeader + foString + svgFooter;
|
|
3886
|
-
dataURL = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}`;
|
|
3887
|
-
state = __spreadValues({ svgString, dataURL }, state);
|
|
3888
|
-
resolve();
|
|
3889
|
-
}, { fast });
|
|
3890
|
-
});
|
|
3891
|
-
yield runHook("afterRender", state);
|
|
3892
|
-
const sandbox = document.getElementById("snapdom-sandbox");
|
|
3893
|
-
if (sandbox && sandbox.style.position === "absolute") sandbox.remove();
|
|
3894
|
-
return state.dataURL;
|
|
3895
|
-
});
|
|
4023
|
+
}
|
|
4024
|
+
return false;
|
|
4025
|
+
}
|
|
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;
|
|
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;
|
|
3896
4050
|
}
|
|
3897
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) };
|
|
4072
|
+
}
|
|
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 };
|
|
4077
|
+
}
|
|
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 };
|
|
4082
|
+
}
|
|
3898
4083
|
function parseFilterDropShadows(cs) {
|
|
3899
4084
|
var _a;
|
|
3900
4085
|
const raw = `${cs.filter || ""} ${cs.webkitFilter || ""}`.trim();
|
|
@@ -3984,35 +4169,6 @@ ${imported}
|
|
|
3984
4169
|
return null;
|
|
3985
4170
|
}
|
|
3986
4171
|
}
|
|
3987
|
-
function parseBoxShadow(cs) {
|
|
3988
|
-
var _a;
|
|
3989
|
-
const v = cs.boxShadow || "";
|
|
3990
|
-
if (!v || v === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
3991
|
-
const parts = v.split(/\),(?=(?:[^()]*\([^()]*\))*[^()]*$)/).map((s) => s.trim());
|
|
3992
|
-
let t = 0, r = 0, b2 = 0, l = 0;
|
|
3993
|
-
for (const part of parts) {
|
|
3994
|
-
const nums = ((_a = part.match(/-?\d+(\.\d+)?px/g)) == null ? void 0 : _a.map((n) => parseFloat(n))) || [];
|
|
3995
|
-
if (nums.length < 2) continue;
|
|
3996
|
-
const [ox2, oy2, blur = 0, spread = 0] = nums;
|
|
3997
|
-
const extX = Math.abs(ox2) + blur + spread;
|
|
3998
|
-
const extY = Math.abs(oy2) + blur + spread;
|
|
3999
|
-
r = Math.max(r, extX + Math.max(ox2, 0));
|
|
4000
|
-
l = Math.max(l, extX + Math.max(-ox2, 0));
|
|
4001
|
-
b2 = Math.max(b2, extY + Math.max(oy2, 0));
|
|
4002
|
-
t = Math.max(t, extY + Math.max(-oy2, 0));
|
|
4003
|
-
}
|
|
4004
|
-
return { top: Math.ceil(t), right: Math.ceil(r), bottom: Math.ceil(b2), left: Math.ceil(l) };
|
|
4005
|
-
}
|
|
4006
|
-
function parseFilterBlur(cs) {
|
|
4007
|
-
const m = (cs.filter || "").match(/blur\(\s*([0-9.]+)px\s*\)/);
|
|
4008
|
-
const b2 = m ? Math.ceil(parseFloat(m[1]) || 0) : 0;
|
|
4009
|
-
return { top: b2, right: b2, bottom: b2, left: b2 };
|
|
4010
|
-
}
|
|
4011
|
-
function parseOutline(cs) {
|
|
4012
|
-
if ((cs.outlineStyle || "none") === "none") return { top: 0, right: 0, bottom: 0, left: 0 };
|
|
4013
|
-
const w2 = Math.ceil(parseFloat(cs.outlineWidth || "0") || 0);
|
|
4014
|
-
return { top: w2, right: w2, bottom: w2, left: w2 };
|
|
4015
|
-
}
|
|
4016
4172
|
function bboxWithOriginFull(w2, h2, M, ox2, oy2) {
|
|
4017
4173
|
const a2 = M.a, b2 = M.b, c2 = M.c, d2 = M.d, e2 = M.e || 0, f2 = M.f || 0;
|
|
4018
4174
|
function pt(x, y) {
|
|
@@ -4032,17 +4188,24 @@ ${imported}
|
|
|
4032
4188
|
}
|
|
4033
4189
|
return { minX: minX2, minY: minY2, maxX: maxX2, maxY: maxY2, width: maxX2 - minX2, height: maxY2 - minY2 };
|
|
4034
4190
|
}
|
|
4035
|
-
function
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
return
|
|
4045
|
-
|
|
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
|
+
};
|
|
4046
4209
|
}
|
|
4047
4210
|
function readIndividualTransforms(el) {
|
|
4048
4211
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -4100,35 +4263,6 @@ ${imported}
|
|
|
4100
4263
|
out.translate = cs.translate && cs.translate !== "none" ? cs.translate : null;
|
|
4101
4264
|
return out;
|
|
4102
4265
|
}
|
|
4103
|
-
function hasBBoxAffectingTransform(el) {
|
|
4104
|
-
const cs = getComputedStyle(el);
|
|
4105
|
-
const t = cs.transform || "none";
|
|
4106
|
-
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);
|
|
4107
|
-
if (hasMatrix) return true;
|
|
4108
|
-
const r = cs.rotate && cs.rotate !== "none" && cs.rotate !== "0deg";
|
|
4109
|
-
const s = cs.scale && cs.scale !== "none" && cs.scale !== "1";
|
|
4110
|
-
const tr = cs.translate && cs.translate !== "none" && cs.translate !== "0px 0px";
|
|
4111
|
-
return Boolean(r || s || tr);
|
|
4112
|
-
}
|
|
4113
|
-
function parseTransformOriginPx(cs, w, h) {
|
|
4114
|
-
const raw = (cs.transformOrigin || "0 0").trim().split(/\s+/);
|
|
4115
|
-
const [oxRaw, oyRaw] = [raw[0] || "0", raw[1] || "0"];
|
|
4116
|
-
const toPx = (token, size) => {
|
|
4117
|
-
const t = token.toLowerCase();
|
|
4118
|
-
if (t === "left" || t === "top") return 0;
|
|
4119
|
-
if (t === "center") return size / 2;
|
|
4120
|
-
if (t === "right") return size;
|
|
4121
|
-
if (t === "bottom") return size;
|
|
4122
|
-
if (t.endsWith("px")) return parseFloat(t) || 0;
|
|
4123
|
-
if (t.endsWith("%")) return (parseFloat(t) || 0) * size / 100;
|
|
4124
|
-
if (/^-?\d+(\.\d+)?$/.test(t)) return parseFloat(t) || 0;
|
|
4125
|
-
return 0;
|
|
4126
|
-
};
|
|
4127
|
-
return {
|
|
4128
|
-
ox: toPx(oxRaw, w),
|
|
4129
|
-
oy: toPx(oyRaw, h)
|
|
4130
|
-
};
|
|
4131
|
-
}
|
|
4132
4266
|
var __measureHost = null;
|
|
4133
4267
|
function getMeasureHost() {
|
|
4134
4268
|
if (__measureHost) return __measureHost;
|
|
@@ -4163,6 +4297,259 @@ ${imported}
|
|
|
4163
4297
|
host.removeChild(tmp);
|
|
4164
4298
|
return M;
|
|
4165
4299
|
}
|
|
4300
|
+
function hasBBoxAffectingTransform(el) {
|
|
4301
|
+
const cs = getComputedStyle(el);
|
|
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);
|
|
4309
|
+
}
|
|
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") {
|
|
4354
|
+
try {
|
|
4355
|
+
shrinkAutoSizeBoxes(state.element, state.clone, state.styleCache);
|
|
4356
|
+
} catch (e) {
|
|
4357
|
+
console.warn("[snapdom] shrink pass failed:", e);
|
|
4358
|
+
}
|
|
4359
|
+
}
|
|
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
|
+
});
|
|
4549
|
+
}
|
|
4550
|
+
function hasTFBBox(el) {
|
|
4551
|
+
return hasBBoxAffectingTransform(el);
|
|
4552
|
+
}
|
|
4166
4553
|
|
|
4167
4554
|
// src/core/context.js
|
|
4168
4555
|
function normalizeCachePolicy(v) {
|
|
@@ -4321,7 +4708,7 @@ ${imported}
|
|
|
4321
4708
|
}
|
|
4322
4709
|
function toCanvas(url, options) {
|
|
4323
4710
|
return __async(this, null, function* () {
|
|
4324
|
-
let { width: optW, height: optH, scale = 1, dpr = 1, meta = {} } = options;
|
|
4711
|
+
let { width: optW, height: optH, scale = 1, dpr = 1, meta = {}, backgroundColor } = options;
|
|
4325
4712
|
url = maybeConvertBoxShadowForSafari(url);
|
|
4326
4713
|
const img = new Image();
|
|
4327
4714
|
img.loading = "eager";
|
|
@@ -4360,6 +4747,12 @@ ${imported}
|
|
|
4360
4747
|
canvas.style.height = `${outH}px`;
|
|
4361
4748
|
const ctx = canvas.getContext("2d");
|
|
4362
4749
|
if (dpr !== 1) ctx.scale(dpr, dpr);
|
|
4750
|
+
if (backgroundColor) {
|
|
4751
|
+
ctx.save();
|
|
4752
|
+
ctx.fillStyle = backgroundColor;
|
|
4753
|
+
ctx.fillRect(0, 0, outW, outH);
|
|
4754
|
+
ctx.restore();
|
|
4755
|
+
}
|
|
4363
4756
|
ctx.drawImage(img, 0, 0, outW, outH);
|
|
4364
4757
|
return canvas;
|
|
4365
4758
|
});
|
|
@@ -4369,12 +4762,11 @@ ${imported}
|
|
|
4369
4762
|
function rasterize(url, options) {
|
|
4370
4763
|
return __async(this, null, function* () {
|
|
4371
4764
|
const canvas = yield toCanvas(url, options);
|
|
4372
|
-
const finalCanvas = options.backgroundColor ? createBackground(canvas, options.backgroundColor) : canvas;
|
|
4373
4765
|
const img = new Image();
|
|
4374
|
-
img.src =
|
|
4766
|
+
img.src = canvas.toDataURL(`image/${options.format}`, options.quality);
|
|
4375
4767
|
yield img.decode();
|
|
4376
|
-
img.style.width = `${
|
|
4377
|
-
img.style.height = `${
|
|
4768
|
+
img.style.width = `${canvas.width / options.dpr}px`;
|
|
4769
|
+
img.style.height = `${canvas.height / options.dpr}px`;
|
|
4378
4770
|
return img;
|
|
4379
4771
|
});
|
|
4380
4772
|
}
|
|
@@ -4438,13 +4830,8 @@ ${imported}
|
|
|
4438
4830
|
return new Blob([svgText], { type: "image/svg+xml" });
|
|
4439
4831
|
}
|
|
4440
4832
|
const canvas = yield toCanvas(url, options);
|
|
4441
|
-
const finalCanvas = options.backgroundColor ? createBackground(canvas, options.backgroundColor) : canvas;
|
|
4442
4833
|
return new Promise(
|
|
4443
|
-
(resolve) =>
|
|
4444
|
-
(blob) => resolve(blob),
|
|
4445
|
-
`image/${type}`,
|
|
4446
|
-
options.quality
|
|
4447
|
-
)
|
|
4834
|
+
(resolve) => canvas.toBlob((blob) => resolve(blob), `image/${type}`, options.quality)
|
|
4448
4835
|
);
|
|
4449
4836
|
});
|
|
4450
4837
|
}
|
|
@@ -4464,9 +4851,8 @@ ${imported}
|
|
|
4464
4851
|
return;
|
|
4465
4852
|
}
|
|
4466
4853
|
const canvas = yield toCanvas(url, options);
|
|
4467
|
-
const finalCanvas = options.backgroundColor ? createBackground(canvas, options.backgroundColor) : canvas;
|
|
4468
4854
|
const a = document.createElement("a");
|
|
4469
|
-
a.href =
|
|
4855
|
+
a.href = canvas.toDataURL(`image/${options.format}`, options.quality);
|
|
4470
4856
|
a.download = options.filename;
|
|
4471
4857
|
a.click();
|
|
4472
4858
|
});
|