@zumer/snapdom 1.9.6-dev.2 → 1.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/snapdom.js CHANGED
@@ -1,14 +1,13 @@
1
1
 
2
2
  /*
3
3
  * snapdom
4
- * v.1.9.6-dev.2
4
+ * v.1.9.7
5
5
  * Author Juan Martin Muda
6
6
  * License MIT
7
7
  **/
8
8
 
9
9
  (() => {
10
10
  var __defProp = Object.defineProperty;
11
- var __getOwnPropNames = Object.getOwnPropertyNames;
12
11
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
13
12
  var __hasOwnProp = Object.prototype.hasOwnProperty;
14
13
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -36,12 +35,6 @@
36
35
  }
37
36
  return target;
38
37
  };
39
- var __esm = (fn, res) => function __init() {
40
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
41
- };
42
- var __commonJS = (cb, mod) => function __require() {
43
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
44
- };
45
38
  var __async = (__this, __arguments, generator) => {
46
39
  return new Promise((resolve, reject) => {
47
40
  var fulfilled = (value) => {
@@ -64,6 +57,21 @@
64
57
  };
65
58
 
66
59
  // src/core/cache.js
60
+ var cache = {
61
+ image: /* @__PURE__ */ new Map(),
62
+ background: /* @__PURE__ */ new Map(),
63
+ resource: /* @__PURE__ */ new Map(),
64
+ defaultStyle: /* @__PURE__ */ new Map(),
65
+ baseStyle: /* @__PURE__ */ new Map(),
66
+ computedStyle: /* @__PURE__ */ new WeakMap(),
67
+ font: /* @__PURE__ */ new Set(),
68
+ snapshot: /* @__PURE__ */ new WeakMap(),
69
+ snapshotKey: /* @__PURE__ */ new Map(),
70
+ preStyleMap: /* @__PURE__ */ new Map(),
71
+ preStyle: /* @__PURE__ */ new WeakMap(),
72
+ preNodeMap: /* @__PURE__ */ new Map(),
73
+ reset: resetCache
74
+ };
67
75
  function resetCache() {
68
76
  cache.computedStyle = /* @__PURE__ */ new WeakMap();
69
77
  cache.snapshot = /* @__PURE__ */ new WeakMap();
@@ -72,28 +80,47 @@
72
80
  cache.preStyle = /* @__PURE__ */ new WeakMap();
73
81
  cache.preNodeMap.clear();
74
82
  }
75
- var cache;
76
- var init_cache = __esm({
77
- "src/core/cache.js"() {
78
- cache = {
79
- image: /* @__PURE__ */ new Map(),
80
- background: /* @__PURE__ */ new Map(),
81
- resource: /* @__PURE__ */ new Map(),
82
- defaultStyle: /* @__PURE__ */ new Map(),
83
- baseStyle: /* @__PURE__ */ new Map(),
84
- computedStyle: /* @__PURE__ */ new WeakMap(),
85
- font: /* @__PURE__ */ new Set(),
86
- snapshot: /* @__PURE__ */ new WeakMap(),
87
- snapshotKey: /* @__PURE__ */ new Map(),
88
- preStyleMap: /* @__PURE__ */ new Map(),
89
- preStyle: /* @__PURE__ */ new WeakMap(),
90
- preNodeMap: /* @__PURE__ */ new Map(),
91
- reset: resetCache
92
- };
93
- }
94
- });
95
83
 
96
84
  // src/utils/cssTools.js
85
+ var commonTags = [
86
+ "div",
87
+ "span",
88
+ "p",
89
+ "a",
90
+ "img",
91
+ "ul",
92
+ "li",
93
+ "button",
94
+ "input",
95
+ "select",
96
+ "textarea",
97
+ "label",
98
+ "section",
99
+ "article",
100
+ "header",
101
+ "footer",
102
+ "nav",
103
+ "main",
104
+ "aside",
105
+ "h1",
106
+ "h2",
107
+ "h3",
108
+ "h4",
109
+ "h5",
110
+ "h6",
111
+ "svg",
112
+ "path",
113
+ "circle",
114
+ "rect",
115
+ "line",
116
+ "g",
117
+ "table",
118
+ "thead",
119
+ "tbody",
120
+ "tr",
121
+ "td",
122
+ "th"
123
+ ];
97
124
  function precacheCommonTags() {
98
125
  for (let tag of commonTags) {
99
126
  getDefaultStyleForTag(tag);
@@ -190,51 +217,6 @@
190
217
  }
191
218
  return classMap;
192
219
  }
193
- var commonTags;
194
- var init_cssTools = __esm({
195
- "src/utils/cssTools.js"() {
196
- init_cache();
197
- commonTags = [
198
- "div",
199
- "span",
200
- "p",
201
- "a",
202
- "img",
203
- "ul",
204
- "li",
205
- "button",
206
- "input",
207
- "select",
208
- "textarea",
209
- "label",
210
- "section",
211
- "article",
212
- "header",
213
- "footer",
214
- "nav",
215
- "main",
216
- "aside",
217
- "h1",
218
- "h2",
219
- "h3",
220
- "h4",
221
- "h5",
222
- "h6",
223
- "svg",
224
- "path",
225
- "circle",
226
- "rect",
227
- "line",
228
- "g",
229
- "table",
230
- "thead",
231
- "tbody",
232
- "tr",
233
- "td",
234
- "th"
235
- ];
236
- }
237
- });
238
220
 
239
221
  // src/utils/helpers.js
240
222
  function inlineSingleBackgroundEntry(_0) {
@@ -292,13 +274,10 @@
292
274
  return clean;
293
275
  }
294
276
  function extractURL(value) {
295
- const urlStart = value.indexOf("url(");
296
- if (urlStart === -1) return null;
297
- let url = value.slice(urlStart + 4).trim();
298
- if (url.endsWith(")")) url = url.slice(0, -1).trim();
299
- if (url.startsWith('"') && url.endsWith('"') || url.startsWith("'") && url.endsWith("'")) {
300
- url = url.slice(1, -1);
301
- }
277
+ const match = value.match(/url\((['"]?)(.*?)(\1)\)/);
278
+ if (!match) return null;
279
+ const url = match[2].trim();
280
+ if (url.startsWith("#")) return null;
302
281
  return url;
303
282
  }
304
283
  function fetchImage(src, { timeout = 3e3, useProxy = "" } = {}) {
@@ -336,20 +315,16 @@
336
315
  try {
337
316
  return yield fetchBlobAsDataURL(proxied);
338
317
  } catch (e2) {
339
- console.error(`[SnapDOM - fetchImage] Proxy fallback failed for: ${url}`);
340
- throw new Error("CORS restrictions prevented image capture (even via proxy)");
318
+ throw new Error("[SnapDOM - fetchImage] CORS restrictions prevented image capture (even via proxy)");
341
319
  }
342
320
  } else {
343
- console.error(`[SnapDOM - fetchImage] No valid proxy URL provided for fallback: ${url}`);
344
- throw new Error("Fetch fallback failed and no proxy provided");
321
+ throw new Error("[SnapDOM - fetchImage] Fetch fallback failed and no proxy provided");
345
322
  }
346
323
  }
347
324
  });
348
325
  }
349
326
  const crossOriginValue = getCrossOriginMode(src);
350
- console.log(`[SnapDOM - fetchImage] Start loading image: ${src} with crossOrigin=${crossOriginValue}`);
351
327
  if (cache.image.has(src)) {
352
- console.log(`[SnapDOM - fetchImage] Cache hit for: ${src}`);
353
328
  return Promise.resolve(cache.image.get(src));
354
329
  }
355
330
  const isDataURI = src.startsWith("data:image/");
@@ -376,8 +351,7 @@
376
351
  }
377
352
  return new Promise((resolve, reject) => {
378
353
  const timeoutId = setTimeout(() => {
379
- console.log(`[SnapDOM - fetchImage] Timeout after ${timeout}ms for image: ${src}`);
380
- reject(new Error("Image load timed out"));
354
+ reject(new Error("[SnapDOM - fetchImage] Image load timed out"));
381
355
  }, timeout);
382
356
  const image = new Image();
383
357
  image.crossOrigin = crossOriginValue;
@@ -470,11 +444,6 @@
470
444
  parts.push(bg.slice(lastIndex).trim());
471
445
  return parts;
472
446
  }
473
- var init_helpers = __esm({
474
- "src/utils/helpers.js"() {
475
- init_cache();
476
- }
477
- });
478
447
 
479
448
  // src/modules/styles.js
480
449
  function snapshotComputedStyleFull(style) {
@@ -511,177 +480,177 @@
511
480
  cache.snapshotKey.set(hash, key);
512
481
  cache.preStyleMap.set(clone, key);
513
482
  }
514
- var init_styles = __esm({
515
- "src/modules/styles.js"() {
516
- init_cssTools();
517
- init_helpers();
518
- init_cache();
519
- }
520
- });
521
483
 
522
484
  // src/core/clone.js
523
- function isSlotElement(node) {
524
- return node.nodeType === Node.ELEMENT_NODE && node.tagName === "SLOT";
525
- }
526
485
  function deepClone(node, compress, options = {}, originalRoot) {
527
486
  var _a, _b;
528
- if (!node) {
529
- throw new Error("Invalid node: node is null or undefined");
487
+ if (!node) throw new Error("Invalid node");
488
+ const clonedAssignedNodes = /* @__PURE__ */ new Set();
489
+ let pendingSelectValue = null;
490
+ if (node.nodeType === Node.TEXT_NODE) {
491
+ return node.cloneNode(true);
530
492
  }
531
- try {
532
- if (node.nodeType === Node.TEXT_NODE) {
533
- return node.cloneNode(true);
534
- }
535
- if (node.nodeType !== Node.ELEMENT_NODE) {
536
- return node.cloneNode(true);
537
- }
538
- if (node.getAttribute("data-capture") === "exclude") {
539
- const spacer = document.createElement("div");
540
- const rect = node.getBoundingClientRect();
541
- spacer.style.cssText = `display: inline-block; width: ${rect.width}px; height: ${rect.height}px; visibility: hidden;`;
542
- return spacer;
543
- }
544
- if (options.exclude && Array.isArray(options.exclude)) {
545
- for (const selector of options.exclude) {
546
- try {
547
- if ((_a = node.matches) == null ? void 0 : _a.call(node, selector)) {
548
- const spacer = document.createElement("div");
549
- const rect = node.getBoundingClientRect();
550
- spacer.style.cssText = `display: inline-block; width: ${rect.width}px; height: ${rect.height}px; visibility: hidden;`;
551
- return spacer;
552
- }
553
- } catch (err) {
554
- console.warn(`Invalid selector in exclude option: ${selector}`, err);
555
- }
556
- }
557
- }
558
- if (typeof options.filter === "function") {
493
+ if (node.nodeType !== Node.ELEMENT_NODE) {
494
+ return node.cloneNode(true);
495
+ }
496
+ if (node.getAttribute("data-capture") === "exclude") {
497
+ const spacer = document.createElement("div");
498
+ const rect = node.getBoundingClientRect();
499
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
500
+ return spacer;
501
+ }
502
+ if (options.exclude && Array.isArray(options.exclude)) {
503
+ for (const selector of options.exclude) {
559
504
  try {
560
- if (!options.filter(node, originalRoot || node)) {
505
+ if ((_a = node.matches) == null ? void 0 : _a.call(node, selector)) {
561
506
  const spacer = document.createElement("div");
562
507
  const rect = node.getBoundingClientRect();
563
- spacer.style.cssText = `display: inline-block; width: ${rect.width}px; height: ${rect.height}px; visibility: hidden;`;
508
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
564
509
  return spacer;
565
510
  }
566
511
  } catch (err) {
567
- console.warn("Error in filter function:", err);
512
+ console.warn(`Invalid selector in exclude option: ${selector}`, err);
568
513
  }
569
514
  }
570
- if (node.tagName === "IFRAME") {
571
- const fallback = document.createElement("div");
572
- fallback.textContent = "";
573
- fallback.style.cssText = `width: ${node.offsetWidth}px; height: ${node.offsetHeight}px; background-image: repeating-linear-gradient(45deg, #ddd, #ddd 5px, #f9f9f9 5px, #f9f9f9 10px);display: flex;align-items: center;justify-content: center;font-size: 12px;color: #555; border: 1px solid #aaa;`;
574
- return fallback;
575
- }
576
- if (node.getAttribute("data-capture") === "placeholder") {
577
- const clone2 = node.cloneNode(false);
578
- cache.preNodeMap.set(clone2, node);
579
- inlineAllStyles(node, clone2, compress);
580
- const placeholder = document.createElement("div");
581
- placeholder.textContent = node.getAttribute("data-placeholder-text") || "";
582
- placeholder.style.cssText = `color: #666;font-size: 12px;text-align: center;line-height: 1.4;padding: 0.5em;box-sizing: border-box;`;
583
- clone2.appendChild(placeholder);
584
- return clone2;
585
- }
586
- if (node.tagName === "CANVAS") {
587
- const dataURL = node.toDataURL();
588
- const img = document.createElement("img");
589
- img.src = dataURL;
590
- img.width = node.width;
591
- img.height = node.height;
592
- cache.preNodeMap.set(img, node);
593
- inlineAllStyles(node, img, compress);
594
- return img;
595
- }
596
- let clone;
515
+ }
516
+ if (typeof options.filter === "function") {
597
517
  try {
598
- clone = node.cloneNode(false);
599
- if (!clone) {
600
- throw new Error("Failed to clone node: cloneNode returned null");
518
+ if (!options.filter(node, originalRoot || node)) {
519
+ const spacer = document.createElement("div");
520
+ const rect = node.getBoundingClientRect();
521
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
522
+ return spacer;
601
523
  }
602
- cache.preNodeMap.set(clone, node);
603
524
  } catch (err) {
604
- console.error("[Snapdom] Failed to clone node:", node, err);
605
- throw err;
525
+ console.warn("Error in filter function:", err);
606
526
  }
607
- if (node instanceof HTMLInputElement) {
608
- clone.value = node.value;
609
- clone.setAttribute("value", node.value);
610
- if (node.checked !== void 0) {
611
- clone.checked = node.checked;
612
- if (node.checked) clone.setAttribute("checked", "");
613
- }
614
- } else if (node instanceof HTMLTextAreaElement) {
615
- const rect = node.getBoundingClientRect();
616
- clone.textContent = node.value;
617
- clone.style.width = `${rect.width}px`;
618
- clone.style.height = `${rect.height}px`;
619
- } else if (node instanceof HTMLSelectElement) {
620
- clone.value = node.value;
621
- Array.from(clone.options).forEach((opt) => {
622
- if (opt.value === node.value) {
623
- opt.setAttribute("selected", "");
624
- } else {
625
- opt.removeAttribute("selected");
626
- }
627
- });
527
+ }
528
+ if (node.tagName === "IFRAME") {
529
+ const fallback = document.createElement("div");
530
+ fallback.style.cssText = `width:${node.offsetWidth}px;height:${node.offsetHeight}px;background-image:repeating-linear-gradient(45deg,#ddd,#ddd 5px,#f9f9f9 5px,#f9f9f9 10px);display:flex;align-items:center;justify-content:center;font-size:12px;color:#555;border:1px solid #aaa;`;
531
+ return fallback;
532
+ }
533
+ if (node.getAttribute("data-capture") === "placeholder") {
534
+ const clone2 = node.cloneNode(false);
535
+ cache.preNodeMap.set(clone2, node);
536
+ inlineAllStyles(node, clone2, compress);
537
+ const placeholder = document.createElement("div");
538
+ placeholder.textContent = node.getAttribute("data-placeholder-text") || "";
539
+ placeholder.style.cssText = `color:#666;font-size:12px;text-align:center;line-height:1.4;padding:0.5em;box-sizing:border-box;`;
540
+ clone2.appendChild(placeholder);
541
+ return clone2;
542
+ }
543
+ if (node.tagName === "CANVAS") {
544
+ const dataURL = node.toDataURL();
545
+ const img = document.createElement("img");
546
+ img.src = dataURL;
547
+ img.width = node.width;
548
+ img.height = node.height;
549
+ cache.preNodeMap.set(img, node);
550
+ inlineAllStyles(node, img, compress);
551
+ return img;
552
+ }
553
+ let clone;
554
+ try {
555
+ clone = node.cloneNode(false);
556
+ cache.preNodeMap.set(clone, node);
557
+ } catch (err) {
558
+ console.error("[Snapdom] Failed to clone node:", node, err);
559
+ throw err;
560
+ }
561
+ if (node instanceof HTMLTextAreaElement) {
562
+ clone.textContent = node.value;
563
+ clone.value = node.value;
564
+ const rect = node.getBoundingClientRect();
565
+ clone.style.width = `${rect.width}px`;
566
+ clone.style.height = `${rect.height}px`;
567
+ return clone;
568
+ }
569
+ if (node instanceof HTMLInputElement) {
570
+ clone.value = node.value;
571
+ clone.setAttribute("value", node.value);
572
+ if (node.checked !== void 0) {
573
+ clone.checked = node.checked;
574
+ if (node.checked) clone.setAttribute("checked", "");
575
+ if (node.indeterminate) clone.indeterminate = node.indeterminate;
628
576
  }
629
- inlineAllStyles(node, clone, compress);
630
- try {
631
- if (isSlotElement(node)) {
632
- const assigned = ((_b = node.assignedNodes) == null ? void 0 : _b.call(node, { flatten: true })) || [];
633
- const nodesToClone = assigned.length > 0 ? assigned : Array.from(node.childNodes);
634
- const fragment = document.createDocumentFragment();
635
- for (const child of nodesToClone) {
636
- try {
637
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
638
- if (clonedChild) fragment.appendChild(clonedChild);
639
- } catch (err) {
640
- console.warn("[Snapdom] Failed to clone slot content:", child, err);
641
- }
642
- }
643
- return fragment;
644
- } else {
645
- const baseChildren = node.shadowRoot ? node.shadowRoot.childNodes : node.childNodes;
646
- for (const child of baseChildren) {
647
- try {
648
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
649
- if (clonedChild) clone.appendChild(clonedChild);
650
- } catch (err) {
651
- console.warn("[Snapdom] Failed to clone child node:", child, err);
577
+ }
578
+ if (node instanceof HTMLSelectElement) {
579
+ pendingSelectValue = node.value;
580
+ }
581
+ inlineAllStyles(node, clone, compress);
582
+ if (node.shadowRoot) {
583
+ const hasSlot = Array.from(node.shadowRoot.querySelectorAll("slot")).length > 0;
584
+ if (hasSlot) {
585
+ for (const child of node.shadowRoot.childNodes) {
586
+ if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "STYLE") {
587
+ const cssText = child.textContent || "";
588
+ if (cssText.trim() && compress) {
589
+ if (!cache.preStyle) cache.preStyle = /* @__PURE__ */ new WeakMap();
590
+ cache.preStyle.set(child, cssText);
652
591
  }
653
592
  }
654
- if (node.shadowRoot && node.childNodes.length > 0 && !node.shadowRoot.querySelector("slot")) {
655
- const lightDomContent = document.createDocumentFragment();
656
- for (const child of node.childNodes) {
657
- try {
658
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
659
- if (clonedChild) lightDomContent.appendChild(clonedChild);
660
- } catch (err) {
661
- console.warn("[Snapdom] Failed to clone light DOM child:", child, err);
662
- }
593
+ }
594
+ } else {
595
+ const shadowFrag = document.createDocumentFragment();
596
+ for (const child of node.shadowRoot.childNodes) {
597
+ if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "STYLE") {
598
+ const cssText = child.textContent || "";
599
+ if (cssText.trim() && compress) {
600
+ if (!cache.preStyle) cache.preStyle = /* @__PURE__ */ new WeakMap();
601
+ cache.preStyle.set(child, cssText);
663
602
  }
664
- clone.appendChild(lightDomContent);
603
+ continue;
665
604
  }
605
+ const clonedChild = deepClone(child, compress, options, originalRoot || node);
606
+ if (clonedChild) shadowFrag.appendChild(clonedChild);
666
607
  }
667
- } catch (err) {
668
- console.error("[Snapdom] Error cloning children:", err);
669
- throw err;
608
+ clone.appendChild(shadowFrag);
670
609
  }
671
- return clone;
672
- } catch (error) {
673
- console.error("[Snapdom] Error in deepClone:", error);
674
- throw error;
675
610
  }
676
- }
677
- var init_clone = __esm({
678
- "src/core/clone.js"() {
679
- init_styles();
680
- init_cache();
611
+ if (node.tagName === "SLOT") {
612
+ const assigned = ((_b = node.assignedNodes) == null ? void 0 : _b.call(node, { flatten: true })) || [];
613
+ const nodesToClone = assigned.length > 0 ? assigned : Array.from(node.childNodes);
614
+ const fragment = document.createDocumentFragment();
615
+ for (const child of nodesToClone) {
616
+ const clonedChild = deepClone(child, compress, options, originalRoot || node);
617
+ if (clonedChild) fragment.appendChild(clonedChild);
618
+ }
619
+ return fragment;
681
620
  }
682
- });
621
+ for (const child of node.childNodes) {
622
+ if (clonedAssignedNodes.has(child)) continue;
623
+ const clonedChild = deepClone(child, compress, options, originalRoot || node);
624
+ if (clonedChild) clone.appendChild(clonedChild);
625
+ }
626
+ if (pendingSelectValue !== null && clone instanceof HTMLSelectElement) {
627
+ clone.value = pendingSelectValue;
628
+ for (const opt of clone.options) {
629
+ if (opt.value === pendingSelectValue) {
630
+ opt.setAttribute("selected", "");
631
+ } else {
632
+ opt.removeAttribute("selected");
633
+ }
634
+ }
635
+ }
636
+ return clone;
637
+ }
683
638
 
684
639
  // src/modules/iconFonts.js
640
+ var defaultIconFonts = [
641
+ // /uicons/i,
642
+ /font\s*awesome/i,
643
+ /material\s*icons/i,
644
+ /ionicons/i,
645
+ /glyphicons/i,
646
+ /feather/i,
647
+ /bootstrap\s*icons/i,
648
+ /remix\s*icons/i,
649
+ /heroicons/i,
650
+ /layui/i,
651
+ /lucide/i
652
+ ];
653
+ var userIconFonts = [];
685
654
  function extendIconFonts(fonts) {
686
655
  const list = Array.isArray(fonts) ? fonts : [fonts];
687
656
  for (const f of list) {
@@ -703,25 +672,6 @@
703
672
  if (/icon/i.test(text) || /glyph/i.test(text) || /symbols/i.test(text) || /feather/i.test(text) || /fontawesome/i.test(text)) return true;
704
673
  return false;
705
674
  }
706
- var defaultIconFonts, userIconFonts;
707
- var init_iconFonts = __esm({
708
- "src/modules/iconFonts.js"() {
709
- defaultIconFonts = [
710
- // /uicons/i,
711
- /font\s*awesome/i,
712
- /material\s*icons/i,
713
- /ionicons/i,
714
- /glyphicons/i,
715
- /feather/i,
716
- /bootstrap\s*icons/i,
717
- /remix\s*icons/i,
718
- /heroicons/i,
719
- /layui/i,
720
- /lucide/i
721
- ];
722
- userIconFonts = [];
723
- }
724
- });
725
675
 
726
676
  // src/modules/fonts.js
727
677
  function iconToImage(unicodeChar, fontFamily, fontWeight, fontSize = 32, color = "#000") {
@@ -846,6 +796,13 @@
846
796
  const family = rule.style.getPropertyValue("font-family");
847
797
  if (!src || isIconFont(family)) continue;
848
798
  const urlRegex = /url\((["']?)([^"')]+)\1\)/g;
799
+ const localRegex = /local\((["']?)[^)]+?\1\)/g;
800
+ const hasURL = !!src.match(urlRegex);
801
+ const hasLocal = !!src.match(localRegex);
802
+ if (!hasURL && hasLocal) {
803
+ finalCSS += `@font-face{font-family:${family};src:${src};font-style:${rule.style.getPropertyValue("font-style") || "normal"};font-weight:${rule.style.getPropertyValue("font-weight") || "normal"};}`;
804
+ continue;
805
+ }
849
806
  let inlinedSrc = src;
850
807
  const matches = Array.from(src.matchAll(urlRegex));
851
808
  for (const match of matches) {
@@ -877,13 +834,7 @@
877
834
  console.warn("[snapdom] Failed to fetch font URL:", url);
878
835
  }
879
836
  }
880
- finalCSS += `@font-face {
881
- font-family: ${family};
882
- src: ${inlinedSrc};
883
- font-style: ${rule.style.getPropertyValue("font-style") || "normal"};
884
- font-weight: ${rule.style.getPropertyValue("font-weight") || "normal"};
885
- }
886
- `;
837
+ finalCSS += `@font-face{font-family:${family};src:${inlinedSrc};font-style:${rule.style.getPropertyValue("font-style") || "normal"};font-weight:${rule.style.getPropertyValue("font-weight") || "normal"};}`;
887
838
  }
888
839
  }
889
840
  }
@@ -916,13 +867,7 @@
916
867
  }
917
868
  }
918
869
  }
919
- finalCSS += `@font-face {
920
- font-family: '${font.family}';
921
- src: url(${b64});
922
- font-style: ${font.style || "normal"};
923
- font-weight: ${font.weight || "normal"};
924
- }
925
- `;
870
+ finalCSS += `@font-face{font-family:'${font.family}';src:url(${b64});font-style:${font.style || "normal"};font-weight:${font.weight || "normal"};}`;
926
871
  }
927
872
  }
928
873
  if (finalCSS) {
@@ -937,13 +882,6 @@
937
882
  return finalCSS;
938
883
  });
939
884
  }
940
- var init_fonts = __esm({
941
- "src/modules/fonts.js"() {
942
- init_helpers();
943
- init_cache();
944
- init_iconFonts();
945
- }
946
- });
947
885
 
948
886
  // src/modules/pseudo.js
949
887
  function inlinePseudoElements(source, clone, compress, embedFonts = false, useProxy) {
@@ -969,9 +907,9 @@
969
907
  const span = document.createElement("span");
970
908
  span.textContent = first;
971
909
  span.dataset.snapdomPseudo = "::first-letter";
972
- const snapshot = snapshotComputedStyle(style);
973
- const key = getStyleKey(snapshot, "span", compress);
974
- cache.preStyleMap.set(span, key);
910
+ const snapshot2 = snapshotComputedStyle(style);
911
+ const key2 = getStyleKey(snapshot2, "span", compress);
912
+ cache.preStyleMap.set(span, key2);
975
913
  const restNode = document.createTextNode(rest);
976
914
  clone.replaceChild(restNode, textNode);
977
915
  clone.insertBefore(span, restNode);
@@ -980,59 +918,73 @@
980
918
  const content = style.getPropertyValue("content");
981
919
  const bg = style.getPropertyValue("background-image");
982
920
  const bgColor = style.getPropertyValue("background-color");
921
+ const fontFamily = style.getPropertyValue("font-family");
922
+ const fontSize = parseInt(style.getPropertyValue("font-size")) || 32;
923
+ const fontWeight = parseInt(style.getPropertyValue("font-weight")) || false;
924
+ const color = style.getPropertyValue("color") || "#000";
925
+ const display = style.getPropertyValue("display");
926
+ const width = parseFloat(style.getPropertyValue("width"));
927
+ const height = parseFloat(style.getPropertyValue("height"));
928
+ const borderStyle = style.getPropertyValue("border-style");
929
+ const transform = style.getPropertyValue("transform");
930
+ const isIconFont2 = isIconFont(fontFamily);
931
+ let cleanContent;
932
+ if (/counter\s*\(|counters\s*\(/.test(content)) {
933
+ cleanContent = "- ";
934
+ } else {
935
+ cleanContent = parseContent(content);
936
+ }
983
937
  const hasContent = content !== "none";
938
+ const hasExplicitContent = hasContent && cleanContent !== "";
984
939
  const hasBg = bg && bg !== "none";
985
940
  const hasBgColor = bgColor && bgColor !== "transparent" && bgColor !== "rgba(0, 0, 0, 0)";
986
- if (hasContent || hasBg || hasBgColor) {
987
- const fontFamily = style.getPropertyValue("font-family");
988
- const fontSize = parseInt(style.getPropertyValue("font-size")) || 32;
989
- const fontWeight = parseInt(style.getPropertyValue("font-weight")) || false;
990
- const color = style.getPropertyValue("color") || "#000";
991
- const pseudoEl = document.createElement("span");
992
- pseudoEl.dataset.snapdomPseudo = pseudo;
993
- const snapshot = snapshotComputedStyle(style);
994
- const key = getStyleKey(snapshot, "span", compress);
995
- cache.preStyleMap.set(pseudoEl, key);
996
- const isIconFont2 = isIconFont(fontFamily);
997
- const cleanContent = parseContent(content);
998
- if (isIconFont2 && cleanContent.length === 1) {
999
- const imgEl = document.createElement("img");
1000
- imgEl.src = yield iconToImage(cleanContent, fontFamily, fontWeight, fontSize, color);
1001
- imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
1002
- pseudoEl.appendChild(imgEl);
1003
- } else if (cleanContent.startsWith("url(")) {
1004
- const rawUrl = extractURL(cleanContent);
1005
- if (rawUrl && rawUrl.trim() !== "") {
1006
- try {
1007
- const imgEl = document.createElement("img");
1008
- const dataUrl = yield fetchImage(safeEncodeURI(rawUrl, { useProxy }));
1009
- imgEl.src = dataUrl;
1010
- imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
1011
- pseudoEl.appendChild(imgEl);
1012
- } catch (e) {
1013
- console.error(`[snapdom] Error in pseudo ${pseudo} for`, source, e);
1014
- }
1015
- }
1016
- } else if (!isIconFont2 && cleanContent && cleanContent !== "none") {
1017
- pseudoEl.textContent = cleanContent;
1018
- }
1019
- if (hasBg) {
941
+ const hasBox = display !== "inline" && (width > 0 || height > 0);
942
+ const hasBorder = borderStyle && borderStyle !== "none";
943
+ const hasTransform = transform && transform !== "none";
944
+ const shouldRender = hasExplicitContent || hasBg || hasBgColor || hasBox || hasBorder || hasTransform;
945
+ if (!shouldRender) continue;
946
+ const pseudoEl = document.createElement("span");
947
+ pseudoEl.dataset.snapdomPseudo = pseudo;
948
+ const snapshot = snapshotComputedStyle(style);
949
+ const key = getStyleKey(snapshot, "span", compress);
950
+ cache.preStyleMap.set(pseudoEl, key);
951
+ if (isIconFont2 && cleanContent.length === 1) {
952
+ const imgEl = document.createElement("img");
953
+ imgEl.src = yield iconToImage(cleanContent, fontFamily, fontWeight, fontSize, color);
954
+ imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
955
+ pseudoEl.appendChild(imgEl);
956
+ } else if (cleanContent.startsWith("url(")) {
957
+ const rawUrl = extractURL(cleanContent);
958
+ if (rawUrl && rawUrl.trim() !== "") {
1020
959
  try {
1021
- const bgSplits = splitBackgroundImage(bg);
1022
- const newBgParts = yield Promise.all(
1023
- bgSplits.map((entry) => inlineSingleBackgroundEntry(entry))
1024
- );
1025
- pseudoEl.style.backgroundImage = newBgParts.join(", ");
960
+ const imgEl = document.createElement("img");
961
+ const dataUrl = yield fetchImage(safeEncodeURI(rawUrl, { useProxy }));
962
+ imgEl.src = dataUrl;
963
+ imgEl.style = `width:${fontSize}px;height:auto;object-fit:contain;`;
964
+ pseudoEl.appendChild(imgEl);
1026
965
  } catch (e) {
1027
- console.warn(`[snapdom] Failed to inline background-image for ${pseudo}`, e);
966
+ console.error(`[snapdom] Error in pseudo ${pseudo} for`, source, e);
1028
967
  }
1029
968
  }
1030
- if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
1031
- const hasContent2 = pseudoEl.childNodes.length > 0 || pseudoEl.textContent && pseudoEl.textContent.trim() !== "";
1032
- const hasVisibleBox = hasContent2 || hasBg || hasBgColor;
1033
- if (!hasVisibleBox) continue;
1034
- pseudo === "::before" ? clone.insertBefore(pseudoEl, clone.firstChild) : clone.appendChild(pseudoEl);
969
+ } else if (!isIconFont2 && hasExplicitContent) {
970
+ pseudoEl.textContent = cleanContent;
971
+ }
972
+ if (hasBg) {
973
+ try {
974
+ const bgSplits = splitBackgroundImage(bg);
975
+ const newBgParts = yield Promise.all(
976
+ bgSplits.map((entry) => inlineSingleBackgroundEntry(entry))
977
+ );
978
+ pseudoEl.style.backgroundImage = newBgParts.join(", ");
979
+ } catch (e) {
980
+ console.warn(`[snapdom] Failed to inline background-image for ${pseudo}`, e);
981
+ }
1035
982
  }
983
+ if (hasBgColor) pseudoEl.style.backgroundColor = bgColor;
984
+ const hasContent2 = pseudoEl.childNodes.length > 0 || pseudoEl.textContent && pseudoEl.textContent.trim() !== "";
985
+ const hasVisibleBox = hasContent2 || hasBg || hasBgColor || hasBox || hasBorder || hasTransform;
986
+ if (!hasVisibleBox) continue;
987
+ pseudo === "::before" ? clone.insertBefore(pseudoEl, clone.firstChild) : clone.appendChild(pseudoEl);
1036
988
  } catch (e) {
1037
989
  console.warn(`[snapdom] Failed to capture ${pseudo} for`, source, e);
1038
990
  }
@@ -1050,15 +1002,6 @@
1050
1002
  }
1051
1003
  });
1052
1004
  }
1053
- var init_pseudo = __esm({
1054
- "src/modules/pseudo.js"() {
1055
- init_helpers();
1056
- init_cssTools();
1057
- init_fonts();
1058
- init_iconFonts();
1059
- init_cache();
1060
- }
1061
- });
1062
1005
 
1063
1006
  // src/modules/svgDefs.js
1064
1007
  function inlineExternalDef(root) {
@@ -1089,10 +1032,6 @@
1089
1032
  }
1090
1033
  });
1091
1034
  }
1092
- var init_svgDefs = __esm({
1093
- "src/modules/svgDefs.js"() {
1094
- }
1095
- });
1096
1035
 
1097
1036
  // src/core/prepare.js
1098
1037
  function prepareClone(_0) {
@@ -1176,16 +1115,6 @@
1176
1115
  return { clone, classCSS };
1177
1116
  });
1178
1117
  }
1179
- var init_prepare = __esm({
1180
- "src/core/prepare.js"() {
1181
- init_cssTools();
1182
- init_helpers();
1183
- init_clone();
1184
- init_pseudo();
1185
- init_svgDefs();
1186
- init_cache();
1187
- }
1188
- });
1189
1118
 
1190
1119
  // src/modules/images.js
1191
1120
  function inlineImages(_0) {
@@ -1211,11 +1140,6 @@
1211
1140
  }
1212
1141
  });
1213
1142
  }
1214
- var init_images = __esm({
1215
- "src/modules/images.js"() {
1216
- init_helpers();
1217
- }
1218
- });
1219
1143
 
1220
1144
  // src/modules/background.js
1221
1145
  function inlineBackgroundImages(_0, _1) {
@@ -1258,12 +1182,6 @@
1258
1182
  }
1259
1183
  });
1260
1184
  }
1261
- var init_background = __esm({
1262
- "src/modules/background.js"() {
1263
- init_helpers();
1264
- init_cache();
1265
- }
1266
- });
1267
1185
 
1268
1186
  // src/core/capture.js
1269
1187
  function captureDOM(_0) {
@@ -1345,8 +1263,6 @@
1345
1263
  const existingTransform = clone.style.transform || "";
1346
1264
  const scaleTransform = `scale(${scaleX}, ${scaleY})`;
1347
1265
  clone.style.transform = `${scaleTransform} ${existingTransform}`.trim();
1348
- } else if (hasScale && isSafari()) {
1349
- clone.style.scale = `${scale}`;
1350
1266
  }
1351
1267
  const svgNS = "http://www.w3.org/2000/svg";
1352
1268
  const fo = document.createElementNS(svgNS, "foreignObject");
@@ -1370,17 +1286,6 @@
1370
1286
  return dataURL;
1371
1287
  });
1372
1288
  }
1373
- var init_capture = __esm({
1374
- "src/core/capture.js"() {
1375
- init_prepare();
1376
- init_images();
1377
- init_background();
1378
- init_helpers();
1379
- init_cssTools();
1380
- init_fonts();
1381
- init_cache();
1382
- }
1383
- });
1384
1289
 
1385
1290
  // src/api/snapdom.js
1386
1291
  function toImg(_0, _1) {
@@ -1388,13 +1293,8 @@
1388
1293
  const img = new Image();
1389
1294
  img.src = url;
1390
1295
  yield img.decode();
1391
- if (isSafari) {
1392
- img.width = img.width * scale;
1393
- img.height = img.height * scale;
1394
- } else {
1395
- img.width = img.width / scale;
1396
- img.height = img.height / scale;
1397
- }
1296
+ img.width = img.width * scale;
1297
+ img.height = img.height * scale;
1398
1298
  return img;
1399
1299
  });
1400
1300
  }
@@ -1402,17 +1302,34 @@
1402
1302
  return __async(this, arguments, function* (url, { dpr = 1, scale = 1 } = {}) {
1403
1303
  const img = new Image();
1404
1304
  img.src = url;
1305
+ img.crossOrigin = "anonymous";
1306
+ img.loading = "eager";
1307
+ img.decoding = "sync";
1308
+ const isSafariBrowser = isSafari();
1309
+ let appended = false;
1310
+ if (isSafariBrowser) {
1311
+ document.body.appendChild(img);
1312
+ appended = true;
1313
+ }
1405
1314
  yield img.decode();
1406
- const canvas = document.createElement("canvas");
1315
+ if (isSafariBrowser) {
1316
+ yield new Promise((resolve) => setTimeout(resolve, 100));
1317
+ }
1318
+ if (img.width === 0 || img.height === 0) {
1319
+ if (appended) img.remove();
1320
+ throw new Error("Image failed to load or has no dimensions");
1321
+ }
1407
1322
  const width = img.width * scale;
1408
1323
  const height = img.height * scale;
1324
+ const canvas = document.createElement("canvas");
1409
1325
  canvas.width = Math.ceil(width * dpr);
1410
1326
  canvas.height = Math.ceil(height * dpr);
1327
+ canvas.style.width = `${width}px`;
1328
+ canvas.style.height = `${height}px`;
1411
1329
  const ctx = canvas.getContext("2d");
1412
1330
  ctx.scale(dpr, dpr);
1413
1331
  ctx.drawImage(img, 0, 0, width, height);
1414
- canvas.style.width = `${width}px`;
1415
- canvas.style.height = `${height}px`;
1332
+ if (appended) img.remove();
1416
1333
  return canvas;
1417
1334
  });
1418
1335
  }
@@ -1467,7 +1384,7 @@
1467
1384
  });
1468
1385
  }
1469
1386
  function download(_0) {
1470
- return __async(this, arguments, function* (url, { dpr = 1, scale = 1, backgroundColor = "#fff", format = "png", filename = "capture" } = {}) {
1387
+ return __async(this, arguments, function* (url, { dpr = 1, scale = 1, backgroundColor, format = "png", filename = "snapDOM" } = {}) {
1471
1388
  if (format === "svg") {
1472
1389
  const blob = yield toBlob(url);
1473
1390
  const objectURL = URL.createObjectURL(blob);
@@ -1504,63 +1421,56 @@
1504
1421
  return yield snapdom.capture(element, options);
1505
1422
  });
1506
1423
  }
1507
- var init_snapdom = __esm({
1508
- "src/api/snapdom.js"() {
1509
- init_capture();
1510
- init_helpers();
1511
- init_iconFonts();
1512
- snapdom.capture = (_0, ..._1) => __async(null, [_0, ..._1], function* (el, options = {}) {
1513
- const url = yield captureDOM(el, options);
1514
- const dpr = window.devicePixelRatio || 1;
1515
- const scale = options.scale || 1;
1516
- return {
1517
- url,
1518
- options,
1519
- toRaw: () => url,
1520
- toImg: () => toImg(url, { dpr, scale }),
1521
- toCanvas: () => toCanvas(url, { dpr, scale }),
1522
- toBlob: (options2) => toBlob(url, __spreadValues({ dpr, scale }, options2)),
1523
- toPng: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "png"),
1524
- toJpg: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "jpeg"),
1525
- toWebp: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "webp"),
1526
- download: ({ format = "png", filename = "capture", backgroundColor } = {}) => download(url, { dpr, scale, backgroundColor, format, filename })
1527
- };
1528
- });
1529
- snapdom.toRaw = (el, options) => __async(null, null, function* () {
1530
- return (yield snapdom.capture(el, options)).toRaw();
1531
- });
1532
- snapdom.toImg = (el, options) => __async(null, null, function* () {
1533
- return (yield snapdom.capture(el, options)).toImg();
1534
- });
1535
- snapdom.toCanvas = (el, options) => __async(null, null, function* () {
1536
- return (yield snapdom.capture(el, options)).toCanvas();
1537
- });
1538
- snapdom.toBlob = (el, options) => __async(null, null, function* () {
1539
- return (yield snapdom.capture(el, options)).toBlob(options);
1540
- });
1541
- snapdom.toPng = (el, options) => __async(null, null, function* () {
1542
- return (yield snapdom.capture(el, options)).toPng(options);
1543
- });
1544
- snapdom.toJpg = (el, options) => __async(null, null, function* () {
1545
- return (yield snapdom.capture(el, options)).toJpg(options);
1546
- });
1547
- snapdom.toWebp = (el, options) => __async(null, null, function* () {
1548
- return (yield snapdom.capture(el, options)).toWebp(options);
1549
- });
1550
- snapdom.download = (_0, ..._1) => __async(null, [_0, ..._1], function* (el, options = {}) {
1551
- const _a = options, {
1552
- format = "png",
1553
- filename = "capture",
1554
- backgroundColor
1555
- } = _a, rest = __objRest(_a, [
1556
- "format",
1557
- "filename",
1558
- "backgroundColor"
1559
- ]);
1560
- const capture = yield snapdom.capture(el, rest);
1561
- return yield capture.download({ format, filename, backgroundColor });
1562
- });
1563
- }
1424
+ snapdom.capture = (_0, ..._1) => __async(null, [_0, ..._1], function* (el, options = {}) {
1425
+ const url = yield captureDOM(el, options);
1426
+ const dpr = window.devicePixelRatio || 1;
1427
+ const scale = options.scale || 1;
1428
+ return {
1429
+ url,
1430
+ options,
1431
+ toRaw: () => url,
1432
+ toImg: () => toImg(url, { dpr, scale }),
1433
+ toCanvas: () => toCanvas(url, { dpr, scale }),
1434
+ toBlob: (options2) => toBlob(url, __spreadValues({ dpr, scale }, options2)),
1435
+ toPng: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "png"),
1436
+ toJpg: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "jpeg"),
1437
+ toWebp: (options2) => toRasterImg(url, __spreadValues({ dpr, scale }, options2), "webp"),
1438
+ download: ({ format = "png", filename = "capture", backgroundColor } = {}) => download(url, { dpr, scale, backgroundColor, format, filename })
1439
+ };
1440
+ });
1441
+ snapdom.toRaw = (el, options) => __async(null, null, function* () {
1442
+ return (yield snapdom.capture(el, options)).toRaw();
1443
+ });
1444
+ snapdom.toImg = (el, options) => __async(null, null, function* () {
1445
+ return (yield snapdom.capture(el, options)).toImg();
1446
+ });
1447
+ snapdom.toCanvas = (el, options) => __async(null, null, function* () {
1448
+ return (yield snapdom.capture(el, options)).toCanvas();
1449
+ });
1450
+ snapdom.toBlob = (el, options) => __async(null, null, function* () {
1451
+ return (yield snapdom.capture(el, options)).toBlob(options);
1452
+ });
1453
+ snapdom.toPng = (el, options) => __async(null, null, function* () {
1454
+ return (yield snapdom.capture(el, options)).toPng(options);
1455
+ });
1456
+ snapdom.toJpg = (el, options) => __async(null, null, function* () {
1457
+ return (yield snapdom.capture(el, options)).toJpg(options);
1458
+ });
1459
+ snapdom.toWebp = (el, options) => __async(null, null, function* () {
1460
+ return (yield snapdom.capture(el, options)).toWebp(options);
1461
+ });
1462
+ snapdom.download = (_0, ..._1) => __async(null, [_0, ..._1], function* (el, options = {}) {
1463
+ const _a = options, {
1464
+ format = "png",
1465
+ filename = "capture",
1466
+ backgroundColor
1467
+ } = _a, rest = __objRest(_a, [
1468
+ "format",
1469
+ "filename",
1470
+ "backgroundColor"
1471
+ ]);
1472
+ const capture = yield snapdom.capture(el, rest);
1473
+ return yield capture.download({ format, filename, backgroundColor });
1564
1474
  });
1565
1475
 
1566
1476
  // src/api/preCache.js
@@ -1609,38 +1519,10 @@
1609
1519
  yield Promise.all(promises);
1610
1520
  });
1611
1521
  }
1612
- var init_preCache = __esm({
1613
- "src/api/preCache.js"() {
1614
- init_helpers();
1615
- init_fonts();
1616
- init_cssTools();
1617
- init_cache();
1618
- }
1619
- });
1620
1522
 
1621
1523
  // src/index.browser.js
1622
- var require_index_browser = __commonJS({
1623
- "src/index.browser.js"(exports, module) {
1624
- init_snapdom();
1625
- init_preCache();
1626
- window.snapdom = snapdom;
1627
- if (typeof window !== "undefined") {
1628
- window.snapdom = snapdom;
1629
- window.preCache = preCache;
1630
- }
1631
- if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
1632
- module.exports = { snapdom, preCache };
1633
- }
1634
- if (typeof define === "function" && define.amd) {
1635
- define([], function() {
1636
- return { snapdom, preCache };
1637
- });
1638
- }
1639
- if (typeof globalThis !== "undefined") {
1640
- globalThis.snapdom = snapdom;
1641
- globalThis.preCache = preCache;
1642
- }
1643
- }
1644
- });
1645
- require_index_browser();
1524
+ if (typeof window !== "undefined") {
1525
+ window.snapdom = snapdom;
1526
+ window.preCache = preCache;
1527
+ }
1646
1528
  })();