@zumer/snapdom 1.9.11 → 1.9.12-dev.0

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 CHANGED
@@ -202,7 +202,9 @@ All capture methods accept an `options` object:
202
202
  | `useProxy` | string | `''` | Proxy base for CORS fallbacks |
203
203
  | `type` | string | `svg` | Default Blob type (`svg`\|`png`\|`jpg`\|`webp`) |
204
204
  | `exclude` | string[] | - | CSS selectors to exclude |
205
+ | `excludeMode` | string | 'visuallyHide' | Controls how `exclude` works with nodes |
205
206
  | `filter` | function | - | Custom predicate `(el) => boolean` |
207
+ | `filterMode` | string | 'visuallyHide' | Controls how `filter` works with nodes |
206
208
  | `cache` | string | `"soft"` | Control internal caches: `disabled`, `soft`, `auto`, `full` |
207
209
  | `defaultImageUrl` | string \| function | - | Fallback image when an `<img>` fails. If a function is provided, it receives `{ width?, height?, src?, element }` and must return a URL (string or Promise<string>). Useful for placeholder services (e.g. `https://placehold.co/{width}x{height}`) |
208
210
 
@@ -304,7 +306,9 @@ await snapdom.toPng(el, {
304
306
  ### Filtering nodes: `exclude` vs `filter`
305
307
 
306
308
  * `exclude`: remove by **selector**.
309
+ * `excludeMode`: `visuallyHide` applies `visibility:hidden` CSS rule on excluded nodes and the layout remains as the original. `remove` do not clone excluded nodes at all.
307
310
  * `filter`: advanced predicate per element (return `false` to drop).
311
+ * `filterMode`: `visuallyHide` applies `visibility:hidden` CSS rule on filtered nodes and the layout remains as the original. `remove` do not clone filtered nodes at all.
308
312
 
309
313
  **Example: filter out elements with `display:none`:**
310
314
  ```js
@@ -345,7 +349,7 @@ await preCache({
345
349
 
346
350
  ### Cache control
347
351
 
348
- SnapDOM maintains internal caches for images, backgrounds, resources, styles, and fonts.
352
+ SnapDOM maintains internal caches for images, backgrounds, resources, styles, and fonts.
349
353
  You can control how they are cleared between captures using the `cache` option:
350
354
 
351
355
  | Mode | Description |
@@ -382,7 +386,7 @@ Values are **average capture time (ms)** → lower is better.
382
386
 
383
387
  ### Simple elements
384
388
 
385
- | Scenario | SnapDOM v1.9.10 | SnapDOM v1.9.9 | html2canvas | html-to-image |
389
+ | Scenario | SnapDOM current | SnapDOM v1.9.9 | html2canvas | html-to-image |
386
390
  | ------------------------ | --------------- | -------------- | ----------- | ------------- |
387
391
  | Small (200×100) | **0.5 ms** | 0.8 ms | 67.7 ms | 3.1 ms |
388
392
  | Modal (400×300) | **0.5 ms** | 0.8 ms | 75.5 ms | 3.6 ms |
@@ -394,7 +398,7 @@ Values are **average capture time (ms)** → lower is better.
394
398
 
395
399
  ### Complex elements
396
400
 
397
- | Scenario | SnapDOM v1.9.10 | SnapDOM v1.9.9 | html2canvas | html-to-image |
401
+ | Scenario | SnapDOM current | SnapDOM v1.9.9 | html2canvas | html-to-image |
398
402
  | ------------------------ | --------------- | -------------- | ----------- | ------------- |
399
403
  | Small (200×100) | **1.6 ms** | 3.3 ms | 68.0 ms | 14.3 ms |
400
404
  | Modal (400×300) | **2.9 ms** | 6.8 ms | 87.5 ms | 34.8 ms |
package/dist/snapdom.js CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  /*
3
3
  * snapdom
4
- * v.1.9.10
4
+ * v.1.9.12-dev.0
5
5
  * Author Juan Martin Muda
6
6
  * License MIT
7
7
  **/
@@ -167,10 +167,25 @@
167
167
  var _inflight = /* @__PURE__ */ new Map();
168
168
  var _errorCache = /* @__PURE__ */ new Map();
169
169
  function isSpecialURL(url) {
170
- return /^data:|^blob:|^about:blank$/.test(url);
170
+ return /^data:|^blob:|^about:blank$/i.test(url);
171
+ }
172
+ function isAlreadyProxied(url, useProxy) {
173
+ try {
174
+ const baseHref = typeof location !== "undefined" && location.href ? location.href : "http://localhost/";
175
+ const proxyBaseRaw = useProxy.includes("{url}") ? useProxy.split("{url}")[0] : useProxy;
176
+ const proxyBase = new URL(proxyBaseRaw || ".", baseHref);
177
+ const u = new URL(url, baseHref);
178
+ if (u.origin === proxyBase.origin) return true;
179
+ const sp = u.searchParams;
180
+ if (sp && (sp.has("url") || sp.has("target"))) return true;
181
+ } catch (e) {
182
+ }
183
+ return false;
171
184
  }
172
185
  function shouldProxy(url, useProxy) {
173
- if (!useProxy || isSpecialURL(url)) return false;
186
+ if (!useProxy) return false;
187
+ if (isSpecialURL(url)) return false;
188
+ if (isAlreadyProxied(url, useProxy)) return false;
174
189
  try {
175
190
  const base = typeof location !== "undefined" && location.href ? location.href : "http://localhost/";
176
191
  const u = new URL(url, base);
@@ -181,8 +196,19 @@
181
196
  }
182
197
  function applyProxy(url, useProxy) {
183
198
  if (!useProxy) return url;
184
- if (useProxy.includes("{url}")) return useProxy.replace("{url}", encodeURIComponent(url));
185
- const sep = useProxy.endsWith("?") ? "" : useProxy.includes("?") ? "&" : "?";
199
+ if (useProxy.includes("{url}")) {
200
+ return useProxy.replace("{urlRaw}", safeEncodeURI(url)).replace("{url}", encodeURIComponent(url));
201
+ }
202
+ if (/[?&]url=?$/.test(useProxy)) {
203
+ return `${useProxy}${encodeURIComponent(url)}`;
204
+ }
205
+ if (useProxy.endsWith("?")) {
206
+ return `${useProxy}url=${encodeURIComponent(url)}`;
207
+ }
208
+ if (useProxy.endsWith("/")) {
209
+ return `${useProxy}${safeEncodeURI(url)}`;
210
+ }
211
+ const sep = useProxy.includes("?") ? "&" : "?";
186
212
  return `${useProxy}${sep}url=${encodeURIComponent(url)}`;
187
213
  }
188
214
  function blobToDataURL(blob) {
@@ -212,6 +238,65 @@
212
238
  const errorTTL = (_c = options.errorTTL) != null ? _c : 8e3;
213
239
  const headers = options.headers || {};
214
240
  const silent = !!options.silent;
241
+ if (/^data:/i.test(url)) {
242
+ try {
243
+ if (as === "text") {
244
+ return { ok: true, data: String(url), status: 200, url, fromCache: false };
245
+ }
246
+ if (as === "dataURL") {
247
+ return {
248
+ ok: true,
249
+ data: String(url),
250
+ status: 200,
251
+ url,
252
+ fromCache: false,
253
+ mime: String(url).slice(5).split(";")[0] || ""
254
+ };
255
+ }
256
+ const [, meta = "", data = ""] = String(url).match(/^data:([^,]*),(.*)$/) || [];
257
+ const isBase64 = /;base64/i.test(meta);
258
+ const bin = isBase64 ? atob(data) : decodeURIComponent(data);
259
+ const bytes = new Uint8Array([...bin].map((c) => c.charCodeAt(0)));
260
+ const b = new Blob([bytes], { type: (meta || "").split(";")[0] || "" });
261
+ return { ok: true, data: b, status: 200, url, fromCache: false, mime: b.type || "" };
262
+ } catch (e2) {
263
+ return { ok: false, data: null, status: 0, url, fromCache: false, reason: "special_url_error" };
264
+ }
265
+ }
266
+ if (/^blob:/i.test(url)) {
267
+ try {
268
+ const resp = yield fetch(url);
269
+ if (!resp.ok) {
270
+ return { ok: false, data: null, status: resp.status, url, fromCache: false, reason: "http_error" };
271
+ }
272
+ const blob = yield resp.blob();
273
+ const mime = blob.type || resp.headers.get("content-type") || "";
274
+ if (as === "dataURL") {
275
+ const dataURL = yield blobToDataURL(blob);
276
+ return { ok: true, data: dataURL, status: resp.status, url, fromCache: false, mime };
277
+ }
278
+ if (as === "text") {
279
+ const text = yield blob.text();
280
+ return { ok: true, data: text, status: resp.status, url, fromCache: false, mime };
281
+ }
282
+ return { ok: true, data: blob, status: resp.status, url, fromCache: false, mime };
283
+ } catch (e2) {
284
+ return { ok: false, data: null, status: 0, url, fromCache: false, reason: "network" };
285
+ }
286
+ }
287
+ if (/^about:blank$/i.test(url)) {
288
+ if (as === "dataURL") {
289
+ return {
290
+ ok: true,
291
+ data: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==",
292
+ status: 200,
293
+ url,
294
+ fromCache: false,
295
+ mime: "image/png"
296
+ };
297
+ }
298
+ return { ok: true, data: as === "text" ? "" : new Blob([]), status: 200, url, fromCache: false };
299
+ }
215
300
  const key = makeKey(url, { as, timeout, useProxy, errorTTL });
216
301
  const e = _errorCache.get(key);
217
302
  if (e && e.until > Date.now()) {
@@ -241,7 +326,7 @@
241
326
  const resp = yield fetch(finalURL, { signal: ctrl.signal, credentials: cred, headers });
242
327
  if (!resp.ok) {
243
328
  const result = { ok: false, data: null, status: resp.status, url: finalURL, fromCache: false, reason: "http_error" };
244
- _errorCache.set(key, { until: Date.now() + errorTTL, result });
329
+ if (errorTTL > 0) _errorCache.set(key, { until: Date.now() + errorTTL, result });
245
330
  if (!silent) {
246
331
  const short = `${resp.status} ${resp.statusText || ""}`.trim();
247
332
  snapLogger.warnOnce(
@@ -266,7 +351,9 @@
266
351
  } catch (err) {
267
352
  const reason = err && typeof err === "object" && "name" in err && err.name === "AbortError" ? String(err.message || "").includes("timeout") ? "timeout" : "abort" : "network";
268
353
  const result = { ok: false, data: null, status: 0, url: finalURL, fromCache: false, reason };
269
- _errorCache.set(key, { until: Date.now() + errorTTL, result });
354
+ if (!/^blob:/i.test(url) && errorTTL > 0) {
355
+ _errorCache.set(key, { until: Date.now() + errorTTL, result });
356
+ }
270
357
  if (!silent) {
271
358
  const k = `${reason}:${as}:${new URL(url, (_b2 = location == null ? void 0 : location.href) != null ? _b2 : "http://localhost/").origin}`;
272
359
  const tips = reason === "timeout" ? `Timeout after ${timeout}ms. Consider increasing timeout or using a proxy for ${url}` : reason === "abort" ? `Request aborted while fetching ${as} ${url}` : `Network/CORS issue while fetching ${as} ${url}. A proxy may be required`;
@@ -956,19 +1043,27 @@
956
1043
  return node.cloneNode(true);
957
1044
  }
958
1045
  if (node.getAttribute("data-capture") === "exclude") {
959
- const spacer = document.createElement("div");
960
- const rect = node.getBoundingClientRect();
961
- spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
962
- return spacer;
1046
+ if (options.excludeMode === "visuallyHide") {
1047
+ const spacer = document.createElement("div");
1048
+ const rect = node.getBoundingClientRect();
1049
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
1050
+ return spacer;
1051
+ } else if (options.excludeMode === "remove") {
1052
+ return null;
1053
+ }
963
1054
  }
964
1055
  if (options.exclude && Array.isArray(options.exclude)) {
965
1056
  for (const selector of options.exclude) {
966
1057
  try {
967
1058
  if ((_a = node.matches) == null ? void 0 : _a.call(node, selector)) {
968
- const spacer = document.createElement("div");
969
- const rect = node.getBoundingClientRect();
970
- spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
971
- return spacer;
1059
+ if (options.excludeMode === "visuallyHide") {
1060
+ const spacer = document.createElement("div");
1061
+ const rect = node.getBoundingClientRect();
1062
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
1063
+ return spacer;
1064
+ } else if (options.excludeMode === "remove") {
1065
+ return null;
1066
+ }
972
1067
  }
973
1068
  } catch (err) {
974
1069
  console.warn(`Invalid selector in exclude option: ${selector}`, err);
@@ -978,10 +1073,14 @@
978
1073
  if (typeof options.filter === "function") {
979
1074
  try {
980
1075
  if (!options.filter(node)) {
981
- const spacer = document.createElement("div");
982
- const rect = node.getBoundingClientRect();
983
- spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
984
- return spacer;
1076
+ if (options.filterMode === "visuallyHide") {
1077
+ const spacer = document.createElement("div");
1078
+ const rect = node.getBoundingClientRect();
1079
+ spacer.style.cssText = `display:inline-block;width:${rect.width}px;height:${rect.height}px;visibility:hidden;`;
1080
+ return spacer;
1081
+ } else if (options.filterMode === "remove") {
1082
+ return null;
1083
+ }
985
1084
  }
986
1085
  } catch (err) {
987
1086
  console.warn("Error in filter function:", err);
@@ -2480,7 +2579,7 @@
2480
2579
  const families = new Set(
2481
2580
  Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
2482
2581
  );
2483
- yield ensureFontsReady(families, 5);
2582
+ yield ensureFontsReady(families, 2);
2484
2583
  }
2485
2584
  fontsCSS = yield embedCustomFonts({
2486
2585
  required,
@@ -2749,7 +2848,7 @@
2749
2848
  return "soft";
2750
2849
  }
2751
2850
  function createContext(options = {}) {
2752
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
2851
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
2753
2852
  const resolvedFormat = (_a = options.format) != null ? _a : "png";
2754
2853
  const cachePolicy = normalizeCachePolicy(options.cache);
2755
2854
  return {
@@ -2759,29 +2858,31 @@
2759
2858
  scale: (_d = options.scale) != null ? _d : 1,
2760
2859
  // DOM filters
2761
2860
  exclude: (_e = options.exclude) != null ? _e : [],
2762
- filter: (_f = options.filter) != null ? _f : null,
2861
+ excludeMode: (_f = options.excludeMode) != null ? _f : "visuallyHide",
2862
+ filter: (_g = options.filter) != null ? _g : null,
2863
+ filterMode: (_h = options.filterMode) != null ? _h : "visuallyHide",
2763
2864
  placeholders: options.placeholders !== false,
2764
2865
  // default true
2765
2866
  // Fuentes
2766
- embedFonts: (_g = options.embedFonts) != null ? _g : false,
2867
+ embedFonts: (_i = options.embedFonts) != null ? _i : false,
2767
2868
  iconFonts: Array.isArray(options.iconFonts) ? options.iconFonts : options.iconFonts ? [options.iconFonts] : [],
2768
2869
  localFonts: Array.isArray(options.localFonts) ? options.localFonts : [],
2769
- excludeFonts: (_h = options.excludeFonts) != null ? _h : void 0,
2770
- defaultImageUrl: (_i = options.defaultImageUrl) != null ? _i : void 0,
2870
+ excludeFonts: (_j = options.excludeFonts) != null ? _j : void 0,
2871
+ defaultImageUrl: (_k = options.defaultImageUrl) != null ? _k : void 0,
2771
2872
  /** Cache policy (disabled|full|auto|soft). Default: "soft" */
2772
2873
  /** @type {CachePolicy} */
2773
2874
  cache: cachePolicy,
2774
2875
  // Red
2775
2876
  useProxy: typeof options.useProxy === "string" ? options.useProxy : "",
2776
2877
  // Salida
2777
- width: (_j = options.width) != null ? _j : null,
2778
- height: (_k = options.height) != null ? _k : null,
2878
+ width: (_l = options.width) != null ? _l : null,
2879
+ height: (_m = options.height) != null ? _m : null,
2779
2880
  format: resolvedFormat,
2780
- type: (_l = options.type) != null ? _l : "svg",
2781
- quality: (_m = options.quality) != null ? _m : 0.92,
2782
- dpr: (_n = options.dpr) != null ? _n : window.devicePixelRatio || 1,
2783
- backgroundColor: (_o = options.backgroundColor) != null ? _o : ["jpg", "jpeg", "webp"].includes(resolvedFormat) ? "#ffffff" : null,
2784
- filename: (_p = options.filename) != null ? _p : "snapDOM"
2881
+ type: (_n = options.type) != null ? _n : "svg",
2882
+ quality: (_o = options.quality) != null ? _o : 0.92,
2883
+ dpr: (_p = options.dpr) != null ? _p : window.devicePixelRatio || 1,
2884
+ backgroundColor: (_q = options.backgroundColor) != null ? _q : ["jpg", "jpeg", "webp"].includes(resolvedFormat) ? "#ffffff" : null,
2885
+ filename: (_r = options.filename) != null ? _r : "snapDOM"
2785
2886
  // Plugins (reservado para futura activación)
2786
2887
  // plugins: normalizePlugins(...),
2787
2888
  };
@@ -2805,24 +2906,12 @@
2805
2906
  function toCanvas(url, options) {
2806
2907
  return __async(this, null, function* () {
2807
2908
  const { scale, dpr } = options;
2808
- const safari = isSafari();
2809
2909
  const img = new Image();
2810
2910
  img.crossOrigin = "anonymous";
2811
2911
  img.loading = "eager";
2812
2912
  img.decoding = "sync";
2813
2913
  img.src = url;
2814
- let tempSlot = null;
2815
- if (safari) {
2816
- tempSlot = document.createElement("div");
2817
- tempSlot.setAttribute("aria-hidden", "true");
2818
- tempSlot.style.cssText = "position:absolute;left:-99999px;top:0;width:0;height:0;overflow:hidden;opacity:0;pointer-events:none;contain:size layout style;";
2819
- document.body.appendChild(tempSlot);
2820
- tempSlot.appendChild(img);
2821
- }
2822
2914
  yield img.decode();
2823
- if (safari) {
2824
- yield new Promise((r) => setTimeout(r, 100));
2825
- }
2826
2915
  const width = img.naturalWidth * scale;
2827
2916
  const height = img.naturalHeight * scale;
2828
2917
  const canvas = document.createElement("canvas");
@@ -2833,12 +2922,6 @@
2833
2922
  const ctx = canvas.getContext("2d");
2834
2923
  if (dpr !== 1) ctx.scale(dpr, dpr);
2835
2924
  ctx.drawImage(img, 0, 0, width, height);
2836
- if (tempSlot && tempSlot.parentNode) {
2837
- try {
2838
- tempSlot.parentNode.removeChild(tempSlot);
2839
- } catch (e) {
2840
- }
2841
- }
2842
2925
  return canvas;
2843
2926
  });
2844
2927
  }
@@ -2901,9 +2984,20 @@
2901
2984
 
2902
2985
  // src/api/snapdom.js
2903
2986
  var INTERNAL_TOKEN = Symbol("snapdom.internal");
2987
+ var _safariWarmup = false;
2904
2988
  function snapdom(element, userOptions) {
2905
2989
  return __async(this, null, function* () {
2906
2990
  if (!element) throw new Error("Element cannot be null or undefined");
2991
+ if (isSafari()) {
2992
+ for (let i = 0; i < 3; i++) {
2993
+ try {
2994
+ yield safariWarmup(element, userOptions);
2995
+ console.log("Iteraci\xF3n n\xFAmero:", i);
2996
+ _safariWarmup = false;
2997
+ } catch (error) {
2998
+ }
2999
+ }
3000
+ }
2907
3001
  const context = createContext(userOptions);
2908
3002
  if (context.iconFonts && context.iconFonts.length > 0) extendIconFonts(context.iconFonts);
2909
3003
  if (!context.snap) {
@@ -2948,26 +3042,68 @@
2948
3042
  snapdom.toJpg = (el, options) => snapdom(el, __spreadProps(__spreadValues({}, options), { format: "jpeg" })).then((result) => result.toJpg());
2949
3043
  snapdom.toWebp = (el, options) => snapdom(el, __spreadProps(__spreadValues({}, options), { format: "webp" })).then((result) => result.toWebp());
2950
3044
  snapdom.download = (el, options) => snapdom(el, options).then((result) => result.download());
3045
+ function safariWarmup(element, baseOptions) {
3046
+ return __async(this, null, function* () {
3047
+ if (_safariWarmup) return;
3048
+ const preflight = __spreadProps(__spreadValues({}, baseOptions), {
3049
+ fast: true,
3050
+ embedFonts: true,
3051
+ scale: 0.2
3052
+ });
3053
+ let url;
3054
+ try {
3055
+ url = yield captureDOM(element, preflight);
3056
+ } catch (e) {
3057
+ return;
3058
+ }
3059
+ yield new Promise((resolve) => {
3060
+ const img = new Image();
3061
+ img.decoding = "sync";
3062
+ img.loading = "eager";
3063
+ img.style.position = "fixed";
3064
+ img.style.left = 0;
3065
+ img.style.top = 0;
3066
+ img.style.width = "10px";
3067
+ img.style.height = "10px";
3068
+ img.style.opacity = "0.01";
3069
+ img.style.transform = "translateZ(10px)";
3070
+ img.style.willChange = "transform,opacity;";
3071
+ img.src = url;
3072
+ const cleanup = () => __async(null, null, function* () {
3073
+ yield new Promise((r) => setTimeout(r, 100));
3074
+ if (img && img.parentNode) img.parentNode.removeChild(img);
3075
+ _safariWarmup = true;
3076
+ resolve();
3077
+ });
3078
+ document.body.appendChild(img);
3079
+ cleanup();
3080
+ });
3081
+ });
3082
+ }
2951
3083
 
2952
3084
  // src/api/preCache.js
2953
3085
  function preCache() {
2954
3086
  return __async(this, arguments, function* (root = document, options = {}) {
2955
- var _a;
3087
+ var _a, _b, _c, _d;
2956
3088
  const {
2957
3089
  embedFonts = true,
2958
- cacheOpt = "full",
2959
3090
  useProxy = ""
2960
3091
  } = options;
2961
- applyCachePolicy(cacheOpt);
3092
+ const cacheMode = (_b = (_a = options.cache) != null ? _a : options.cacheOpt) != null ? _b : "full";
3093
+ applyCachePolicy(cacheMode);
2962
3094
  try {
2963
- yield document.fonts.ready;
3095
+ yield (_c = document.fonts) == null ? void 0 : _c.ready;
3096
+ } catch (e) {
3097
+ }
3098
+ try {
3099
+ precacheCommonTags();
2964
3100
  } catch (e) {
2965
3101
  }
2966
- precacheCommonTags();
2967
3102
  cache.session = cache.session || {};
2968
3103
  if (!cache.session.styleCache) {
2969
3104
  cache.session.styleCache = /* @__PURE__ */ new WeakMap();
2970
3105
  }
3106
+ cache.image = cache.image || /* @__PURE__ */ new Map();
2971
3107
  try {
2972
3108
  yield inlineBackgroundImages(
2973
3109
  root,
@@ -2988,12 +3124,15 @@
2988
3124
  }
2989
3125
  const promises = [];
2990
3126
  for (const img of imgEls) {
2991
- const src = img == null ? void 0 : img.src;
3127
+ const src = (img == null ? void 0 : img.currentSrc) || (img == null ? void 0 : img.src);
2992
3128
  if (!src) continue;
2993
3129
  if (!cache.image.has(src)) {
2994
- const p = Promise.resolve().then(() => snapFetch(src, { as: "dataURL", useProxy })).then((dataURL) => {
2995
- cache.image.set(src, dataURL);
2996
- }).catch(() => {
3130
+ const p = Promise.resolve().then(() => __async(null, null, function* () {
3131
+ const res = yield snapFetch(src, { as: "dataURL", useProxy });
3132
+ if ((res == null ? void 0 : res.ok) && typeof res.data === "string") {
3133
+ cache.image.set(src, res.data);
3134
+ }
3135
+ })).catch(() => {
2997
3136
  });
2998
3137
  promises.push(p);
2999
3138
  }
@@ -3019,7 +3158,8 @@
3019
3158
  try {
3020
3159
  const required = collectUsedFontVariants(root);
3021
3160
  const usedCodepoints = collectUsedCodepoints(root);
3022
- if (typeof isSafari === "function" ? isSafari() : !!isSafari) {
3161
+ const safari = typeof isSafari === "function" ? isSafari() : !!isSafari;
3162
+ if (safari) {
3023
3163
  const families = new Set(
3024
3164
  Array.from(required).map((k) => String(k).split("__")[0]).filter(Boolean)
3025
3165
  );
@@ -3030,7 +3170,7 @@
3030
3170
  usedCodepoints,
3031
3171
  exclude: options.excludeFonts,
3032
3172
  localFonts: options.localFonts,
3033
- useProxy: (_a = options.useProxy) != null ? _a : useProxy
3173
+ useProxy: (_d = options.useProxy) != null ? _d : useProxy
3034
3174
  });
3035
3175
  } catch (e) {
3036
3176
  }