@zumer/snapdom 1.9.6 → 1.9.8
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 +57 -9
- package/dist/snapdom.js +240 -139
- package/dist/snapdom.min.js +3 -3
- package/dist/snapdom.min.mjs +3 -3
- package/dist/snapdom.mjs +230 -137
- package/package.json +1 -1
- package/types/snapdom.d.ts +1 -0
package/dist/snapdom.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/*
|
|
3
3
|
* snapdom
|
|
4
|
-
* v.1.9.
|
|
4
|
+
* v.1.9.8
|
|
5
5
|
* Author Juan Martin Muda
|
|
6
6
|
* License MIT
|
|
7
7
|
**/
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
if (cache.defaultStyle.has(tagName)) {
|
|
131
131
|
return cache.defaultStyle.get(tagName);
|
|
132
132
|
}
|
|
133
|
-
const skipTags = /* @__PURE__ */ new Set(["script", "style", "meta", "link", "noscript", "template"]);
|
|
133
|
+
const skipTags = /* @__PURE__ */ new Set(["script", "style", "meta", "link", "noscript", "template", "defs", "symbol", "title", "metadata", "desc"]);
|
|
134
134
|
if (skipTags.has(tagName)) {
|
|
135
135
|
const empty = {};
|
|
136
136
|
cache.defaultStyle.set(tagName, empty);
|
|
@@ -160,10 +160,14 @@
|
|
|
160
160
|
cache.defaultStyle.set(tagName, defaults);
|
|
161
161
|
return defaults;
|
|
162
162
|
}
|
|
163
|
+
var IGNORED_PROPS = /* @__PURE__ */ new Set([
|
|
164
|
+
"-webkit-locale"
|
|
165
|
+
]);
|
|
163
166
|
function getStyleKey(snapshot, tagName, compress = false) {
|
|
164
167
|
const entries = [];
|
|
165
168
|
const defaultStyles = getDefaultStyleForTag(tagName);
|
|
166
169
|
for (let [prop, value] of Object.entries(snapshot)) {
|
|
170
|
+
if (IGNORED_PROPS.has(prop)) continue;
|
|
167
171
|
if (!compress) {
|
|
168
172
|
if (value) {
|
|
169
173
|
entries.push(`${prop}:${value}`);
|
|
@@ -213,6 +217,7 @@
|
|
|
213
217
|
const classMap = /* @__PURE__ */ new Map();
|
|
214
218
|
let counter = 1;
|
|
215
219
|
for (const key of keySet) {
|
|
220
|
+
if (!key.trim()) continue;
|
|
216
221
|
classMap.set(key, `c${counter++}`);
|
|
217
222
|
}
|
|
218
223
|
return classMap;
|
|
@@ -448,6 +453,7 @@
|
|
|
448
453
|
// src/modules/styles.js
|
|
449
454
|
function snapshotComputedStyleFull(style) {
|
|
450
455
|
const result = {};
|
|
456
|
+
const computedVisibility = style.getPropertyValue("visibility");
|
|
451
457
|
for (let i = 0; i < style.length; i++) {
|
|
452
458
|
const prop = style[i];
|
|
453
459
|
let val = style.getPropertyValue(prop);
|
|
@@ -456,6 +462,9 @@
|
|
|
456
462
|
}
|
|
457
463
|
result[prop] = val;
|
|
458
464
|
}
|
|
465
|
+
if (computedVisibility === "hidden") {
|
|
466
|
+
result.opacity = "0";
|
|
467
|
+
}
|
|
459
468
|
return result;
|
|
460
469
|
}
|
|
461
470
|
function inlineAllStyles(source, clone, compress) {
|
|
@@ -574,7 +583,6 @@
|
|
|
574
583
|
if (node.checked) clone.setAttribute("checked", "");
|
|
575
584
|
if (node.indeterminate) clone.indeterminate = node.indeterminate;
|
|
576
585
|
}
|
|
577
|
-
return clone;
|
|
578
586
|
}
|
|
579
587
|
if (node instanceof HTMLSelectElement) {
|
|
580
588
|
pendingSelectValue = node.value;
|
|
@@ -679,25 +687,38 @@
|
|
|
679
687
|
return __async(this, null, function* () {
|
|
680
688
|
fontFamily = fontFamily.replace(/^['"]+|['"]+$/g, "");
|
|
681
689
|
const dpr = window.devicePixelRatio || 1;
|
|
682
|
-
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
+
yield document.fonts.ready;
|
|
691
|
+
const span = document.createElement("span");
|
|
692
|
+
span.textContent = unicodeChar;
|
|
693
|
+
span.style.position = "absolute";
|
|
694
|
+
span.style.visibility = "hidden";
|
|
695
|
+
span.style.fontFamily = `"${fontFamily}"`;
|
|
696
|
+
span.style.fontWeight = fontWeight || "normal";
|
|
697
|
+
span.style.fontSize = `${fontSize}px`;
|
|
698
|
+
span.style.lineHeight = "1";
|
|
699
|
+
span.style.whiteSpace = "nowrap";
|
|
700
|
+
span.style.padding = "0";
|
|
701
|
+
span.style.margin = "0";
|
|
702
|
+
document.body.appendChild(span);
|
|
703
|
+
const rect = span.getBoundingClientRect();
|
|
704
|
+
const width = Math.ceil(rect.width);
|
|
705
|
+
const height = Math.ceil(rect.height);
|
|
706
|
+
document.body.removeChild(span);
|
|
690
707
|
const canvas = document.createElement("canvas");
|
|
691
|
-
canvas.width =
|
|
692
|
-
canvas.height =
|
|
708
|
+
canvas.width = width * dpr;
|
|
709
|
+
canvas.height = height * dpr;
|
|
693
710
|
const ctx = canvas.getContext("2d");
|
|
694
711
|
ctx.scale(dpr, dpr);
|
|
695
|
-
ctx.font =
|
|
712
|
+
ctx.font = fontWeight ? `${fontWeight} ${fontSize}px "${fontFamily}"` : `${fontSize}px "${fontFamily}"`;
|
|
696
713
|
ctx.textAlign = "left";
|
|
697
|
-
ctx.textBaseline = "
|
|
714
|
+
ctx.textBaseline = "top";
|
|
698
715
|
ctx.fillStyle = color;
|
|
699
|
-
ctx.fillText(unicodeChar, 0,
|
|
700
|
-
return
|
|
716
|
+
ctx.fillText(unicodeChar, 0, 0);
|
|
717
|
+
return {
|
|
718
|
+
dataUrl: canvas.toDataURL(),
|
|
719
|
+
width,
|
|
720
|
+
height
|
|
721
|
+
};
|
|
701
722
|
});
|
|
702
723
|
}
|
|
703
724
|
function isStylesheetLoaded(href) {
|
|
@@ -798,8 +819,8 @@
|
|
|
798
819
|
if (!src || isIconFont(family)) continue;
|
|
799
820
|
const urlRegex = /url\((["']?)([^"')]+)\1\)/g;
|
|
800
821
|
const localRegex = /local\((["']?)[^)]+?\1\)/g;
|
|
801
|
-
const hasURL =
|
|
802
|
-
const hasLocal =
|
|
822
|
+
const hasURL = !!src.match(urlRegex);
|
|
823
|
+
const hasLocal = !!src.match(localRegex);
|
|
803
824
|
if (!hasURL && hasLocal) {
|
|
804
825
|
finalCSS += `@font-face{font-family:${family};src:${src};font-style:${rule.style.getPropertyValue("font-style") || "normal"};font-weight:${rule.style.getPropertyValue("font-weight") || "normal"};}`;
|
|
805
826
|
continue;
|
|
@@ -885,19 +906,25 @@
|
|
|
885
906
|
}
|
|
886
907
|
|
|
887
908
|
// src/modules/pseudo.js
|
|
888
|
-
function inlinePseudoElements(source, clone,
|
|
909
|
+
function inlinePseudoElements(source, clone, options) {
|
|
889
910
|
return __async(this, null, function* () {
|
|
911
|
+
var _a;
|
|
890
912
|
if (!(source instanceof Element) || !(clone instanceof Element)) return;
|
|
891
913
|
for (const pseudo of ["::before", "::after", "::first-letter"]) {
|
|
892
914
|
try {
|
|
893
915
|
const style = getStyle(source, pseudo);
|
|
894
916
|
if (!style || typeof style[Symbol.iterator] !== "function") continue;
|
|
917
|
+
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";
|
|
918
|
+
if (isEmptyPseudo) continue;
|
|
895
919
|
if (pseudo === "::first-letter") {
|
|
896
920
|
const normal = getComputedStyle(source);
|
|
897
921
|
const isMeaningful = style.color !== normal.color || style.fontSize !== normal.fontSize || style.fontWeight !== normal.fontWeight;
|
|
898
922
|
if (!isMeaningful) continue;
|
|
899
923
|
const textNode = Array.from(clone.childNodes).find(
|
|
900
|
-
(n) =>
|
|
924
|
+
(n) => {
|
|
925
|
+
var _a2;
|
|
926
|
+
return n.nodeType === Node.TEXT_NODE && ((_a2 = n.textContent) == null ? void 0 : _a2.trim().length) > 0;
|
|
927
|
+
}
|
|
901
928
|
);
|
|
902
929
|
if (!textNode) continue;
|
|
903
930
|
const text = textNode.textContent;
|
|
@@ -908,74 +935,83 @@
|
|
|
908
935
|
const span = document.createElement("span");
|
|
909
936
|
span.textContent = first;
|
|
910
937
|
span.dataset.snapdomPseudo = "::first-letter";
|
|
911
|
-
const
|
|
912
|
-
const
|
|
913
|
-
cache.preStyleMap.set(span,
|
|
938
|
+
const snapshot2 = snapshotComputedStyle(style);
|
|
939
|
+
const key2 = getStyleKey(snapshot2, "span", options);
|
|
940
|
+
cache.preStyleMap.set(span, key2);
|
|
914
941
|
const restNode = document.createTextNode(rest);
|
|
915
942
|
clone.replaceChild(restNode, textNode);
|
|
916
943
|
clone.insertBefore(span, restNode);
|
|
917
944
|
continue;
|
|
918
945
|
}
|
|
919
|
-
const content = style.
|
|
920
|
-
const
|
|
921
|
-
const
|
|
922
|
-
const
|
|
946
|
+
const content = style.content;
|
|
947
|
+
const cleanContent = /counter\s*\(|counters\s*\(/.test(content) ? "- " : parseContent(content);
|
|
948
|
+
const bg = style.backgroundImage;
|
|
949
|
+
const bgColor = style.backgroundColor;
|
|
950
|
+
const fontFamily = style.fontFamily;
|
|
951
|
+
const fontSize = parseInt(style.fontSize) || 32;
|
|
952
|
+
const fontWeight = parseInt(style.fontWeight) || false;
|
|
953
|
+
const color = style.color || "#000";
|
|
954
|
+
const display = style.display;
|
|
955
|
+
const width = parseFloat(style.width);
|
|
956
|
+
const height = parseFloat(style.height);
|
|
957
|
+
const borderStyle = style.borderStyle;
|
|
958
|
+
const borderWidth = parseFloat(style.borderWidth);
|
|
959
|
+
const transform = style.transform;
|
|
960
|
+
const isIconFont2 = isIconFont(fontFamily);
|
|
961
|
+
const hasExplicitContent = content !== "none" && cleanContent !== "";
|
|
923
962
|
const hasBg = bg && bg !== "none";
|
|
924
963
|
const hasBgColor = bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)";
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
pseudoEl.appendChild(imgEl);
|
|
947
|
-
} else if (cleanContent.startsWith("url(")) {
|
|
948
|
-
const rawUrl = extractURL(cleanContent);
|
|
949
|
-
if (rawUrl && rawUrl.trim() !== "") {
|
|
950
|
-
try {
|
|
951
|
-
const imgEl = document.createElement("img");
|
|
952
|
-
const dataUrl = yield fetchImage(safeEncodeURI(rawUrl, { useProxy }));
|
|
953
|
-
imgEl.src = dataUrl;
|
|
954
|
-
imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
|
|
955
|
-
pseudoEl.appendChild(imgEl);
|
|
956
|
-
} catch (e) {
|
|
957
|
-
console.error(`[snapdom] Error in pseudo ${pseudo} for`, source, e);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
} else if (!isIconFont2 && cleanContent && cleanContent !== "none") {
|
|
961
|
-
pseudoEl.textContent = cleanContent;
|
|
962
|
-
}
|
|
963
|
-
if (hasBg) {
|
|
964
|
+
const hasBox = display !== "inline" && (width > 0 || height > 0);
|
|
965
|
+
const hasBorder = borderStyle && borderStyle !== "none" && borderWidth > 0;
|
|
966
|
+
const hasTransform = transform && transform !== "none";
|
|
967
|
+
const shouldRender = hasExplicitContent || hasBg || hasBgColor || hasBox || hasBorder || hasTransform;
|
|
968
|
+
if (!shouldRender) continue;
|
|
969
|
+
const pseudoEl = document.createElement("span");
|
|
970
|
+
pseudoEl.dataset.snapdomPseudo = pseudo;
|
|
971
|
+
pseudoEl.style.verticalAlign = "middle";
|
|
972
|
+
const snapshot = snapshotComputedStyle(style);
|
|
973
|
+
const key = getStyleKey(snapshot, "span", options);
|
|
974
|
+
cache.preStyleMap.set(pseudoEl, key);
|
|
975
|
+
if (isIconFont2 && cleanContent.length === 1) {
|
|
976
|
+
const { dataUrl, width: width2, height: height2 } = yield iconToImage(cleanContent, fontFamily, fontWeight, fontSize, color);
|
|
977
|
+
const imgEl = document.createElement("img");
|
|
978
|
+
imgEl.src = dataUrl;
|
|
979
|
+
imgEl.style = `height:${fontSize}px;width:${width2 / height2 * fontSize}px;object-fit:contain;`;
|
|
980
|
+
pseudoEl.appendChild(imgEl);
|
|
981
|
+
clone.dataset.snapdomHasIcon = "true";
|
|
982
|
+
} else if (cleanContent.startsWith("url(")) {
|
|
983
|
+
const rawUrl = extractURL(cleanContent);
|
|
984
|
+
if (rawUrl == null ? void 0 : rawUrl.trim()) {
|
|
964
985
|
try {
|
|
965
|
-
const
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
pseudoEl.
|
|
986
|
+
const imgEl = document.createElement("img");
|
|
987
|
+
const dataUrl = yield fetchImage(safeEncodeURI(rawUrl), options);
|
|
988
|
+
imgEl.src = dataUrl;
|
|
989
|
+
imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
|
|
990
|
+
pseudoEl.appendChild(imgEl);
|
|
970
991
|
} catch (e) {
|
|
971
|
-
console.
|
|
992
|
+
console.error(`[snapdom] Error in pseudo ${pseudo} for`, source, e);
|
|
972
993
|
}
|
|
973
994
|
}
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
995
|
+
} else if (!isIconFont2 && hasExplicitContent) {
|
|
996
|
+
pseudoEl.textContent = cleanContent;
|
|
997
|
+
}
|
|
998
|
+
if (hasBg) {
|
|
999
|
+
try {
|
|
1000
|
+
const bgSplits = splitBackgroundImage(bg);
|
|
1001
|
+
const newBgParts = yield Promise.all(bgSplits.map(inlineSingleBackgroundEntry));
|
|
1002
|
+
pseudoEl.style.backgroundImage = newBgParts.join(", ");
|
|
1003
|
+
} catch (e) {
|
|
1004
|
+
console.warn(`[snapdom] Failed to inline background-image for ${pseudo}`, e);
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
|
|
1008
|
+
const hasContent2 = pseudoEl.childNodes.length > 0 || ((_a = pseudoEl.textContent) == null ? void 0 : _a.trim()) !== "";
|
|
1009
|
+
const hasVisibleBox = hasContent2 || hasBg || hasBgColor || hasBox || hasBorder || hasTransform;
|
|
1010
|
+
if (!hasVisibleBox) continue;
|
|
1011
|
+
if (pseudo === "::before") {
|
|
1012
|
+
clone.insertBefore(pseudoEl, clone.firstChild);
|
|
1013
|
+
} else {
|
|
1014
|
+
clone.appendChild(pseudoEl);
|
|
979
1015
|
}
|
|
980
1016
|
} catch (e) {
|
|
981
1017
|
console.warn(`[snapdom] Failed to capture ${pseudo} for`, source, e);
|
|
@@ -984,53 +1020,73 @@
|
|
|
984
1020
|
const sChildren = Array.from(source.children);
|
|
985
1021
|
const cChildren = Array.from(clone.children).filter((child) => !child.dataset.snapdomPseudo);
|
|
986
1022
|
for (let i = 0; i < Math.min(sChildren.length, cChildren.length); i++) {
|
|
987
|
-
yield inlinePseudoElements(
|
|
988
|
-
sChildren[i],
|
|
989
|
-
cChildren[i],
|
|
990
|
-
compress,
|
|
991
|
-
embedFonts,
|
|
992
|
-
useProxy
|
|
993
|
-
);
|
|
1023
|
+
yield inlinePseudoElements(sChildren[i], cChildren[i], options);
|
|
994
1024
|
}
|
|
995
1025
|
});
|
|
996
1026
|
}
|
|
997
1027
|
|
|
998
1028
|
// src/modules/svgDefs.js
|
|
999
|
-
function
|
|
1000
|
-
if (!
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1029
|
+
function inlineExternalDefsAndSymbols(rootElement) {
|
|
1030
|
+
if (!rootElement) return;
|
|
1031
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
1032
|
+
rootElement.querySelectorAll("use").forEach((use) => {
|
|
1033
|
+
const href = use.getAttribute("xlink:href") || use.getAttribute("href");
|
|
1034
|
+
if (href && href.startsWith("#")) {
|
|
1035
|
+
usedIds.add(href.slice(1));
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
if (!usedIds.size) return;
|
|
1039
|
+
const allGlobal = Array.from(document.querySelectorAll("svg > symbol, svg > defs"));
|
|
1040
|
+
const globalSymbols = allGlobal.filter((el) => el.tagName.toLowerCase() === "symbol");
|
|
1041
|
+
const globalDefs = allGlobal.filter((el) => el.tagName.toLowerCase() === "defs");
|
|
1042
|
+
let container = rootElement.querySelector("svg.inline-defs-container");
|
|
1043
|
+
if (!container) {
|
|
1044
|
+
container = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1045
|
+
container.setAttribute("aria-hidden", "true");
|
|
1046
|
+
container.setAttribute("style", "position: absolute; width: 0; height: 0; overflow: hidden;");
|
|
1047
|
+
container.classList.add("inline-defs-container");
|
|
1048
|
+
rootElement.insertBefore(container, rootElement.firstChild);
|
|
1049
|
+
}
|
|
1050
|
+
const existingIds = /* @__PURE__ */ new Set();
|
|
1051
|
+
rootElement.querySelectorAll("symbol[id], defs > *[id]").forEach((el) => {
|
|
1052
|
+
existingIds.add(el.id);
|
|
1053
|
+
});
|
|
1054
|
+
usedIds.forEach((id) => {
|
|
1055
|
+
if (existingIds.has(id)) return;
|
|
1056
|
+
const symbol = globalSymbols.find((sym) => sym.id === id);
|
|
1057
|
+
if (symbol) {
|
|
1058
|
+
container.appendChild(symbol.cloneNode(true));
|
|
1059
|
+
existingIds.add(id);
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
for (const defs of globalDefs) {
|
|
1063
|
+
const defEl = defs.querySelector(`#${CSS.escape(id)}`);
|
|
1064
|
+
if (defEl) {
|
|
1065
|
+
let defsContainer = container.querySelector("defs");
|
|
1066
|
+
if (!defsContainer) {
|
|
1067
|
+
defsContainer = document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
1068
|
+
container.appendChild(defsContainer);
|
|
1019
1069
|
}
|
|
1070
|
+
defsContainer.appendChild(defEl.cloneNode(true));
|
|
1071
|
+
existingIds.add(id);
|
|
1072
|
+
break;
|
|
1020
1073
|
}
|
|
1021
1074
|
}
|
|
1022
|
-
if (defs.childNodes.length) {
|
|
1023
|
-
svg.insertBefore(defs, svg.firstChild);
|
|
1024
|
-
}
|
|
1025
1075
|
});
|
|
1026
1076
|
}
|
|
1027
1077
|
|
|
1028
1078
|
// src/core/prepare.js
|
|
1029
1079
|
function prepareClone(_0) {
|
|
1030
1080
|
return __async(this, arguments, function* (element, compress = false, embedFonts = false, options = {}) {
|
|
1031
|
-
var _a;
|
|
1081
|
+
var _a, _b;
|
|
1032
1082
|
let clone;
|
|
1033
1083
|
let classCSS = "";
|
|
1084
|
+
stabilizeLayout(element);
|
|
1085
|
+
try {
|
|
1086
|
+
inlineExternalDefsAndSymbols(element);
|
|
1087
|
+
} catch (e) {
|
|
1088
|
+
console.warn("inlineExternal defs or symbol failed:", e);
|
|
1089
|
+
}
|
|
1034
1090
|
try {
|
|
1035
1091
|
clone = deepClone(element, compress, options, element);
|
|
1036
1092
|
} catch (e) {
|
|
@@ -1042,21 +1098,24 @@
|
|
|
1042
1098
|
} catch (e) {
|
|
1043
1099
|
console.warn("inlinePseudoElements failed:", e);
|
|
1044
1100
|
}
|
|
1045
|
-
try {
|
|
1046
|
-
inlineExternalDef(clone);
|
|
1047
|
-
} catch (e) {
|
|
1048
|
-
console.warn("inlineExternalDef failed:", e);
|
|
1049
|
-
}
|
|
1050
1101
|
if (compress) {
|
|
1051
1102
|
const keyToClass = generateCSSClasses();
|
|
1052
1103
|
classCSS = Array.from(keyToClass.entries()).map(([key, className]) => `.${className}{${key}}`).join("");
|
|
1053
1104
|
for (const [node, key] of cache.preStyleMap.entries()) {
|
|
1054
1105
|
if (node.tagName === "STYLE") continue;
|
|
1106
|
+
if (node.getRootNode && node.getRootNode() instanceof ShadowRoot) {
|
|
1107
|
+
node.setAttribute("style", key.replace(/;/g, "; "));
|
|
1108
|
+
continue;
|
|
1109
|
+
}
|
|
1055
1110
|
const className = keyToClass.get(key);
|
|
1056
1111
|
if (className) node.classList.add(className);
|
|
1057
1112
|
const bgImage = (_a = node.style) == null ? void 0 : _a.backgroundImage;
|
|
1058
|
-
node.
|
|
1113
|
+
const hasIcon = (_b = node.dataset) == null ? void 0 : _b.snapdomHasIcon;
|
|
1059
1114
|
if (bgImage && bgImage !== "none") node.style.backgroundImage = bgImage;
|
|
1115
|
+
if (hasIcon) {
|
|
1116
|
+
node.style.verticalAlign = "middle";
|
|
1117
|
+
node.style.display = "inline";
|
|
1118
|
+
}
|
|
1060
1119
|
}
|
|
1061
1120
|
} else {
|
|
1062
1121
|
for (const [node, key] of cache.preStyleMap.entries()) {
|
|
@@ -1107,6 +1166,18 @@
|
|
|
1107
1166
|
return { clone, classCSS };
|
|
1108
1167
|
});
|
|
1109
1168
|
}
|
|
1169
|
+
function stabilizeLayout(element) {
|
|
1170
|
+
const style = getComputedStyle(element);
|
|
1171
|
+
const outlineStyle = style.outlineStyle;
|
|
1172
|
+
const outlineWidth = style.outlineWidth;
|
|
1173
|
+
const borderStyle = style.borderStyle;
|
|
1174
|
+
const borderWidth = style.borderWidth;
|
|
1175
|
+
const outlineVisible = outlineStyle !== "none" && parseFloat(outlineWidth) > 0;
|
|
1176
|
+
const borderAbsent = borderStyle === "none" || parseFloat(borderWidth) === 0;
|
|
1177
|
+
if (outlineVisible && borderAbsent) {
|
|
1178
|
+
element.style.border = `${outlineWidth} solid transparent`;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1110
1181
|
|
|
1111
1182
|
// src/modules/images.js
|
|
1112
1183
|
function inlineImages(_0) {
|
|
@@ -1145,13 +1216,27 @@
|
|
|
1145
1216
|
"mask-source",
|
|
1146
1217
|
"mask-box-image-source",
|
|
1147
1218
|
"mask-border-source",
|
|
1148
|
-
"-webkit-mask-box-image-source"
|
|
1219
|
+
"-webkit-mask-box-image-source",
|
|
1220
|
+
"border-image",
|
|
1221
|
+
"border-image-source",
|
|
1222
|
+
"border-image-slice",
|
|
1223
|
+
"border-image-width",
|
|
1224
|
+
"border-image-outset",
|
|
1225
|
+
"border-image-repeat"
|
|
1149
1226
|
];
|
|
1150
1227
|
while (queue.length) {
|
|
1151
1228
|
const [srcNode, cloneNode] = queue.shift();
|
|
1152
1229
|
const style = cache.preStyle.get(srcNode) || getStyle(srcNode);
|
|
1153
1230
|
if (!cache.preStyle.has(srcNode)) cache.preStyle.set(srcNode, style);
|
|
1231
|
+
const hasBorderImage = (() => {
|
|
1232
|
+
const bi = style.getPropertyValue("border-image");
|
|
1233
|
+
const bis = style.getPropertyValue("border-image-source");
|
|
1234
|
+
return bi && bi !== "none" || bis && bis !== "none";
|
|
1235
|
+
})();
|
|
1154
1236
|
for (const prop of imageProps) {
|
|
1237
|
+
if (["border-image-slice", "border-image-width", "border-image-outset", "border-image-repeat"].includes(prop) && !hasBorderImage) {
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1155
1240
|
const val = style.getPropertyValue(prop);
|
|
1156
1241
|
if (!val || val === "none") continue;
|
|
1157
1242
|
const splits = splitBackgroundImage(val);
|
|
@@ -1255,8 +1340,6 @@
|
|
|
1255
1340
|
const existingTransform = clone.style.transform || "";
|
|
1256
1341
|
const scaleTransform = `scale(${scaleX}, ${scaleY})`;
|
|
1257
1342
|
clone.style.transform = `${scaleTransform} ${existingTransform}`.trim();
|
|
1258
|
-
} else if (hasScale && isSafari()) {
|
|
1259
|
-
clone.style.scale = `${scale}`;
|
|
1260
1343
|
}
|
|
1261
1344
|
const svgNS = "http://www.w3.org/2000/svg";
|
|
1262
1345
|
const fo = document.createElementNS(svgNS, "foreignObject");
|
|
@@ -1282,17 +1365,14 @@
|
|
|
1282
1365
|
}
|
|
1283
1366
|
|
|
1284
1367
|
// src/api/snapdom.js
|
|
1285
|
-
function toImg(_0
|
|
1286
|
-
return __async(this, arguments, function* (url, {
|
|
1368
|
+
function toImg(_0) {
|
|
1369
|
+
return __async(this, arguments, function* (url, { scale = 1 } = {}) {
|
|
1287
1370
|
const img = new Image();
|
|
1288
1371
|
img.src = url;
|
|
1289
1372
|
yield img.decode();
|
|
1290
|
-
if (
|
|
1291
|
-
img.width = img.
|
|
1292
|
-
img.height = img.
|
|
1293
|
-
} else {
|
|
1294
|
-
img.width = img.width / scale;
|
|
1295
|
-
img.height = img.height / scale;
|
|
1373
|
+
if (scale !== 1) {
|
|
1374
|
+
img.style.width = `${img.naturalWidth * scale}px`;
|
|
1375
|
+
img.style.height = `${img.naturalHeight * scale}px`;
|
|
1296
1376
|
}
|
|
1297
1377
|
return img;
|
|
1298
1378
|
});
|
|
@@ -1301,17 +1381,34 @@
|
|
|
1301
1381
|
return __async(this, arguments, function* (url, { dpr = 1, scale = 1 } = {}) {
|
|
1302
1382
|
const img = new Image();
|
|
1303
1383
|
img.src = url;
|
|
1384
|
+
img.crossOrigin = "anonymous";
|
|
1385
|
+
img.loading = "eager";
|
|
1386
|
+
img.decoding = "sync";
|
|
1387
|
+
const isSafariBrowser = isSafari();
|
|
1388
|
+
let appended = false;
|
|
1389
|
+
if (isSafariBrowser) {
|
|
1390
|
+
document.body.appendChild(img);
|
|
1391
|
+
appended = true;
|
|
1392
|
+
}
|
|
1304
1393
|
yield img.decode();
|
|
1394
|
+
if (isSafariBrowser) {
|
|
1395
|
+
yield new Promise((resolve) => setTimeout(resolve, 100));
|
|
1396
|
+
}
|
|
1397
|
+
if (img.width === 0 || img.height === 0) {
|
|
1398
|
+
if (appended) img.remove();
|
|
1399
|
+
throw new Error("Image failed to load or has no dimensions");
|
|
1400
|
+
}
|
|
1401
|
+
const width = img.naturalWidth * scale;
|
|
1402
|
+
const height = img.naturalHeight * scale;
|
|
1305
1403
|
const canvas = document.createElement("canvas");
|
|
1306
|
-
const width = img.width * scale;
|
|
1307
|
-
const height = img.height * scale;
|
|
1308
1404
|
canvas.width = Math.ceil(width * dpr);
|
|
1309
1405
|
canvas.height = Math.ceil(height * dpr);
|
|
1406
|
+
canvas.style.width = `${width}px`;
|
|
1407
|
+
canvas.style.height = `${height}px`;
|
|
1310
1408
|
const ctx = canvas.getContext("2d");
|
|
1311
1409
|
ctx.scale(dpr, dpr);
|
|
1312
1410
|
ctx.drawImage(img, 0, 0, width, height);
|
|
1313
|
-
|
|
1314
|
-
canvas.style.height = `${height}px`;
|
|
1411
|
+
if (appended) img.remove();
|
|
1315
1412
|
return canvas;
|
|
1316
1413
|
});
|
|
1317
1414
|
}
|
|
@@ -1366,7 +1463,7 @@
|
|
|
1366
1463
|
});
|
|
1367
1464
|
}
|
|
1368
1465
|
function download(_0) {
|
|
1369
|
-
return __async(this, arguments, function* (url, { dpr = 1, scale = 1, backgroundColor
|
|
1466
|
+
return __async(this, arguments, function* (url, { dpr = 1, scale = 1, backgroundColor, format = "png", filename = "snapDOM" } = {}) {
|
|
1370
1467
|
if (format === "svg") {
|
|
1371
1468
|
const blob = yield toBlob(url);
|
|
1372
1469
|
const objectURL = URL.createObjectURL(blob);
|
|
@@ -1404,20 +1501,24 @@
|
|
|
1404
1501
|
});
|
|
1405
1502
|
}
|
|
1406
1503
|
snapdom.capture = (_0, ..._1) => __async(null, [_0, ..._1], function* (el, options = {}) {
|
|
1504
|
+
var _a;
|
|
1407
1505
|
const url = yield captureDOM(el, options);
|
|
1408
|
-
const dpr = window.devicePixelRatio || 1;
|
|
1506
|
+
const dpr = (_a = options.dpr) != null ? _a : window.devicePixelRatio || 1;
|
|
1409
1507
|
const scale = options.scale || 1;
|
|
1410
1508
|
return {
|
|
1411
1509
|
url,
|
|
1412
1510
|
options,
|
|
1413
1511
|
toRaw: () => url,
|
|
1414
|
-
toImg: () => toImg(url, { dpr, scale }),
|
|
1415
|
-
toCanvas: () => toCanvas(url, { dpr, scale }),
|
|
1416
|
-
toBlob: (
|
|
1417
|
-
toPng: (
|
|
1418
|
-
toJpg: (
|
|
1419
|
-
toWebp: (
|
|
1420
|
-
download: (
|
|
1512
|
+
toImg: (opts = {}) => toImg(url, __spreadValues({ dpr, scale }, opts)),
|
|
1513
|
+
toCanvas: (opts = {}) => toCanvas(url, __spreadValues({ dpr, scale }, opts)),
|
|
1514
|
+
toBlob: (opts = {}) => toBlob(url, __spreadValues({ dpr, scale }, opts)),
|
|
1515
|
+
toPng: (opts = {}) => toRasterImg(url, __spreadValues({ dpr, scale }, opts), "png"),
|
|
1516
|
+
toJpg: (opts = {}) => toRasterImg(url, __spreadValues({ dpr, scale }, opts), "jpeg"),
|
|
1517
|
+
toWebp: (opts = {}) => toRasterImg(url, __spreadValues({ dpr, scale }, opts), "webp"),
|
|
1518
|
+
download: (_b = {}) => {
|
|
1519
|
+
var _c = _b, { format = "png", filename = "snapDOM", backgroundColor } = _c, opts = __objRest(_c, ["format", "filename", "backgroundColor"]);
|
|
1520
|
+
return download(url, __spreadValues({ dpr, scale, format, filename, backgroundColor }, opts));
|
|
1521
|
+
}
|
|
1421
1522
|
};
|
|
1422
1523
|
});
|
|
1423
1524
|
snapdom.toRaw = (el, options) => __async(null, null, function* () {
|