@zumer/snapdom 1.9.8 → 1.9.9

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,13 +1,15 @@
1
1
 
2
2
  /*
3
3
  * snapdom
4
- * v.1.9.8
4
+ * v.1.9.9
5
5
  * Author Juan Martin Muda
6
6
  * License MIT
7
7
  **/
8
8
 
9
9
  (() => {
10
10
  var __defProp = Object.defineProperty;
11
+ var __defProps = Object.defineProperties;
12
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
11
13
  var __getOwnPropSymbols = Object.getOwnPropertySymbols;
12
14
  var __hasOwnProp = Object.prototype.hasOwnProperty;
13
15
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
@@ -23,6 +25,7 @@
23
25
  }
24
26
  return a;
25
27
  };
28
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
26
29
  var __objRest = (source, exclude) => {
27
30
  var target = {};
28
31
  for (var prop in source)
@@ -67,18 +70,10 @@
67
70
  font: /* @__PURE__ */ new Set(),
68
71
  snapshot: /* @__PURE__ */ new WeakMap(),
69
72
  snapshotKey: /* @__PURE__ */ new Map(),
70
- preStyleMap: /* @__PURE__ */ new Map(),
71
- preStyle: /* @__PURE__ */ new WeakMap(),
72
- preNodeMap: /* @__PURE__ */ new Map(),
73
73
  reset: resetCache
74
74
  };
75
75
  function resetCache() {
76
76
  cache.computedStyle = /* @__PURE__ */ new WeakMap();
77
- cache.snapshot = /* @__PURE__ */ new WeakMap();
78
- cache.snapshotKey.clear();
79
- cache.preStyleMap.clear();
80
- cache.preStyle = /* @__PURE__ */ new WeakMap();
81
- cache.preNodeMap.clear();
82
77
  }
83
78
 
84
79
  // src/utils/cssTools.js
@@ -212,8 +207,8 @@
212
207
  }
213
208
  return css;
214
209
  }
215
- function generateCSSClasses() {
216
- const keySet = new Set(cache.preStyleMap.values());
210
+ function generateCSSClasses(styleMap) {
211
+ const keySet = new Set(styleMap.values());
217
212
  const classMap = /* @__PURE__ */ new Map();
218
213
  let counter = 1;
219
214
  for (const key of keySet) {
@@ -285,7 +280,29 @@
285
280
  if (url.startsWith("#")) return null;
286
281
  return url;
287
282
  }
288
- function fetchImage(src, { timeout = 3e3, useProxy = "" } = {}) {
283
+ function fetchResource(_0) {
284
+ return __async(this, arguments, function* (url, { useProxy = "" } = {}) {
285
+ function doFetch(u) {
286
+ return __async(this, null, function* () {
287
+ const res = yield fetch(u);
288
+ if (!res.ok) throw new Error(`[snapdom] Failed to fetch resource: ${u}`);
289
+ return res;
290
+ });
291
+ }
292
+ try {
293
+ return yield doFetch(url);
294
+ } catch (e) {
295
+ if (useProxy && typeof useProxy === "string") {
296
+ const proxied = useProxy.replace(/\/$/, "") + safeEncodeURI(url);
297
+ return doFetch(proxied);
298
+ }
299
+ throw e;
300
+ }
301
+ });
302
+ }
303
+ var _inflight = /* @__PURE__ */ new Map();
304
+ var _errorCache = /* @__PURE__ */ new Map();
305
+ function fetchImage(src, { timeout = 3e3, useProxy = "", errorTTL = 8e3 } = {}) {
289
306
  function getCrossOriginMode(url) {
290
307
  try {
291
308
  const parsed = new URL(url, window.location.href);
@@ -294,107 +311,157 @@
294
311
  return "anonymous";
295
312
  }
296
313
  }
297
- function fetchWithFallback(url) {
298
- return __async(this, null, function* () {
299
- const fetchBlobAsDataURL = (fetchUrl) => fetch(fetchUrl, {
314
+ const ok = (data) => ({ ok: true, data });
315
+ const fail = (e) => ({ ok: false, error: e instanceof Error ? e : new Error(String(e)) });
316
+ function fetchBlobAsDataURLSafe(fetchUrl) {
317
+ try {
318
+ return fetch(fetchUrl, {
300
319
  mode: "cors",
301
320
  credentials: getCrossOriginMode(fetchUrl) === "use-credentials" ? "include" : "omit"
302
- }).then((r) => r.blob()).then((blob) => new Promise((resolve, reject) => {
303
- const reader = new FileReader();
304
- reader.onloadend = () => {
305
- const base64 = reader.result;
306
- if (typeof base64 !== "string" || !base64.startsWith("data:image/")) {
307
- reject(new Error("Invalid image data URL"));
308
- return;
309
- }
310
- resolve(base64);
311
- };
312
- reader.onerror = () => reject(new Error("FileReader error"));
313
- reader.readAsDataURL(blob);
314
- }));
315
- try {
316
- return yield fetchBlobAsDataURL(url);
317
- } catch (e) {
318
- if (useProxy && typeof useProxy === "string") {
319
- const proxied = useProxy.replace(/\/$/, "") + safeEncodeURI(url);
320
- try {
321
- return yield fetchBlobAsDataURL(proxied);
322
- } catch (e2) {
323
- throw new Error("[SnapDOM - fetchImage] CORS restrictions prevented image capture (even via proxy)");
324
- }
325
- } else {
326
- throw new Error("[SnapDOM - fetchImage] Fetch fallback failed and no proxy provided");
327
- }
321
+ }).then((r) => {
322
+ if (!r.ok) return fail(new Error("HTTP " + r.status));
323
+ return r.blob().then((blob) => new Promise((resolve) => {
324
+ const reader = new FileReader();
325
+ reader.onloadend = () => {
326
+ const base64 = reader.result;
327
+ if (typeof base64 !== "string" || !base64.startsWith("data:image/")) {
328
+ resolve(fail(new Error("Invalid image data URL")));
329
+ } else {
330
+ resolve(ok(base64));
331
+ }
332
+ };
333
+ reader.onerror = () => resolve(fail(new Error("FileReader error")));
334
+ reader.readAsDataURL(blob);
335
+ }));
336
+ }).catch((e) => fail(e));
337
+ } catch (e) {
338
+ return Promise.resolve(fail(e));
339
+ }
340
+ }
341
+ function fetchWithFallbackOnceSafe(url) {
342
+ return fetchBlobAsDataURLSafe(url).then((r) => {
343
+ if (r.ok) return r;
344
+ if (useProxy && typeof useProxy === "string") {
345
+ const proxied = useProxy.replace(/\/$/, "") + safeEncodeURI(url);
346
+ return fetchBlobAsDataURLSafe(proxied).then((r2) => {
347
+ if (r2.ok) return r2;
348
+ return fail(new Error("[SnapDOM - fetchImage] Fetch failed and no proxy provided"));
349
+ });
328
350
  }
351
+ return fail(new Error("[SnapDOM - fetchImage] Fetch failed and no proxy provided"));
329
352
  });
330
353
  }
331
- const crossOriginValue = getCrossOriginMode(src);
332
- if (cache.image.has(src)) {
333
- return Promise.resolve(cache.image.get(src));
354
+ const now = Date.now();
355
+ const until = _errorCache.get(src);
356
+ if (until && until > now) {
357
+ const pr = Promise.reject(new Error("[SnapDOM - fetchImage] Recently failed (cooldown)."));
358
+ pr.catch(() => {
359
+ });
360
+ return pr;
334
361
  }
335
- const isDataURI = src.startsWith("data:image/");
336
- if (isDataURI) {
362
+ if (_inflight.has(src)) return _inflight.get(src);
363
+ const crossOriginValue = getCrossOriginMode(src);
364
+ if (cache.image.has(src)) return Promise.resolve(cache.image.get(src));
365
+ if (src.startsWith("data:image/")) {
337
366
  cache.image.set(src, src);
338
367
  return Promise.resolve(src);
339
368
  }
340
- const isSVG = /\.svg(\?.*)?$/i.test(src);
341
- if (isSVG) {
342
- return (() => __async(null, null, function* () {
343
- try {
344
- const response = yield fetch(src, {
345
- mode: "cors",
346
- credentials: crossOriginValue === "use-credentials" ? "include" : "omit"
347
- });
348
- const svgText = yield response.text();
349
- const encoded = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgText)}`;
350
- cache.image.set(src, encoded);
351
- return encoded;
352
- } catch (e) {
353
- return fetchWithFallback(src);
369
+ if (/\.svg(\?.*)?$/i.test(src)) {
370
+ const p2 = (() => __async(null, null, function* () {
371
+ const direct = yield (() => __async(null, null, function* () {
372
+ try {
373
+ const res = yield fetch(src, {
374
+ mode: "cors",
375
+ credentials: crossOriginValue === "use-credentials" ? "include" : "omit"
376
+ });
377
+ if (!res.ok) return fail(new Error("HTTP " + res.status));
378
+ const svgText = yield res.text();
379
+ return ok(`data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgText)}`);
380
+ } catch (e) {
381
+ return fail(e);
382
+ }
383
+ }))();
384
+ if (direct.ok) {
385
+ cache.image.set(src, direct.data);
386
+ return direct.data;
354
387
  }
388
+ const via = yield fetchWithFallbackOnceSafe(src);
389
+ if (via.ok) {
390
+ cache.image.set(src, via.data);
391
+ return via.data;
392
+ }
393
+ _errorCache.set(src, now + errorTTL);
394
+ return Promise.reject(via.error);
355
395
  }))();
396
+ _inflight.set(src, p2);
397
+ p2.finally(() => _inflight.delete(src));
398
+ p2.catch(() => {
399
+ });
400
+ return p2;
356
401
  }
357
- return new Promise((resolve, reject) => {
358
- const timeoutId = setTimeout(() => {
359
- reject(new Error("[SnapDOM - fetchImage] Image load timed out"));
360
- }, timeout);
361
- const image = new Image();
362
- image.crossOrigin = crossOriginValue;
363
- image.onload = () => __async(null, null, function* () {
402
+ const p = new Promise((resolve, reject) => {
403
+ let finished = false;
404
+ const img = new Image();
405
+ const finish = (fn) => (arg) => {
406
+ if (finished) return;
407
+ finished = true;
364
408
  clearTimeout(timeoutId);
365
- try {
366
- yield image.decode();
367
- const canvas = document.createElement("canvas");
368
- canvas.width = image.width;
369
- canvas.height = image.height;
370
- const ctx = canvas.getContext("2d");
371
- ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
372
- const dataURL = canvas.toDataURL("image/png");
373
- cache.image.set(src, dataURL);
374
- resolve(dataURL);
375
- } catch (e) {
409
+ img.onload = img.onerror = null;
410
+ fn(arg);
411
+ };
412
+ const onSuccess = (d) => {
413
+ cache.image.set(src, d);
414
+ resolve(d);
415
+ };
416
+ const onFinalError = (e) => {
417
+ _errorCache.set(src, Date.now() + errorTTL);
418
+ reject(e);
419
+ };
420
+ const timeoutId = setTimeout(
421
+ finish(() => {
422
+ fetchWithFallbackOnceSafe(src).then((r) => {
423
+ if (r.ok) onSuccess(r.data);
424
+ else onFinalError(new Error("Image load timed out"));
425
+ });
426
+ }),
427
+ timeout
428
+ );
429
+ img.crossOrigin = crossOriginValue;
430
+ img.onload = finish(() => {
431
+ Promise.resolve(img.decode()).then(() => {
376
432
  try {
377
- const fallbackDataURL = yield fetchWithFallback(src);
378
- cache.image.set(src, fallbackDataURL);
379
- resolve(fallbackDataURL);
380
- } catch (e2) {
381
- reject(e2);
433
+ const canvas = document.createElement("canvas");
434
+ canvas.width = img.naturalWidth || img.width;
435
+ canvas.height = img.naturalHeight || img.height;
436
+ const ctx = canvas.getContext("2d");
437
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
438
+ onSuccess(canvas.toDataURL("image/png"));
439
+ } catch (e) {
440
+ fetchWithFallbackOnceSafe(src).then((r) => {
441
+ if (r.ok) onSuccess(r.data);
442
+ else onFinalError(r.error);
443
+ });
382
444
  }
383
- }
445
+ }).catch(() => {
446
+ fetchWithFallbackOnceSafe(src).then((r) => {
447
+ if (r.ok) onSuccess(r.data);
448
+ else onFinalError(r.error);
449
+ });
450
+ });
384
451
  });
385
- image.onerror = () => __async(null, null, function* () {
386
- clearTimeout(timeoutId);
387
- console.error(`[SnapDOM - fetchImage] Image failed to load: ${src}`);
388
- try {
389
- const fallbackDataURL = yield fetchWithFallback(src);
390
- cache.image.set(src, fallbackDataURL);
391
- resolve(fallbackDataURL);
392
- } catch (e) {
393
- reject(e);
394
- }
452
+ img.onerror = finish(() => {
453
+ fetchWithFallbackOnceSafe(src).then((r) => {
454
+ if (r.ok) onSuccess(r.data);
455
+ else onFinalError(r.error);
456
+ });
395
457
  });
396
- image.src = src;
458
+ img.src = src;
397
459
  });
460
+ _inflight.set(src, p);
461
+ p.finally(() => _inflight.delete(src));
462
+ p.catch(() => {
463
+ });
464
+ return p;
398
465
  }
399
466
  function snapshotComputedStyle(style) {
400
467
  const snap = {};
@@ -451,6 +518,8 @@
451
518
  }
452
519
 
453
520
  // src/modules/styles.js
521
+ var snapshotCache = /* @__PURE__ */ new WeakMap();
522
+ var snapshotKeyCache = /* @__PURE__ */ new Map();
454
523
  function snapshotComputedStyleFull(style) {
455
524
  const result = {};
456
525
  const computedVisibility = style.getPropertyValue("visibility");
@@ -467,31 +536,43 @@
467
536
  }
468
537
  return result;
469
538
  }
470
- function inlineAllStyles(source, clone, compress) {
539
+ function inlineAllStyles(source, clone, styleMap, cache2, compress) {
471
540
  var _a;
472
541
  if (source.tagName === "STYLE") return;
473
- if (!cache.preStyle.has(source)) {
474
- cache.preStyle.set(source, getStyle(source));
542
+ if (!cache2.has(source)) {
543
+ cache2.set(source, getStyle(source));
475
544
  }
476
- const style = cache.preStyle.get(source);
477
- if (!cache.snapshot.has(source)) {
545
+ const style = cache2.get(source);
546
+ if (!snapshotCache.has(source)) {
478
547
  const snapshot2 = snapshotComputedStyleFull(style);
479
- cache.snapshot.set(source, snapshot2);
548
+ snapshotCache.set(source, snapshot2);
480
549
  }
481
- const snapshot = cache.snapshot.get(source);
550
+ const snapshot = snapshotCache.get(source);
482
551
  const hash = Object.entries(snapshot).sort(([a], [b]) => a.localeCompare(b)).map(([prop, val]) => `${prop}:${val}`).join(";");
483
- if (cache.snapshotKey.has(hash)) {
484
- cache.preStyleMap.set(clone, cache.snapshotKey.get(hash));
552
+ if (snapshotKeyCache.has(hash)) {
553
+ styleMap.set(clone, snapshotKeyCache.get(hash));
485
554
  return;
486
555
  }
487
556
  const tagName = ((_a = source.tagName) == null ? void 0 : _a.toLowerCase()) || "div";
488
557
  const key = getStyleKey(snapshot, tagName, compress);
489
- cache.snapshotKey.set(hash, key);
490
- cache.preStyleMap.set(clone, key);
558
+ snapshotKeyCache.set(hash, key);
559
+ styleMap.set(clone, key);
491
560
  }
492
561
 
493
562
  // src/core/clone.js
494
- function deepClone(node, compress, options = {}, originalRoot) {
563
+ function freezeImgSrcset(original, cloned) {
564
+ try {
565
+ const chosen = original.currentSrc || original.src || "";
566
+ if (!chosen) return;
567
+ cloned.setAttribute("src", chosen);
568
+ cloned.removeAttribute("srcset");
569
+ cloned.removeAttribute("sizes");
570
+ cloned.loading = "eager";
571
+ cloned.decoding = "sync";
572
+ } catch (e) {
573
+ }
574
+ }
575
+ function deepClone(node, styleMap, styleCache, nodeMap, compress, options = {}, originalRoot) {
495
576
  var _a, _b;
496
577
  if (!node) throw new Error("Invalid node");
497
578
  const clonedAssignedNodes = /* @__PURE__ */ new Set();
@@ -541,8 +622,8 @@
541
622
  }
542
623
  if (node.getAttribute("data-capture") === "placeholder") {
543
624
  const clone2 = node.cloneNode(false);
544
- cache.preNodeMap.set(clone2, node);
545
- inlineAllStyles(node, clone2, compress);
625
+ nodeMap.set(clone2, node);
626
+ inlineAllStyles(node, clone2, styleMap, styleCache, compress);
546
627
  const placeholder = document.createElement("div");
547
628
  placeholder.textContent = node.getAttribute("data-placeholder-text") || "";
548
629
  placeholder.style.cssText = `color:#666;font-size:12px;text-align:center;line-height:1.4;padding:0.5em;box-sizing:border-box;`;
@@ -555,14 +636,17 @@
555
636
  img.src = dataURL;
556
637
  img.width = node.width;
557
638
  img.height = node.height;
558
- cache.preNodeMap.set(img, node);
559
- inlineAllStyles(node, img, compress);
639
+ nodeMap.set(img, node);
640
+ inlineAllStyles(node, img, styleMap, styleCache, compress);
560
641
  return img;
561
642
  }
562
643
  let clone;
563
644
  try {
564
645
  clone = node.cloneNode(false);
565
- cache.preNodeMap.set(clone, node);
646
+ nodeMap.set(clone, node);
647
+ if (node.tagName === "IMG") {
648
+ freezeImgSrcset(node, clone);
649
+ }
566
650
  } catch (err) {
567
651
  console.error("[Snapdom] Failed to clone node:", node, err);
568
652
  throw err;
@@ -587,7 +671,7 @@
587
671
  if (node instanceof HTMLSelectElement) {
588
672
  pendingSelectValue = node.value;
589
673
  }
590
- inlineAllStyles(node, clone, compress);
674
+ inlineAllStyles(node, clone, styleMap, styleCache, compress);
591
675
  if (node.shadowRoot) {
592
676
  const hasSlot = Array.from(node.shadowRoot.querySelectorAll("slot")).length > 0;
593
677
  if (hasSlot) {
@@ -595,8 +679,7 @@
595
679
  if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "STYLE") {
596
680
  const cssText = child.textContent || "";
597
681
  if (cssText.trim() && compress) {
598
- if (!cache.preStyle) cache.preStyle = /* @__PURE__ */ new WeakMap();
599
- cache.preStyle.set(child, cssText);
682
+ styleCache.set(child, cssText);
600
683
  }
601
684
  }
602
685
  }
@@ -606,12 +689,11 @@
606
689
  if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "STYLE") {
607
690
  const cssText = child.textContent || "";
608
691
  if (cssText.trim() && compress) {
609
- if (!cache.preStyle) cache.preStyle = /* @__PURE__ */ new WeakMap();
610
- cache.preStyle.set(child, cssText);
692
+ styleCache.set(child, cssText);
611
693
  }
612
694
  continue;
613
695
  }
614
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
696
+ const clonedChild = deepClone(child, styleMap, styleCache, nodeMap, compress, options, originalRoot || node);
615
697
  if (clonedChild) shadowFrag.appendChild(clonedChild);
616
698
  }
617
699
  clone.appendChild(shadowFrag);
@@ -622,14 +704,14 @@
622
704
  const nodesToClone = assigned.length > 0 ? assigned : Array.from(node.childNodes);
623
705
  const fragment = document.createDocumentFragment();
624
706
  for (const child of nodesToClone) {
625
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
707
+ const clonedChild = deepClone(child, styleMap, styleCache, nodeMap, compress, options, originalRoot || node);
626
708
  if (clonedChild) fragment.appendChild(clonedChild);
627
709
  }
628
710
  return fragment;
629
711
  }
630
712
  for (const child of node.childNodes) {
631
713
  if (clonedAssignedNodes.has(child)) continue;
632
- const clonedChild = deepClone(child, compress, options, originalRoot || node);
714
+ const clonedChild = deepClone(child, styleMap, styleCache, nodeMap, compress, options, originalRoot || node);
633
715
  if (clonedChild) clone.appendChild(clonedChild);
634
716
  }
635
717
  if (pendingSelectValue !== null && clone instanceof HTMLSelectElement) {
@@ -737,7 +819,7 @@
737
819
  });
738
820
  }
739
821
  function embedCustomFonts() {
740
- return __async(this, arguments, function* ({ preCached = false } = {}) {
822
+ return __async(this, arguments, function* ({ preCached = false, localFonts = [], useProxy = "" } = {}) {
741
823
  if (cache.resource.has("fonts-embed-css")) {
742
824
  if (preCached) {
743
825
  const style = document.createElement("style");
@@ -747,6 +829,15 @@
747
829
  }
748
830
  return cache.resource.get("fonts-embed-css");
749
831
  }
832
+ const loadedFonts = /* @__PURE__ */ new Set();
833
+ try {
834
+ for (const f of document.fonts) {
835
+ if (f.status === "loaded") {
836
+ loadedFonts.add(`${f.family}__${f.weight || "normal"}__${f.style || "normal"}`);
837
+ }
838
+ }
839
+ } catch (e) {
840
+ }
750
841
  const importRegex = /@import\s+url\(["']?([^"')]+)["']?\)/g;
751
842
  const styleImports = [];
752
843
  for (const styleTag of document.querySelectorAll("style")) {
@@ -765,26 +856,48 @@
765
856
  let finalCSS = "";
766
857
  for (const link of links) {
767
858
  try {
768
- const res = yield fetch(link.href);
859
+ const res = yield fetchResource(link.href, { useProxy });
769
860
  const cssText = yield res.text();
770
861
  if (isIconFont(link.href) || isIconFont(cssText)) continue;
771
- const urlRegex = /url\((["']?)([^"')]+)\1\)/g;
772
- const inlinedCSS = yield Promise.all(
773
- Array.from(cssText.matchAll(urlRegex)).map((match) => __async(null, null, function* () {
862
+ const faceRegex = /@font-face[^{}]*{[^}]*}/g;
863
+ let cssFinal = cssText;
864
+ for (const face of cssText.match(faceRegex) || []) {
865
+ const famMatch = face.match(/font-family:\s*([^;]+);/i);
866
+ if (!famMatch) continue;
867
+ const family = famMatch[1].replace(/['"]/g, "").trim();
868
+ const weightMatch = face.match(/font-weight:\s*([^;]+);/i);
869
+ const styleMatch = face.match(/font-style:\s*([^;]+);/i);
870
+ const weight = weightMatch ? weightMatch[1].trim() : "normal";
871
+ const style = styleMatch ? styleMatch[1].trim() : "normal";
872
+ const key = `${family}__${weight}__${style}`;
873
+ const urlRegex = /url\((["']?)([^"')]+)\1\)/g;
874
+ const hasURL = /url\(/i.test(face);
875
+ const hasLocal = /local\(/i.test(face);
876
+ if (!hasURL && hasLocal) {
877
+ continue;
878
+ }
879
+ if (!loadedFonts.has(key)) {
880
+ cssFinal = cssFinal.replace(face, "");
881
+ continue;
882
+ }
883
+ let inlined = face;
884
+ const matches = Array.from(face.matchAll(urlRegex));
885
+ for (const match of matches) {
774
886
  let rawUrl = extractURL(match[0]);
775
- if (!rawUrl) return null;
887
+ if (!rawUrl) continue;
776
888
  let url = rawUrl;
777
889
  if (!url.startsWith("http") && !url.startsWith("data:")) {
778
890
  url = new URL(url, link.href).href;
779
891
  }
780
- if (isIconFont(url)) return null;
892
+ if (isIconFont(url)) continue;
781
893
  if (cache.resource.has(url)) {
782
894
  cache.font.add(url);
783
- return { original: match[0], inlined: `url(${cache.resource.get(url)})` };
895
+ inlined = inlined.replace(match[0], `url(${cache.resource.get(url)})`);
896
+ continue;
784
897
  }
785
- if (cache.font.has(url)) return null;
898
+ if (cache.font.has(url)) continue;
786
899
  try {
787
- const fontRes = yield fetch(url);
900
+ const fontRes = yield fetchResource(url, { useProxy });
788
901
  const blob = yield fontRes.blob();
789
902
  const b64 = yield new Promise((resolve) => {
790
903
  const reader = new FileReader();
@@ -793,16 +906,12 @@
793
906
  });
794
907
  cache.resource.set(url, b64);
795
908
  cache.font.add(url);
796
- return { original: match[0], inlined: `url(${b64})` };
909
+ inlined = inlined.replace(match[0], `url(${b64})`);
797
910
  } catch (e) {
798
911
  console.warn("[snapdom] Failed to fetch font resource:", url);
799
- return null;
800
912
  }
801
- }))
802
- );
803
- let cssFinal = cssText;
804
- for (const r of inlinedCSS) {
805
- if (r) cssFinal = cssFinal.replace(r.original, r.inlined);
913
+ }
914
+ cssFinal = cssFinal.replace(face, inlined);
806
915
  }
807
916
  finalCSS += cssFinal + "\n";
808
917
  } catch (e) {
@@ -817,14 +926,18 @@
817
926
  const src = rule.style.getPropertyValue("src");
818
927
  const family = rule.style.getPropertyValue("font-family");
819
928
  if (!src || isIconFont(family)) continue;
929
+ const weightVal = rule.style.getPropertyValue("font-weight") || "normal";
930
+ const styleVal = rule.style.getPropertyValue("font-style") || "normal";
931
+ const key = `${family}__${weightVal}__${styleVal}`;
820
932
  const urlRegex = /url\((["']?)([^"')]+)\1\)/g;
821
933
  const localRegex = /local\((["']?)[^)]+?\1\)/g;
822
934
  const hasURL = !!src.match(urlRegex);
823
935
  const hasLocal = !!src.match(localRegex);
824
936
  if (!hasURL && hasLocal) {
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"};}`;
937
+ finalCSS += `@font-face{font-family:${family};src:${src};font-style:${styleVal};font-weight:${weightVal};}`;
826
938
  continue;
827
939
  }
940
+ if (!loadedFonts.has(key)) continue;
828
941
  let inlinedSrc = src;
829
942
  const matches = Array.from(src.matchAll(urlRegex));
830
943
  for (const match of matches) {
@@ -842,7 +955,7 @@
842
955
  }
843
956
  if (cache.font.has(url)) continue;
844
957
  try {
845
- const res = yield fetch(url);
958
+ const res = yield fetchResource(url, { useProxy });
846
959
  const blob = yield res.blob();
847
960
  const b64 = yield new Promise((resolve) => {
848
961
  const reader = new FileReader();
@@ -856,7 +969,7 @@
856
969
  console.warn("[snapdom] Failed to fetch font URL:", url);
857
970
  }
858
971
  }
859
- finalCSS += `@font-face{font-family:${family};src:${inlinedSrc};font-style:${rule.style.getPropertyValue("font-style") || "normal"};font-weight:${rule.style.getPropertyValue("font-weight") || "normal"};}`;
972
+ finalCSS += `@font-face{font-family:${family};src:${inlinedSrc};font-style:${styleVal};font-weight:${weightVal};}`;
860
973
  }
861
974
  }
862
975
  }
@@ -874,7 +987,7 @@
874
987
  cache.font.add(font._snapdomSrc);
875
988
  } else if (!cache.font.has(font._snapdomSrc)) {
876
989
  try {
877
- const res = yield fetch(font._snapdomSrc);
990
+ const res = yield fetchResource(font._snapdomSrc, { useProxy });
878
991
  const blob = yield res.blob();
879
992
  b64 = yield new Promise((resolve) => {
880
993
  const reader = new FileReader();
@@ -892,6 +1005,32 @@
892
1005
  finalCSS += `@font-face{font-family:'${font.family}';src:url(${b64});font-style:${font.style || "normal"};font-weight:${font.weight || "normal"};}`;
893
1006
  }
894
1007
  }
1008
+ for (const font of localFonts) {
1009
+ if (!font || typeof font !== "object") continue;
1010
+ const { family, src, weight = "normal", style = "normal" } = font;
1011
+ if (!family || !src) continue;
1012
+ let b64 = src;
1013
+ if (!b64.startsWith("data:")) {
1014
+ try {
1015
+ const res = yield fetchResource(src, { useProxy });
1016
+ const blob = yield res.blob();
1017
+ b64 = yield new Promise((resolve) => {
1018
+ const reader = new FileReader();
1019
+ reader.onload = () => resolve(reader.result);
1020
+ reader.readAsDataURL(blob);
1021
+ });
1022
+ cache.resource.set(src, b64);
1023
+ cache.font.add(src);
1024
+ } catch (e) {
1025
+ console.warn("[snapdom] Failed to load local font:", src);
1026
+ continue;
1027
+ }
1028
+ } else {
1029
+ cache.resource.set(src, b64);
1030
+ cache.font.add(src);
1031
+ }
1032
+ finalCSS += `@font-face{font-family:'${family}';src:url(${b64});font-style:${style};font-weight:${weight};}`;
1033
+ }
895
1034
  if (finalCSS) {
896
1035
  cache.resource.set("fonts-embed-css", finalCSS);
897
1036
  if (preCached) {
@@ -906,7 +1045,7 @@
906
1045
  }
907
1046
 
908
1047
  // src/modules/pseudo.js
909
- function inlinePseudoElements(source, clone, options) {
1048
+ function inlinePseudoElements(source, clone, styleMap, styleCache, options) {
910
1049
  return __async(this, null, function* () {
911
1050
  var _a;
912
1051
  if (!(source instanceof Element) || !(clone instanceof Element)) return;
@@ -937,7 +1076,7 @@
937
1076
  span.dataset.snapdomPseudo = "::first-letter";
938
1077
  const snapshot2 = snapshotComputedStyle(style);
939
1078
  const key2 = getStyleKey(snapshot2, "span", options);
940
- cache.preStyleMap.set(span, key2);
1079
+ styleMap.set(span, key2);
941
1080
  const restNode = document.createTextNode(rest);
942
1081
  clone.replaceChild(restNode, textNode);
943
1082
  clone.insertBefore(span, restNode);
@@ -971,7 +1110,7 @@
971
1110
  pseudoEl.style.verticalAlign = "middle";
972
1111
  const snapshot = snapshotComputedStyle(style);
973
1112
  const key = getStyleKey(snapshot, "span", options);
974
- cache.preStyleMap.set(pseudoEl, key);
1113
+ styleMap.set(pseudoEl, key);
975
1114
  if (isIconFont2 && cleanContent.length === 1) {
976
1115
  const { dataUrl, width: width2, height: height2 } = yield iconToImage(cleanContent, fontFamily, fontWeight, fontSize, color);
977
1116
  const imgEl = document.createElement("img");
@@ -1020,7 +1159,7 @@
1020
1159
  const sChildren = Array.from(source.children);
1021
1160
  const cChildren = Array.from(clone.children).filter((child) => !child.dataset.snapdomPseudo);
1022
1161
  for (let i = 0; i < Math.min(sChildren.length, cChildren.length); i++) {
1023
- yield inlinePseudoElements(sChildren[i], cChildren[i], options);
1162
+ yield inlinePseudoElements(sChildren[i], cChildren[i], styleMap, styleCache, options);
1024
1163
  }
1025
1164
  });
1026
1165
  }
@@ -1079,6 +1218,9 @@
1079
1218
  function prepareClone(_0) {
1080
1219
  return __async(this, arguments, function* (element, compress = false, embedFonts = false, options = {}) {
1081
1220
  var _a, _b;
1221
+ const styleMap = /* @__PURE__ */ new Map();
1222
+ const styleCache = /* @__PURE__ */ new WeakMap();
1223
+ const nodeMap = /* @__PURE__ */ new Map();
1082
1224
  let clone;
1083
1225
  let classCSS = "";
1084
1226
  stabilizeLayout(element);
@@ -1088,20 +1230,21 @@
1088
1230
  console.warn("inlineExternal defs or symbol failed:", e);
1089
1231
  }
1090
1232
  try {
1091
- clone = deepClone(element, compress, options, element);
1233
+ clone = deepClone(element, styleMap, styleCache, nodeMap, compress, options, element);
1092
1234
  } catch (e) {
1093
1235
  console.warn("deepClone failed:", e);
1094
1236
  throw e;
1095
1237
  }
1096
1238
  try {
1097
- yield inlinePseudoElements(element, clone, compress, embedFonts, options.useProxy);
1239
+ yield inlinePseudoElements(element, clone, styleMap, styleCache, compress, embedFonts, options.useProxy);
1098
1240
  } catch (e) {
1099
1241
  console.warn("inlinePseudoElements failed:", e);
1100
1242
  }
1243
+ yield resolveBlobUrlsInTree(clone);
1101
1244
  if (compress) {
1102
- const keyToClass = generateCSSClasses();
1245
+ const keyToClass = generateCSSClasses(styleMap);
1103
1246
  classCSS = Array.from(keyToClass.entries()).map(([key, className]) => `.${className}{${key}}`).join("");
1104
- for (const [node, key] of cache.preStyleMap.entries()) {
1247
+ for (const [node, key] of styleMap.entries()) {
1105
1248
  if (node.tagName === "STYLE") continue;
1106
1249
  if (node.getRootNode && node.getRootNode() instanceof ShadowRoot) {
1107
1250
  node.setAttribute("style", key.replace(/;/g, "; "));
@@ -1118,12 +1261,12 @@
1118
1261
  }
1119
1262
  }
1120
1263
  } else {
1121
- for (const [node, key] of cache.preStyleMap.entries()) {
1264
+ for (const [node, key] of styleMap.entries()) {
1122
1265
  if (node.tagName === "STYLE") continue;
1123
1266
  node.setAttribute("style", key.replace(/;/g, "; "));
1124
1267
  }
1125
1268
  }
1126
- for (const [cloneNode, originalNode] of cache.preNodeMap.entries()) {
1269
+ for (const [cloneNode, originalNode] of nodeMap.entries()) {
1127
1270
  const scrollX = originalNode.scrollLeft;
1128
1271
  const scrollY = originalNode.scrollTop;
1129
1272
  const hasScroll = scrollX || scrollY;
@@ -1142,9 +1285,9 @@
1142
1285
  cloneNode.appendChild(inner);
1143
1286
  }
1144
1287
  }
1145
- if (element === cache.preNodeMap.get(clone)) {
1146
- const computed = cache.preStyle.get(element) || window.getComputedStyle(element);
1147
- cache.preStyle.set(element, computed);
1288
+ if (element === nodeMap.get(clone)) {
1289
+ const computed = styleCache.get(element) || window.getComputedStyle(element);
1290
+ styleCache.set(element, computed);
1148
1291
  const transform = stripTranslate(computed.transform);
1149
1292
  clone.style.margin = "0";
1150
1293
  clone.style.position = "static";
@@ -1157,13 +1300,13 @@
1157
1300
  clone.style.clear = "none";
1158
1301
  clone.style.transform = transform || "";
1159
1302
  }
1160
- for (const [cloneNode, originalNode] of cache.preNodeMap.entries()) {
1303
+ for (const [cloneNode, originalNode] of nodeMap.entries()) {
1161
1304
  if (originalNode.tagName === "PRE") {
1162
1305
  cloneNode.style.marginTop = "0";
1163
1306
  cloneNode.style.marginBlockStart = "0";
1164
1307
  }
1165
1308
  }
1166
- return { clone, classCSS };
1309
+ return { clone, classCSS, styleCache };
1167
1310
  });
1168
1311
  }
1169
1312
  function stabilizeLayout(element) {
@@ -1178,12 +1321,148 @@
1178
1321
  element.style.border = `${outlineWidth} solid transparent`;
1179
1322
  }
1180
1323
  }
1324
+ var _blobToDataUrlCache = /* @__PURE__ */ new Map();
1325
+ function blobUrlToDataUrl(blobUrl) {
1326
+ return __async(this, null, function* () {
1327
+ if (_blobToDataUrlCache.has(blobUrl)) return _blobToDataUrlCache.get(blobUrl);
1328
+ const res = yield fetch(blobUrl);
1329
+ if (!res.ok) throw new Error(`[SnapDOM] HTTP ${res.status} on blob fetch (${blobUrl})`);
1330
+ const blob = yield res.blob();
1331
+ const dataUrl = yield new Promise((resolve, reject) => {
1332
+ const fr = new FileReader();
1333
+ fr.onloadend = () => {
1334
+ const v = fr.result;
1335
+ if (typeof v === "string" && v.startsWith("data:")) resolve(v);
1336
+ else reject(new Error("[SnapDOM] Invalid data URL from blob"));
1337
+ };
1338
+ fr.onerror = () => reject(new Error("[SnapDOM] FileReader error"));
1339
+ fr.readAsDataURL(blob);
1340
+ });
1341
+ _blobToDataUrlCache.set(blobUrl, dataUrl);
1342
+ return dataUrl;
1343
+ });
1344
+ }
1345
+ var BLOB_URL_RE = /\bblob:[^)"'\s]+/g;
1346
+ function replaceBlobUrlsInCssText(cssText) {
1347
+ return __async(this, null, function* () {
1348
+ if (!cssText || cssText.indexOf("blob:") === -1) return cssText;
1349
+ const uniques = Array.from(new Set(cssText.match(BLOB_URL_RE) || []));
1350
+ if (uniques.length === 0) return cssText;
1351
+ let out = cssText;
1352
+ for (const u of uniques) {
1353
+ try {
1354
+ const d = yield blobUrlToDataUrl(u);
1355
+ out = out.split(u).join(d);
1356
+ } catch (e) {
1357
+ }
1358
+ }
1359
+ return out;
1360
+ });
1361
+ }
1362
+ function isBlobUrl(u) {
1363
+ return typeof u === "string" && u.startsWith("blob:");
1364
+ }
1365
+ function parseSrcset(srcset) {
1366
+ return (srcset || "").split(",").map((s) => s.trim()).filter(Boolean).map((item) => {
1367
+ const m = item.match(/^(\S+)(\s+.+)?$/);
1368
+ return m ? { url: m[1], desc: m[2] || "" } : null;
1369
+ }).filter(Boolean);
1370
+ }
1371
+ function stringifySrcset(parts) {
1372
+ return parts.map((p) => p.desc ? `${p.url} ${p.desc.trim()}` : p.url).join(", ");
1373
+ }
1374
+ function resolveBlobUrlsInTree(root) {
1375
+ return __async(this, null, function* () {
1376
+ var _a, _b;
1377
+ if (!root) return;
1378
+ const imgs = root.querySelectorAll ? root.querySelectorAll("img") : [];
1379
+ for (const img of imgs) {
1380
+ try {
1381
+ const srcAttr = img.getAttribute("src");
1382
+ const effective = srcAttr || img.currentSrc || "";
1383
+ if (isBlobUrl(effective)) {
1384
+ const data = yield blobUrlToDataUrl(effective);
1385
+ img.setAttribute("src", data);
1386
+ }
1387
+ const srcset = img.getAttribute("srcset");
1388
+ if (srcset && srcset.includes("blob:")) {
1389
+ const parts = parseSrcset(srcset);
1390
+ let changed = false;
1391
+ for (const p of parts) {
1392
+ if (isBlobUrl(p.url)) {
1393
+ try {
1394
+ p.url = yield blobUrlToDataUrl(p.url);
1395
+ changed = true;
1396
+ } catch (e) {
1397
+ }
1398
+ }
1399
+ }
1400
+ if (changed) img.setAttribute("srcset", stringifySrcset(parts));
1401
+ }
1402
+ } catch (e) {
1403
+ }
1404
+ }
1405
+ const svgImages = root.querySelectorAll ? root.querySelectorAll("image") : [];
1406
+ for (const node of svgImages) {
1407
+ try {
1408
+ const XLINK_NS = "http://www.w3.org/1999/xlink";
1409
+ const href = node.getAttribute("href") || ((_a = node.getAttributeNS) == null ? void 0 : _a.call(node, XLINK_NS, "href"));
1410
+ if (isBlobUrl(href)) {
1411
+ const d = yield blobUrlToDataUrl(href);
1412
+ node.setAttribute("href", d);
1413
+ (_b = node.removeAttributeNS) == null ? void 0 : _b.call(node, XLINK_NS, "href");
1414
+ }
1415
+ } catch (e) {
1416
+ }
1417
+ }
1418
+ const styled = root.querySelectorAll ? root.querySelectorAll("[style*='blob:']") : [];
1419
+ for (const el of styled) {
1420
+ try {
1421
+ const styleText = el.getAttribute("style");
1422
+ if (styleText && styleText.includes("blob:")) {
1423
+ const replaced = yield replaceBlobUrlsInCssText(styleText);
1424
+ el.setAttribute("style", replaced);
1425
+ }
1426
+ } catch (e) {
1427
+ }
1428
+ }
1429
+ const styleTags = root.querySelectorAll ? root.querySelectorAll("style") : [];
1430
+ for (const s of styleTags) {
1431
+ try {
1432
+ const css = s.textContent || "";
1433
+ if (css.includes("blob:")) {
1434
+ s.textContent = yield replaceBlobUrlsInCssText(css);
1435
+ }
1436
+ } catch (e) {
1437
+ }
1438
+ }
1439
+ const urlAttrs = ["poster"];
1440
+ for (const attr of urlAttrs) {
1441
+ const nodes = root.querySelectorAll ? root.querySelectorAll(`[${attr}^='blob:']`) : [];
1442
+ for (const n of nodes) {
1443
+ try {
1444
+ const u = n.getAttribute(attr);
1445
+ if (isBlobUrl(u)) {
1446
+ n.setAttribute(attr, yield blobUrlToDataUrl(u));
1447
+ }
1448
+ } catch (e) {
1449
+ }
1450
+ }
1451
+ }
1452
+ });
1453
+ }
1181
1454
 
1182
1455
  // src/modules/images.js
1183
1456
  function inlineImages(_0) {
1184
1457
  return __async(this, arguments, function* (clone, options = {}) {
1185
1458
  const imgs = Array.from(clone.querySelectorAll("img"));
1186
1459
  const processImg = (img) => __async(null, null, function* () {
1460
+ if (!img.getAttribute("src")) {
1461
+ const eff = img.currentSrc || img.src || "";
1462
+ if (eff) img.setAttribute("src", eff);
1463
+ }
1464
+ img.removeAttribute("srcset");
1465
+ img.removeAttribute("sizes");
1187
1466
  const src = img.src;
1188
1467
  try {
1189
1468
  const dataUrl = yield fetchImage(src, { useProxy: options.useProxy });
@@ -1205,8 +1484,8 @@
1205
1484
  }
1206
1485
 
1207
1486
  // src/modules/background.js
1208
- function inlineBackgroundImages(_0, _1) {
1209
- return __async(this, arguments, function* (source, clone, options = {}) {
1487
+ function inlineBackgroundImages(_0, _1, _2) {
1488
+ return __async(this, arguments, function* (source, clone, styleCache, options = {}) {
1210
1489
  const queue = [[source, clone]];
1211
1490
  const imageProps = [
1212
1491
  "background-image",
@@ -1226,8 +1505,8 @@
1226
1505
  ];
1227
1506
  while (queue.length) {
1228
1507
  const [srcNode, cloneNode] = queue.shift();
1229
- const style = cache.preStyle.get(srcNode) || getStyle(srcNode);
1230
- if (!cache.preStyle.has(srcNode)) cache.preStyle.set(srcNode, style);
1508
+ const style = styleCache.get(srcNode) || getStyle(srcNode);
1509
+ if (!styleCache.has(srcNode)) styleCache.set(srcNode, style);
1231
1510
  const hasBorderImage = (() => {
1232
1511
  const bi = style.getPropertyValue("border-image");
1233
1512
  const bis = style.getPropertyValue("border-image-source");
@@ -1265,13 +1544,13 @@
1265
1544
  return __async(this, arguments, function* (element, options = {}) {
1266
1545
  if (!element) throw new Error("Element cannot be null or undefined");
1267
1546
  cache.reset();
1268
- const { compress = true, embedFonts = false, fast = true, scale = 1, useProxy = "" } = options;
1269
- let clone, classCSS;
1547
+ const { compress = true, embedFonts = false, fast = true, scale = 1, useProxy = "", localFonts = [] } = options;
1548
+ let clone, classCSS, styleCache;
1270
1549
  let fontsCSS = "";
1271
1550
  let baseCSS = "";
1272
1551
  let dataURL;
1273
1552
  let svgString;
1274
- ({ clone, classCSS } = yield prepareClone(element, compress, embedFonts, options));
1553
+ ({ clone, classCSS, styleCache } = yield prepareClone(element, compress, embedFonts, options));
1275
1554
  yield new Promise((resolve) => {
1276
1555
  idle(() => __async(null, null, function* () {
1277
1556
  yield inlineImages(clone, options);
@@ -1280,14 +1559,14 @@
1280
1559
  });
1281
1560
  yield new Promise((resolve) => {
1282
1561
  idle(() => __async(null, null, function* () {
1283
- yield inlineBackgroundImages(element, clone, options);
1562
+ yield inlineBackgroundImages(element, clone, styleCache, options);
1284
1563
  resolve();
1285
1564
  }), { fast });
1286
1565
  });
1287
1566
  if (embedFonts) {
1288
1567
  yield new Promise((resolve) => {
1289
1568
  idle(() => __async(null, null, function* () {
1290
- fontsCSS = yield embedCustomFonts();
1569
+ fontsCSS = yield embedCustomFonts({ localFonts, useProxy });
1291
1570
  resolve();
1292
1571
  }), { fast });
1293
1572
  });
@@ -1559,12 +1838,21 @@
1559
1838
  // src/api/preCache.js
1560
1839
  function preCache() {
1561
1840
  return __async(this, arguments, function* (root = document, options = {}) {
1562
- const { embedFonts = true, reset = false } = options;
1841
+ const { embedFonts = true, reset = false, useProxy } = options;
1563
1842
  if (reset) {
1564
- cache.reset();
1843
+ cache.image.clear();
1844
+ cache.background.clear();
1845
+ cache.resource.clear();
1846
+ cache.defaultStyle.clear();
1847
+ cache.baseStyle.clear();
1848
+ cache.font.clear();
1849
+ cache.computedStyle = /* @__PURE__ */ new WeakMap();
1565
1850
  return;
1566
1851
  }
1567
- yield document.fonts.ready;
1852
+ try {
1853
+ yield document.fonts.ready;
1854
+ } catch (e) {
1855
+ }
1568
1856
  precacheCommonTags();
1569
1857
  let imgEls = [], allEls = [];
1570
1858
  if (root == null ? void 0 : root.querySelectorAll) {
@@ -1573,33 +1861,41 @@
1573
1861
  }
1574
1862
  const promises = [];
1575
1863
  for (const img of imgEls) {
1576
- const src = img.src;
1864
+ const src = img == null ? void 0 : img.src;
1865
+ if (!src) continue;
1577
1866
  if (!cache.image.has(src)) {
1578
- promises.push(
1579
- fetchImage(src, { useProxy: options.useProxy }).then((dataURL) => cache.image.set(src, dataURL)).catch(() => {
1580
- })
1581
- );
1867
+ const p = Promise.resolve().then(() => fetchImage(src, { useProxy })).then((dataURL) => {
1868
+ cache.image.set(src, dataURL);
1869
+ }).catch(() => {
1870
+ });
1871
+ promises.push(p);
1582
1872
  }
1583
1873
  }
1584
1874
  for (const el of allEls) {
1585
- const bg = getStyle(el).backgroundImage;
1875
+ let bg = "";
1876
+ try {
1877
+ bg = getStyle(el).backgroundImage;
1878
+ } catch (e) {
1879
+ }
1586
1880
  if (bg && bg !== "none") {
1587
1881
  const bgSplits = splitBackgroundImage(bg);
1588
1882
  for (const entry of bgSplits) {
1589
- const isUrl = entry.startsWith("url(");
1590
- if (isUrl) {
1591
- promises.push(
1592
- inlineSingleBackgroundEntry(entry, options).catch(() => {
1593
- })
1594
- );
1883
+ if (entry.startsWith("url(")) {
1884
+ const p = Promise.resolve().then(() => inlineSingleBackgroundEntry(entry, __spreadProps(__spreadValues({}, options), { useProxy }))).catch(() => {
1885
+ });
1886
+ promises.push(p);
1595
1887
  }
1596
1888
  }
1597
1889
  }
1598
1890
  }
1599
1891
  if (embedFonts) {
1600
- yield embedCustomFonts({ preCached: true });
1892
+ try {
1893
+ yield embedCustomFonts({ preCached: true, localFonts: options.localFonts, useProxy: options.useProxy });
1894
+ } catch (e) {
1895
+ }
1896
+ ;
1601
1897
  }
1602
- yield Promise.all(promises);
1898
+ yield Promise.allSettled(promises);
1603
1899
  });
1604
1900
  }
1605
1901