@zumer/snapdom 2.0.2 → 2.1.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.
Files changed (57) hide show
  1. package/README.md +122 -69
  2. package/dist/{modules/chunks/chunk-SSUBCN7X.js → plugins.mjs} +2 -2
  3. package/dist/preCache.mjs +10 -0
  4. package/dist/snapdom.js +6 -6
  5. package/dist/snapdom.mjs +6 -6
  6. package/package.json +5 -5
  7. package/dist/modules/chunks/chunk-3JLSSUO4.js +0 -7
  8. package/dist/modules/chunks/chunk-3PHM6WOF.js +0 -7
  9. package/dist/modules/chunks/chunk-3VYIPD3A.js +0 -7
  10. package/dist/modules/chunks/chunk-4E2QQYX5.js +0 -7
  11. package/dist/modules/chunks/chunk-4IERUYP4.js +0 -7
  12. package/dist/modules/chunks/chunk-4Z46XXMY.js +0 -10
  13. package/dist/modules/chunks/chunk-53XQJAU5.js +0 -7
  14. package/dist/modules/chunks/chunk-5ZWTRQ52.js +0 -10
  15. package/dist/modules/chunks/chunk-7427JF2H.js +0 -10
  16. package/dist/modules/chunks/chunk-ANSXOGKI.js +0 -7
  17. package/dist/modules/chunks/chunk-BF74J4A5.js +0 -8
  18. package/dist/modules/chunks/chunk-BUMT6T6O.js +0 -10
  19. package/dist/modules/chunks/chunk-CNTQFGEZ.js +0 -10
  20. package/dist/modules/chunks/chunk-CRBLWEX6.js +0 -10
  21. package/dist/modules/chunks/chunk-CS7DTJ7I.js +0 -7
  22. package/dist/modules/chunks/chunk-DTQFIIVX.js +0 -7
  23. package/dist/modules/chunks/chunk-EBDTZNMR.js +0 -7
  24. package/dist/modules/chunks/chunk-EVYDSB2B.js +0 -7
  25. package/dist/modules/chunks/chunk-EZMCZKDW.js +0 -7
  26. package/dist/modules/chunks/chunk-FQK3JDTN.js +0 -10
  27. package/dist/modules/chunks/chunk-FTKOXG2W.js +0 -7
  28. package/dist/modules/chunks/chunk-G4EP52KJ.js +0 -10
  29. package/dist/modules/chunks/chunk-GIYVHLCQ.js +0 -8
  30. package/dist/modules/chunks/chunk-GZX3IERM.js +0 -8
  31. package/dist/modules/chunks/chunk-LCE36WDF.js +0 -10
  32. package/dist/modules/chunks/chunk-MW6X4KTL.js +0 -7
  33. package/dist/modules/chunks/chunk-N2KKO64J.js +0 -10
  34. package/dist/modules/chunks/chunk-NM4NY5FQ.js +0 -7
  35. package/dist/modules/chunks/chunk-PZIG3IRP.js +0 -10
  36. package/dist/modules/chunks/chunk-Q2Z2CG2I.js +0 -7
  37. package/dist/modules/chunks/chunk-Q55H7S7M.js +0 -7
  38. package/dist/modules/chunks/chunk-QBJ6HQLA.js +0 -10
  39. package/dist/modules/chunks/chunk-RKOPBBFA.js +0 -10
  40. package/dist/modules/chunks/chunk-SMBRKOUP.js +0 -7
  41. package/dist/modules/chunks/chunk-T4JIPPZO.js +0 -7
  42. package/dist/modules/chunks/chunk-X6RBKLFD.js +0 -10
  43. package/dist/modules/chunks/chunk-Y7FY32AO.js +0 -7
  44. package/dist/modules/chunks/rasterize-34PCWURX.js +0 -7
  45. package/dist/modules/chunks/rasterize-JS5G2XHH.js +0 -7
  46. package/dist/modules/chunks/rasterize-WOXTJCMX.js +0 -7
  47. package/dist/modules/exporters/download.js +0 -7
  48. package/dist/modules/exporters/toBlob.js +0 -7
  49. package/dist/modules/exporters/toCanvas.js +0 -7
  50. package/dist/modules/exporters/toImg.js +0 -7
  51. package/dist/modules/exporters/toJpg.js +0 -7
  52. package/dist/modules/exporters/toPng.js +0 -7
  53. package/dist/modules/exporters/toSvg.js +0 -7
  54. package/dist/modules/exporters/toWebp.js +0 -7
  55. package/dist/modules/plugins.js +0 -7
  56. package/dist/modules/preCache.js +0 -7
  57. package/dist/modules/snapdom.js +0 -7
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  <img alt="NPM version" src="https://img.shields.io/npm/v/@zumer/snapdom?style=flat-square&label=Version">
10
10
  </a>
11
11
  <a href="https://www.npmjs.com/package/@zumer/snapdom">
12
- <img alt="NPM version" src="https://img.shields.io/npm/v/@zumer/snapdom/dev?style=flat-square&label=Dev">
12
+ <img alt="NPM weekly downloads" src="https://img.shields.io/npm/dw/@zumer/snapdom?style=flat-square&label=Downloads">
13
13
  </a>
14
14
  <a href="https://github.com/zumerlab/snapdom/graphs/contributors">
15
15
  <img alt="GitHub contributors" src="https://img.shields.io/github/contributors/zumerlab/snapdom?style=flat-square&label=Contributors">
@@ -50,15 +50,76 @@ It converts any DOM subtree into a self-contained representation that can be exp
50
50
  [https://snapdom.dev](https://snapdom.dev)
51
51
 
52
52
 
53
+ ## Quick Start
54
+
55
+ **Capture any DOM element to PNG in one line:**
56
+
57
+ ```js
58
+ import { snapdom } from '@zumer/snapdom';
59
+
60
+ const img = await snapdom.toPng(document.querySelector('#card'));
61
+ document.body.appendChild(img);
62
+ ```
63
+
64
+ **Reusable capture** (one clone, multiple exports):
65
+
66
+ ```js
67
+ const result = await snapdom(document.querySelector('#card'));
68
+ await result.toPng(); // → HTMLImageElement
69
+ await result.toSvg(); // → SVG as Image
70
+ await result.download({ format: 'jpg', filename: 'card.jpg' });
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Capture Flow
76
+
77
+ SnapDOM transforms your DOM element through these stages:
78
+
79
+ ```mermaid
80
+ flowchart LR
81
+ subgraph Input
82
+ A[DOM Element]
83
+ end
84
+
85
+ subgraph Capture
86
+ B[Clone] --> C[Styles & Pseudo]
87
+ C --> D[Images & Backgrounds]
88
+ D --> E[Fonts]
89
+ E --> F[SVG foreignObject]
90
+ end
91
+
92
+ subgraph Output
93
+ F --> G[data:image/svg+xml]
94
+ G --> H[toPng / toSvg / toBlob / download]
95
+ end
96
+
97
+ A --> B
98
+ ```
99
+
100
+ | Stage | What happens |
101
+ |-------|--------------|
102
+ | **Clone** | Deep clone with styles, Shadow DOM, iframes. Exclude/filter nodes. |
103
+ | **Styles & Pseudo** | Inline `::before`/`::after` as elements, resolve `counter()`/`counters()`. |
104
+ | **Images & Backgrounds** | Fetch and inline external images/backgrounds as data URLs. |
105
+ | **Fonts** | Embed `@font-face` (optional) and icon fonts. |
106
+ | **SVG** | Wrap clone in `<foreignObject>`, serialize to `data:image/svg+xml`. |
107
+ | **Export** | Convert SVG to PNG/JPG/WebP/Blob or trigger download. |
108
+
109
+ Plugin hooks: `beforeSnap` → `beforeClone` → `afterClone` → `beforeRender` → `afterRender` → `beforeExport` → `afterExport`.
110
+
111
+
53
112
  ## Table of Contents
54
113
 
114
+ - [Quick Start](#quick-start)
115
+ - [Capture Flow](#capture-flow)
55
116
  - [Installation](#installation)
56
117
  - [NPM / Yarn (stable)](#npm--yarn-stable)
57
118
  - [NPM / Yarn (dev builds)](#npm--yarn-dev-builds)
58
119
  - [CDN (stable)](#cdn-stable)
59
120
  - [CDN (dev builds)](#cdn-dev-builds)
60
- - [Build Outputs & Tree-Shaking](#build-outputs--tree-shaking)
61
- - [Basic usage](#basic-usage)
121
+ - [Build Outputs](#build-outputs--tree-shaking)
122
+ - [Usage](#usage)
62
123
  - [Reusable capture](#reusable-capture)
63
124
  - [One-step shortcuts](#one-step-shortcuts)
64
125
  - [API](#api)
@@ -144,68 +205,59 @@ yarn add @zumer/snapdom@dev
144
205
  </script>
145
206
  ```
146
207
 
147
- ## Build Outputs & Tree-Shaking
148
-
149
- SnapDOM ships multiple build variants, but using it is simple.
208
+ ## Build Outputs
150
209
 
151
- ### npm usage → ESM modular build (tree-shakeable)
152
-
153
- When you import SnapDOM in a project with a bundler:
210
+ | Variant | File | Use case |
211
+ |---------|------|----------|
212
+ | **ESM** (tree-shakeable) | `dist/snapdom.mjs` | Bundlers (Vite, webpack), `import` |
213
+ | **IIFE** (global) | `dist/snapdom.js` | Script tag, legacy `require` |
154
214
 
215
+ **Bundler (npm):**
155
216
  ```js
156
- import { snapdom } from '@zumer/snapdom';
157
- ```
158
-
159
- your environment automatically loads:
160
-
161
- ```sh
162
- dist/modules/snapdom.js
217
+ import { snapdom } from '@zumer/snapdom'; // → dist/snapdom.mjs
163
218
  ```
164
219
 
165
- This is the modular ESM build, enabling:
166
-
167
- - Tree-shaking
168
-
169
- - Code-splitting
170
-
171
- - Lazy loading of exporters (toPng, toJpg, toWebp, etc.)
172
-
173
- You do not need to configure anything; bundlers pick this build automatically.
174
-
175
- ### Script tag usage → Global build
176
-
220
+ **Script tag (CDN):**
177
221
  ```html
178
222
  <script src="https://unpkg.com/@zumer/snapdom/dist/snapdom.js"></script>
179
- <script>
180
- snapdom.toPng(document.body).then(img => {
181
- document.body.appendChild(img);
182
- });
183
- </script>
223
+ <script> snapdom.toPng(document.body).then(img => document.body.appendChild(img)); </script>
224
+ ```
225
+
226
+ **Subpath imports** (lighter bundle if you only need one):
227
+ ```js
228
+ import { preCache } from '@zumer/snapdom/preCache';
229
+ import { plugins } from '@zumer/snapdom/plugins';
184
230
  ```
185
231
 
186
- This loads the monolithic global build and exposes snapdom on window.
187
232
 
233
+ ## Usage
188
234
 
189
- ## Basic usage
235
+ | Pattern | When to use |
236
+ |---------|-------------|
237
+ | **Reusable** `snapdom(el)` | One clone → many exports (PNG + JPG + download). |
238
+ | **Shortcuts** `snapdom.toPng(el)` | Single export, less code. |
190
239
 
191
240
  ### Reusable capture
241
+
242
+ Capture once, export many times (no re-clone):
243
+
192
244
  ```js
193
245
  const el = document.querySelector('#target');
194
246
  const result = await snapdom(el);
195
247
 
196
248
  const img = await result.toPng();
197
249
  document.body.appendChild(img);
198
-
199
250
  await result.download({ format: 'jpg', filename: 'my-capture.jpg' });
200
251
  ```
201
252
 
202
253
  ### One-step shortcuts
254
+
255
+ Direct export when you need a single format:
256
+
203
257
  ```js
204
- const el = document.querySelector('#target');
205
258
  const png = await snapdom.toPng(el);
206
- document.body.appendChild(png);
207
-
208
259
  const blob = await snapdom.toBlob(el);
260
+ document.body.appendChild(png);
209
261
  ```
210
262
 
211
263
  ## API
@@ -527,17 +579,19 @@ const out = await snapdom(element, {
527
579
 
528
580
  ### Plugin Lifecycle Hooks
529
581
 
530
- | Hook | Purpose |
531
- | ------------------------------ | ------------------------------------------------------------------------------------ |
532
- | `beforeSnap(context)` | Before any clone/style work. Ideal for adjusting global capture options. |
533
- | `beforeClone(context)` | Before DOM cloning. Can modify live DOM (use carefully). |
534
- | `afterClone(context)` | After the element subtree has been cloned. Safe to modify styles in the cloned tree. |
535
- | `beforeRender(context)` | Right before SVG/dataURL serialization. |
536
- | `afterRender(context)` | After serialization (you can inspect `context.svgString` or `context.dataURL`). |
537
- | `beforeExport(context)` | Before each export call (`toPng`, `toSvg`, etc.). |
538
- | `afterExport(context, result)` | After each export call — can transform the returned result. |
539
- | `afterSnap(context)` | Runs **once**, after the **first export** finishes. Perfect for cleanup. |
540
- | `defineExports(context)` | Returns a map of **custom exporters**, e.g. `{ pdf: async (ctx, opts) => Blob }`. |
582
+ Hooks run in capture order (see [Capture Flow](#capture-flow)):
583
+
584
+ | Hook | Stage | Purpose |
585
+ |------|-------|---------|
586
+ | `beforeSnap` | Start | Adjust options before any work. |
587
+ | `beforeClone` | Pre-clone | Before DOM clone (modify live DOM carefully). |
588
+ | `afterClone` | Post-clone | Modify cloned tree safely (e.g. inject overlay). |
589
+ | `beforeRender` | Pre-serialize | Right before SVG → data URL. |
590
+ | `afterRender` | Post-serialize | Inspect `context.svgString` / `context.dataURL`. |
591
+ | `beforeExport` | Per export | Before each `toPng`, `toSvg`, etc. |
592
+ | `afterExport` | Per export | Transform returned result. |
593
+ | `afterSnap` | Once | After first export; cleanup. |
594
+ | `defineExports` | Setup | Add custom exporters (e.g. `toPdf`). |
541
595
 
542
596
  > Returned values from `afterExport` are chained to the next plugin (transform pipeline).
543
597
 
@@ -786,35 +840,30 @@ Feel free to share suggestions or feedback in [GitHub Discussions](https://githu
786
840
 
787
841
  ## Development
788
842
 
789
- To contribute or build snapDOM locally:
843
+ **Source layout:**
844
+ - `src/api/` – Public API (`snapdom`, `preCache`)
845
+ - `src/core/` – Capture pipeline, clone, prepare, plugins
846
+ - `src/modules/` – Images, fonts, pseudo-elements, backgrounds, SVG
847
+ - `src/exporters/` – toPng, toSvg, toBlob, etc.
848
+ - `dist/` – Build output (`snapdom.js`, `snapdom.mjs`, `preCache.mjs`, `plugins.mjs`)
790
849
 
850
+ **Build:**
791
851
  ```sh
792
- # Clone the repository
793
852
  git clone https://github.com/zumerlab/snapdom.git
794
853
  cd snapdom
795
-
796
- # Switch to dev branch
797
854
  git checkout dev
798
-
799
- # Install dependencies
800
855
  npm install
801
-
802
- # Compile the library (ESM, CJS, and minified versions)
803
856
  npm run compile
857
+ ```
804
858
 
805
- # Install playwright browsers (necessary for running tests)
806
- npx playwright install
807
-
808
- # Run tests
859
+ **Test:**
860
+ ```sh
861
+ npx playwright install # Required for browser tests
809
862
  npm test
810
-
811
- # Run Benchmarks
812
863
  npm run test:benchmark
813
864
  ```
814
865
 
815
- The main entry point is in `src/`, and output bundles are generated in the `dist/` folder.
816
-
817
- For detailed contribution guidelines, please see [CONTRIBUTING](https://github.com/zumerlab/snapdom/blob/main/CONTRIBUTING.md).
866
+ For detailed guidelines, see [CONTRIBUTING](https://github.com/zumerlab/snapdom/blob/main/CONTRIBUTING.md).
818
867
 
819
868
 
820
869
  ## Contributors
@@ -824,9 +873,12 @@ For detailed contribution guidelines, please see [CONTRIBUTING](https://github.c
824
873
  <a href="https://github.com/tinchox5" title="tinchox5"><img src="https://avatars.githubusercontent.com/u/11557901?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="tinchox5"/></a>
825
874
  <a href="https://github.com/Jarvis2018" title="Jarvis2018"><img src="https://avatars.githubusercontent.com/u/36788851?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="Jarvis2018"/></a>
826
875
  <a href="https://github.com/tarwin" title="tarwin"><img src="https://avatars.githubusercontent.com/u/646149?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="tarwin"/></a>
876
+ <a href="https://github.com/Amyuan23" title="Amyuan23"><img src="https://avatars.githubusercontent.com/u/25892910?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="Amyuan23"/></a>
877
+ <a href="https://github.com/airamhr9" title="airamhr9"><img src="https://avatars.githubusercontent.com/u/57371081?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="airamhr9"/></a>
878
+ <a href="https://github.com/FlavioLimaMindera" title="FlavioLimaMindera"><img src="https://avatars.githubusercontent.com/u/96424442?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="FlavioLimaMindera"/></a>
827
879
  <a href="https://github.com/jswhisperer" title="jswhisperer"><img src="https://avatars.githubusercontent.com/u/1177690?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="jswhisperer"/></a>
828
880
  <a href="https://github.com/K1ender" title="K1ender"><img src="https://avatars.githubusercontent.com/u/146767945?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="K1ender"/></a>
829
- <a href="https://github.com/Amyuan23" title="Amyuan23"><img src="https://avatars.githubusercontent.com/u/25892910?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="Amyuan23"/></a>
881
+ <a href="https://github.com/kohaiy" title="kohaiy"><img src="https://avatars.githubusercontent.com/u/15622127?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="kohaiy"/></a>
830
882
  <a href="https://github.com/17biubiu" title="17biubiu"><img src="https://avatars.githubusercontent.com/u/13295895?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="17biubiu"/></a>
831
883
  <a href="https://github.com/av01d" title="av01d"><img src="https://avatars.githubusercontent.com/u/6247646?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="av01d"/></a>
832
884
  <a href="https://github.com/CHOYSEN" title="CHOYSEN"><img src="https://avatars.githubusercontent.com/u/25995358?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="CHOYSEN"/></a>
@@ -837,13 +889,14 @@ For detailed contribution guidelines, please see [CONTRIBUTING](https://github.c
837
889
  <a href="https://github.com/sharuzzaman" title="sharuzzaman"><img src="https://avatars.githubusercontent.com/u/7421941?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="sharuzzaman"/></a>
838
890
  <a href="https://github.com/simon1uo" title="simon1uo"><img src="https://avatars.githubusercontent.com/u/60037549?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="simon1uo"/></a>
839
891
  <a href="https://github.com/titoBouzout" title="titoBouzout"><img src="https://avatars.githubusercontent.com/u/64156?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="titoBouzout"/></a>
892
+ <a href="https://github.com/ZiuChen" title="ZiuChen"><img src="https://avatars.githubusercontent.com/u/64892985?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="ZiuChen"/></a>
840
893
  <a href="https://github.com/harshasiddartha" title="harshasiddartha"><img src="https://avatars.githubusercontent.com/u/147021873?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="harshasiddartha"/></a>
894
+ <a href="https://github.com/karasHou" title="karasHou"><img src="https://avatars.githubusercontent.com/u/27048083?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="karasHou"/></a>
841
895
  <a href="https://github.com/jhbae200" title="jhbae200"><img src="https://avatars.githubusercontent.com/u/20170610?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="jhbae200"/></a>
842
896
  <a href="https://github.com/xiaobai-web715" title="xiaobai-web715"><img src="https://avatars.githubusercontent.com/u/81091224?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="xiaobai-web715"/></a>
843
897
  <a href="https://github.com/miusuncle" title="miusuncle"><img src="https://avatars.githubusercontent.com/u/7549857?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="miusuncle"/></a>
844
898
  <a href="https://github.com/rbbydotdev" title="rbbydotdev"><img src="https://avatars.githubusercontent.com/u/101137670?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="rbbydotdev"/></a>
845
899
  <a href="https://github.com/zhanghaotian2018" title="zhanghaotian2018"><img src="https://avatars.githubusercontent.com/u/169218899?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="zhanghaotian2018"/></a>
846
- <a href="https://github.com/kohaiy" title="kohaiy"><img src="https://avatars.githubusercontent.com/u/15622127?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="kohaiy"/></a>
847
900
  <a href="https://github.com/fu050409" title="fu050409"><img src="https://avatars.githubusercontent.com/u/46275354?v=4&s=100" style="border-radius:10px; width:60px; height:60px; object-fit:cover; margin:5px;" alt="fu050409"/></a>
848
901
  </p>
849
902
  <!-- CONTRIBUTORS:END -->
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * SnapDOM
3
- * v2.0.0
3
+ * v2.1.0
4
4
  * Author: Juan Martin Muda
5
5
  * License: MIT
6
6
  */
7
- var f=[];function c(n){if(!n)return null;if(Array.isArray(n)){let[t,o]=n;return typeof t=="function"?t(o):t}if(typeof n=="object"&&"plugin"in n){let{plugin:t,options:o}=n;return typeof t=="function"?t(o):t}return typeof n=="function"?n():n}function p(...n){let t=n.flat();for(let o of t){let i=c(o);i&&(f.some(r=>r&&r.name&&i.name&&r.name===i.name)||f.push(i))}}function l(n){return(n&&Array.isArray(n.plugins)?n.plugins:f)||f}async function g(n,t,o){let i=o,r=l(t);for(let u of r){let e=u&&typeof u[n]=="function"?u[n]:null;if(!e)continue;let s=await e(t,i);typeof s<"u"&&(i=s)}return i}async function y(n,t,o){let i=[],r=l(t);for(let u of r){let e=u&&typeof u[n]=="function"?u[n]:null;if(!e)continue;let s=await e(t,o);typeof s<"u"&&i.push(s)}return i}function m(){return f.slice()}function d(){f.length=0}function a(n){let t=[];if(Array.isArray(n))for(let o of n){let i=c(o);if(!i||!i.name)continue;let r=t.findIndex(u=>u&&u.name===i.name);r>=0&&t.splice(r,1),t.push(i)}for(let o of f)o&&o.name&&!t.some(i=>i.name===o.name)&&t.push(o);return Object.freeze(t)}function A(n,t,o=!1){return!n||n.plugins&&!o||(n.plugins=a(t)),n}function P(){return f.slice()}export{c as a,p as b,g as c,y as d,m as e,d as f,a as g,A as h,P as i};
7
+ var f=[];function c(n){if(!n)return null;if(Array.isArray(n)){let[t,o]=n;return typeof t=="function"?t(o):t}if(typeof n=="object"&&"plugin"in n){let{plugin:t,options:o}=n;return typeof t=="function"?t(o):t}return typeof n=="function"?n():n}function p(...n){let t=n.flat();for(let o of t){let i=c(o);i&&(f.some(r=>r&&r.name&&i.name&&r.name===i.name)||f.push(i))}}function l(n){return(n&&Array.isArray(n.plugins)?n.plugins:f)||f}async function g(n,t,o){let i=o,r=l(t);for(let u of r){let e=u&&typeof u[n]=="function"?u[n]:null;if(!e)continue;let s=await e(t,i);typeof s<"u"&&(i=s)}return i}async function y(n,t,o){let i=[],r=l(t);for(let u of r){let e=u&&typeof u[n]=="function"?u[n]:null;if(!e)continue;let s=await e(t,o);typeof s<"u"&&i.push(s)}return i}function m(){return f.slice()}function d(){f.length=0}function a(n){let t=[];if(Array.isArray(n))for(let o of n){let i=c(o);if(!i||!i.name)continue;let r=t.findIndex(u=>u&&u.name===i.name);r>=0&&t.splice(r,1),t.push(i)}for(let o of f)o&&o.name&&!t.some(i=>i.name===o.name)&&t.push(o);return Object.freeze(t)}function A(n,t,o=!1){return!n||n.plugins&&!o||(n.plugins=a(t)),n}function P(){return f.slice()}export{A as attachSessionPlugins,d as clearPlugins,P as getGlobalPlugins,a as mergePlugins,c as normalizePlugin,m as pluginsList,p as registerPlugins,y as runAll,g as runHook};
@@ -0,0 +1,10 @@
1
+ /*
2
+ * SnapDOM
3
+ * v2.1.0
4
+ * Author: Juan Martin Muda
5
+ * License: MIT
6
+ */
7
+ var f={image:new Map,background:new Map,resource:new Map,defaultStyle:new Map,baseStyle:new Map,computedStyle:new WeakMap,font:new Set,session:{styleMap:new Map,styleCache:new WeakMap,nodeMap:new Map}};function X(t="soft"){switch(f.session.__counterEpoch=(f.session.__counterEpoch||0)+1,t){case"auto":{f.session.styleMap=new Map,f.session.nodeMap=new Map;return}case"soft":{f.session.styleMap=new Map,f.session.nodeMap=new Map,f.session.styleCache=new WeakMap;return}case"full":return;case"disabled":{f.session.styleMap=new Map,f.session.nodeMap=new Map,f.session.styleCache=new WeakMap,f.computedStyle=new WeakMap,f.baseStyle=new Map,f.defaultStyle=new Map,f.image=new Map,f.background=new Map,f.resource=new Map,f.font=new Set;return}default:{f.session.styleMap=new Map,f.session.nodeMap=new Map,f.session.styleCache=new WeakMap;return}}}function N(t){let e=t.match(/url\((['"]?)(.*?)(\1)\)/);if(!e)return null;let n=e[2].trim();return n.startsWith("#")?null:n}function O(t){if(/%[0-9A-Fa-f]{2}/.test(t))return t;try{return encodeURI(t)}catch{return t}}function dt(t="[snapDOM]",{ttlMs:e=5*6e4,maxEntries:n=12}={}){let r=new Map,o=0;function i(s,u,c){if(o>=n)return;let m=Date.now();(r.get(u)||0)>m||(r.set(u,m+e),o++,s==="warn"&&console&&console.warn?console.warn(`${t} ${c}`):console&&console.error&&console.error(`${t} ${c}`))}return{warnOnce(s,u){i("warn",s,u)},errorOnce(s,u){i("error",s,u)},reset(){r.clear(),o=0}}}var Y=dt("[snapDOM]",{ttlMs:3*6e4,maxEntries:10}),j=new Map,W=new Map;function pt(t){return/^data:|^blob:|^about:blank$/i.test(t)}function ht(t,e){try{let n=typeof location<"u"&&location.href?location.href:"http://localhost/",r=e.includes("{url}")?e.split("{url}")[0]:e,o=new URL(r||".",n),i=new URL(t,n);if(i.origin===o.origin)return!0;let s=i.searchParams;if(s&&(s.has("url")||s.has("target")))return!0}catch{}return!1}function gt(t,e){if(!e||pt(t)||ht(t,e))return!1;try{let n=typeof location<"u"&&location.href?location.href:"http://localhost/",r=new URL(t,n);return typeof location<"u"?r.origin!==location.origin:!0}catch{return!!e}}function yt(t,e){if(!e)return t;if(e.includes("{url}"))return e.replace("{urlRaw}",O(t)).replace("{url}",encodeURIComponent(t));if(/[?&]url=?$/.test(e))return`${e}${encodeURIComponent(t)}`;if(e.endsWith("?"))return`${e}url=${encodeURIComponent(t)}`;if(e.endsWith("/"))return`${e}${O(t)}`;let n=e.includes("?")?"&":"?";return`${e}${n}url=${encodeURIComponent(t)}`}function J(t){return new Promise((e,n)=>{let r=new FileReader;r.onload=()=>e(String(r.result||"")),r.onerror=()=>n(new Error("read_failed")),r.readAsDataURL(t)})}function wt(t,e){return[e.as||"blob",e.timeout??3e3,e.useProxy||"",e.errorTTL??8e3,t].join("|")}async function R(t,e={}){let n=e.as??"blob",r=e.timeout??3e3,o=e.useProxy||"",i=e.errorTTL??8e3,s=e.headers||{},u=!!e.silent;if(/^data:/i.test(t))try{if(n==="text")return{ok:!0,data:String(t),status:200,url:t,fromCache:!1};if(n==="dataURL")return{ok:!0,data:String(t),status:200,url:t,fromCache:!1,mime:String(t).slice(5).split(";")[0]||""};let[,l="",d=""]=String(t).match(/^data:([^,]*),(.*)$/)||[],h=/;base64/i.test(l)?atob(d):decodeURIComponent(d),S=new Uint8Array([...h].map(A=>A.charCodeAt(0))),k=new Blob([S],{type:(l||"").split(";")[0]||""});return{ok:!0,data:k,status:200,url:t,fromCache:!1,mime:k.type||""}}catch{return{ok:!1,data:null,status:0,url:t,fromCache:!1,reason:"special_url_error"}}if(/^blob:/i.test(t))try{let l=await fetch(t);if(!l.ok)return{ok:!1,data:null,status:l.status,url:t,fromCache:!1,reason:"http_error"};let d=await l.blob(),y=d.type||l.headers.get("content-type")||"";return n==="dataURL"?{ok:!0,data:await J(d),status:l.status,url:t,fromCache:!1,mime:y}:n==="text"?{ok:!0,data:await d.text(),status:l.status,url:t,fromCache:!1,mime:y}:{ok:!0,data:d,status:l.status,url:t,fromCache:!1,mime:y}}catch{return{ok:!1,data:null,status:0,url:t,fromCache:!1,reason:"network"}}if(/^about:blank$/i.test(t))return n==="dataURL"?{ok:!0,data:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==",status:200,url:t,fromCache:!1,mime:"image/png"}:{ok:!0,data:n==="text"?"":new Blob([]),status:200,url:t,fromCache:!1};let c=wt(t,{as:n,timeout:r,useProxy:o,errorTTL:i}),m=W.get(c);if(m&&m.until>Date.now())return{...m.result,fromCache:!0};m&&W.delete(c);let p=j.get(c);if(p)return p;let g=gt(t,o)?yt(t,o):t,w=e.credentials;if(!w)try{let l=typeof location<"u"&&location.href?location.href:"http://localhost/",d=new URL(t,l);w=typeof location<"u"&&d.origin===location.origin?"include":"omit"}catch{w="omit"}let b=new AbortController,C=setTimeout(()=>b.abort("timeout"),r),a=(async()=>{try{let l=await fetch(g,{signal:b.signal,credentials:w,headers:s});if(!l.ok){let h={ok:!1,data:null,status:l.status,url:g,fromCache:!1,reason:"http_error"};if(i>0&&W.set(c,{until:Date.now()+i,result:h}),!u){let S=`${l.status} ${l.statusText||""}`.trim();Y.warnOnce(`http:${l.status}:${n}:${new URL(t,location?.href??"http://localhost/").origin}`,`HTTP error ${S} while fetching ${n} ${t}`)}return e.onError&&e.onError(h),h}if(n==="text")return{ok:!0,data:await l.text(),status:l.status,url:g,fromCache:!1};let d=await l.blob(),y=d.type||l.headers.get("content-type")||"";return n==="dataURL"?{ok:!0,data:await J(d),status:l.status,url:g,fromCache:!1,mime:y}:{ok:!0,data:d,status:l.status,url:g,fromCache:!1,mime:y}}catch(l){let d=l&&typeof l=="object"&&"name"in l&&l.name==="AbortError"?String(l.message||"").includes("timeout")?"timeout":"abort":"network",y={ok:!1,data:null,status:0,url:g,fromCache:!1,reason:d};if(!/^blob:/i.test(t)&&i>0&&W.set(c,{until:Date.now()+i,result:y}),!u){let h=`${d}:${n}:${new URL(t,location?.href??"http://localhost/").origin}`,S=d==="timeout"?`Timeout after ${r}ms. Consider increasing timeout or using a proxy for ${t}`:d==="abort"?`Request aborted while fetching ${n} ${t}`:`Network/CORS issue while fetching ${n} ${t}. A proxy may be required`;Y.errorOnce(h,S)}return e.onError&&e.onError(y),y}finally{clearTimeout(C),j.delete(c)}})();return j.set(c,a),a}async function T(t,e={}){if(/^((repeating-)?(linear|radial|conic)-gradient)\(/i.test(t)||t.trim()==="none")return t;let r=N(t);if(!r)return t;let o=O(r);if(f.background.has(o)){let i=f.background.get(o);return i?`url("${i}")`:"none"}try{let i=await R(o,{as:"dataURL",useProxy:e.useProxy});return i.ok?(f.background.set(o,i.data),`url("${i.data}")`):(f.background.set(o,null),"none")}catch{return f.background.set(o,null),"none"}}var Z=new Set(["meta","script","noscript","title","link","template"]),z=new Set(["meta","link","style","title","noscript","script","template","g","defs","use","marker","mask","clipPath","pattern","path","polygon","polyline","line","circle","ellipse","rect","filter","lineargradient","radialgradient","stop"]),St=["div","span","p","a","img","ul","li","button","input","select","textarea","label","section","article","header","footer","nav","main","aside","h1","h2","h3","h4","h5","h6","table","thead","tbody","tr","td","th"];function G(){for(let t of St){let e=String(t).toLowerCase();Z.has(e)||z.has(e)||tt(e)}}function tt(t){if(t=String(t).toLowerCase(),z.has(t)){let i={};return f.defaultStyle.set(t,i),i}if(f.defaultStyle.has(t))return f.defaultStyle.get(t);let e=document.getElementById("snapdom-sandbox");e||(e=document.createElement("div"),e.id="snapdom-sandbox",e.setAttribute("data-snapdom-sandbox","true"),e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.left="-9999px",e.style.top="-9999px",e.style.width="0px",e.style.height="0px",e.style.overflow="hidden",document.body.appendChild(e));let n=document.createElement(t);n.style.all="initial",e.appendChild(n);let r=getComputedStyle(n),o={};for(let i of r){if(xt(i))continue;let s=r.getPropertyValue(i);o[i]=s}return e.removeChild(n),f.defaultStyle.set(t,o),o}var bt=/(?:^|-)(animation|transition)(?:-|$)/i,Ct=/^(--|view-timeline|scroll-timeline|animation-trigger|offset-|position-try|app-region|interactivity|overlay|view-transition|-webkit-locale|-webkit-user-(?:drag|modify)|-webkit-tap-highlight-color|-webkit-text-security)$/i,kt=new Set(["cursor","pointer-events","touch-action","user-select","print-color-adjust","speak","reading-flow","reading-order","anchor-name","anchor-scope","container-name","container-type","timeline-scope"]);function xt(t){let e=String(t).toLowerCase();return!!(kt.has(e)||Ct.test(e)||bt.test(e))}function P(t,e=null){if(!(t instanceof Element))return window.getComputedStyle(t,e);let n=f.computedStyle.get(t);if(n||(n=new Map,f.computedStyle.set(t,n)),!n.has(e)){let r=window.getComputedStyle(t,e);n.set(e,r)}return n.get(e)}function K(t){let e=[],n=0,r=0;for(let o=0;o<t.length;o++){let i=t[o];i==="("&&n++,i===")"&&n--,i===","&&n===0&&(e.push(t.slice(r,o).trim()),r=o+1)}return e.push(t.slice(r).trim()),e}function v(){if(typeof navigator>"u")return!1;let t=navigator.userAgent||"",e=t.toLowerCase(),n=e.includes("safari")&&!e.includes("chrome")&&!e.includes("crios")&&!e.includes("fxios")&&!e.includes("android"),r=/applewebkit/i.test(t),o=/mobile/i.test(t),i=!/safari/i.test(t),s=r&&o&&i,u=/(micromessenger|wxwork|wecom|windowswechat|macwechat)/i.test(t),c=/(baiduboxapp|baidubrowser|baidusearch|baiduboxlite)/i.test(e),m=/ipad|iphone|ipod/.test(e)&&r;return n||s||u||c||m}var At=[/font\s*awesome/i,/material\s*icons/i,/ionicons/i,/glyphicons/i,/feather/i,/bootstrap\s*icons/i,/remix\s*icons/i,/heroicons/i,/layui/i,/lucide/i],ie=Object.assign({materialIconsFilled:"https://fonts.gstatic.com/s/materialicons/v48/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2",materialIconsOutlined:"https://fonts.gstatic.com/s/materialiconsoutlined/v110/gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2",materialIconsRound:"https://fonts.gstatic.com/s/materialiconsround/v109/LDItaoyNOAY6Uewc665JcIzCKsKc_M9flwmPq_HTTw.woff2",materialIconsSharp:"https://fonts.gstatic.com/s/materialiconssharp/v110/oPWQ_lt5nv4pWNJpghLP75WiFR4kLh3kvmvRImcycg.woff2"},typeof window<"u"&&window.__SNAPDOM_ICON_FONTS__||{}),$t=[];function M(t){let e=typeof t=="string"?t:"",n=[...At,...$t];for(let r of n)if(r instanceof RegExp&&r.test(e))return!0;return!!(/icon/i.test(e)||/glyph/i.test(e)||/symbols/i.test(e)||/feather/i.test(e)||/fontawesome/i.test(e))}var Rt=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","emoji","math","fangsong","ui-serif","ui-sans-serif","ui-monospace","ui-rounded"]),Mt=["katex","mathjax","mathml"];function V(t){if(!t)return"";for(let e of t.split(",")){let n=e.trim().replace(/^['"]+|['"]+$/g,"");if(n&&!Rt.has(n.toLowerCase()))return n}return""}function B(t){let e=String(t??"400").trim().toLowerCase();if(e==="normal")return 400;if(e==="bold")return 700;let n=parseInt(e,10);return Number.isFinite(n)?Math.min(900,Math.max(100,n)):400}function D(t){let e=String(t??"normal").trim().toLowerCase();return e.startsWith("italic")?"italic":e.startsWith("oblique")?"oblique":"normal"}function Lt(t){let e=String(t??"100%").match(/(\d+(?:\.\d+)?)\s*%/);return e?Math.max(50,Math.min(200,parseFloat(e[1]))):100}function Ft(t){let e=String(t||"400").trim(),n=e.match(/^(\d{2,3})\s+(\d{2,3})$/);if(n){let o=B(n[1]),i=B(n[2]);return{min:Math.min(o,i),max:Math.max(o,i)}}let r=B(e);return{min:r,max:r}}function Et(t){let e=String(t||"normal").trim().toLowerCase();return e==="italic"?{kind:"italic"}:e.startsWith("oblique")?{kind:"oblique"}:{kind:"normal"}}function Ut(t){let e=String(t||"100%").trim(),n=e.match(/(\d+(?:\.\d+)?)\s*%\s+(\d+(?:\.\d+)?)\s*%/);if(n){let i=parseFloat(n[1]),s=parseFloat(n[2]);return{min:Math.min(i,s),max:Math.max(i,s)}}let r=e.match(/(\d+(?:\.\d+)?)\s*%/),o=r?parseFloat(r[1]):100;return{min:o,max:o}}function _t(t,e){if(!t)return!1;try{let n=new URL(t,location.href);if(n.origin===location.origin)return!0;let o=n.host.toLowerCase();if(["fonts.googleapis.com","fonts.gstatic.com","use.typekit.net","p.typekit.net","kit.fontawesome.com","use.fontawesome.com"].some(u=>o.endsWith(u)))return!0;let s=(n.pathname+n.search).toLowerCase();if(/\bfont(s)?\b/.test(s)||/\.woff2?(\b|$)/.test(s)||Mt.some(u=>s.includes(u)))return!0;for(let u of e){let c=u.toLowerCase().replace(/\s+/g,"+"),m=u.toLowerCase().replace(/\s+/g,"-");if(s.includes(c)||s.includes(m))return!0}return!1}catch{return!1}}function It(t){let e=new Set;for(let n of t||[]){let r=String(n).split("__")[0]?.trim();r&&e.add(r)}return e}function et(t,e){return t&&t.replace(/url\(\s*(['"]?)([^)'"]+)\1\s*\)/g,(n,r,o)=>{let i=(o||"").trim();if(!i||/^data:|^blob:|^https?:|^file:|^about:/i.test(i))return n;let s=i;try{s=new URL(i,e||location.href).href}catch{}return`url("${s}")`})}var H=/@import\s+(?:url\(\s*(['"]?)([^)"']+)\1\s*\)|(['"])([^"']+)\3)([^;]*);/g,q=4;async function Ot(t,e,n){if(!t)return t;let r=new Set;function o(u,c){try{return new URL(u,c||location.href).href}catch{return u}}async function i(u,c,m=0){if(m>q)return console.warn(`[snapDOM] @import depth exceeded (${q}) at ${c}`),u;let p="",g=0,w;for(;w=H.exec(u);){p+=u.slice(g,w.index),g=H.lastIndex;let b=(w[2]||w[4]||"").trim(),C=o(b,c);if(r.has(C)){console.warn(`[snapDOM] Skipping circular @import: ${C}`);continue}r.add(C);let a="";try{let l=await R(C,{as:"text",useProxy:n,silent:!0});l.ok&&typeof l.data=="string"&&(a=l.data)}catch{}a?(a=et(a,C),a=await i(a,C,m+1),p+=`
8
+ /* inlined: ${C} */
9
+ ${a}
10
+ `):p+=w[0]}return p+=u.slice(g),p}let s=et(t,e||location.href);return s=await i(s,e||location.href,0),s}var ot=/url\((["']?)([^"')]+)\1\)/g,Tt=/@font-face[^{}]*\{[^}]*\}/g;function rt(t){if(!t)return[];let e=[],n=t.split(",").map(r=>r.trim()).filter(Boolean);for(let r of n){let o=r.match(/^U\+([0-9A-Fa-f?]+)(?:-([0-9A-Fa-f?]+))?$/);if(!o)continue;let i=o[1],s=o[2],u=c=>{if(!c.includes("?"))return parseInt(c,16);let m=parseInt(c.replace(/\?/g,"0"),16),p=parseInt(c.replace(/\?/g,"F"),16);return[m,p]};if(s){let c=u(i),m=u(s),p=Array.isArray(c)?c[0]:c,g=Array.isArray(m)?m[1]:m;e.push([Math.min(p,g),Math.max(p,g)])}else{let c=u(i);Array.isArray(c)?e.push([c[0],c[1]]):e.push([c,c])}}return e}function st(t,e){if(!e.length||!t||t.size===0)return!0;for(let n of t)for(let[r,o]of e)if(n>=r&&n<=o)return!0;return!1}function Q(t,e){let n=[];if(!t)return n;for(let r of t.matchAll(ot)){let o=(r[2]||"").trim();if(!(!o||o.startsWith("data:"))){if(!/^https?:/i.test(o))try{o=new URL(o,e||location.href).href}catch{}n.push(o)}}return n}async function at(t,e,n=""){let r=t;for(let o of t.matchAll(ot)){let i=N(o[0]);if(!i)continue;let s=i;if(!s.startsWith("http")&&!s.startsWith("data:"))try{s=new URL(s,e||location.href).href}catch{}if(!M(s)){if(f.resource?.has(s)){f.font?.add(s),r=r.replace(o[0],`url(${f.resource.get(s)})`);continue}if(!f.font?.has(s))try{let u=await R(s,{as:"dataURL",useProxy:n,silent:!0});if(u.ok&&typeof u.data=="string"){let c=u.data;f.resource?.set(s,c),f.font?.add(s),r=r.replace(o[0],`url(${c})`)}}catch{console.warn("[snapDOM] Failed to fetch font resource:",s)}}}return r}function Pt(t){if(!t.length)return null;let e=(u,c)=>t.some(([m,p])=>!(p<u||m>c)),n=e(0,255)||e(305,305),r=e(256,591)||e(7680,7935),o=e(880,1023),i=e(1024,1279);return e(7840,7929)||e(258,259)||e(416,417)||e(431,432)?"vietnamese":i?"cyrillic":o?"greek":r?"latin-ext":n?"latin":null}function nt(t={}){let e=new Set((t.families||[]).map(o=>String(o).toLowerCase())),n=new Set((t.domains||[]).map(o=>String(o).toLowerCase())),r=new Set((t.subsets||[]).map(o=>String(o).toLowerCase()));return(o,i)=>{if(e.size&&e.has(o.family.toLowerCase()))return!0;if(n.size)for(let s of o.srcUrls)try{if(n.has(new URL(s).host.toLowerCase()))return!0}catch{}if(r.size){let s=Pt(i);if(s&&r.has(s))return!0}return!1}}function vt(t){if(!t)return t;let e=/@font-face[^{}]*\{[^}]*\}/gi,n=new Set,r=[];for(let i of t.match(e)||[]){let s=i.match(/font-family:\s*([^;]+);/i)?.[1]||"",u=V(s),c=(i.match(/font-weight:\s*([^;]+);/i)?.[1]||"400").trim(),m=(i.match(/font-style:\s*([^;]+);/i)?.[1]||"normal").trim(),p=(i.match(/font-stretch:\s*([^;]+);/i)?.[1]||"100%").trim(),g=(i.match(/unicode-range:\s*([^;]+);/i)?.[1]||"").trim(),w=(i.match(/src\s*:\s*([^;}]+)[;}]/i)?.[1]||"").trim(),b=Q(w,location.href),C=b.length?b.map(l=>String(l).toLowerCase()).sort().join("|"):w.toLowerCase(),a=[String(u||"").toLowerCase(),c,m,p,g.toLowerCase(),C].join("|");n.has(a)||(n.add(a),r.push(i))}if(r.length===0)return t;let o=0;return t.replace(e,()=>r[o++]||"")}function Nt(t,e,n,r){let o=Array.from(t||[]).sort().join("|"),i=e?JSON.stringify({families:(e.families||[]).map(c=>String(c).toLowerCase()).sort(),domains:(e.domains||[]).map(c=>String(c).toLowerCase()).sort(),subsets:(e.subsets||[]).map(c=>String(c).toLowerCase()).sort()}):"",s=(n||[]).map(c=>`${(c.family||"").toLowerCase()}::${c.weight||"normal"}::${c.style||"normal"}::${c.src||""}`).sort().join("|");return`fonts-embed-css::req=${o}::ex=${i}::lf=${s}::px=${r||""}`}async function it(t,e,n,r){let o;try{o=t.cssRules||[]}catch{return}let i=(s,u)=>{try{return new URL(s,u||location.href).href}catch{return s}};for(let s of o){if(s.type===CSSRule.IMPORT_RULE&&s.styleSheet){let u=s.href?i(s.href,e):e;if(r.depth>=q){console.warn(`[snapDOM] CSSOM import depth exceeded (${q}) at ${u}`);continue}if(u&&r.visitedSheets.has(u)){console.warn(`[snapDOM] Skipping circular CSSOM import: ${u}`);continue}u&&r.visitedSheets.add(u);let c={...r,depth:(r.depth||0)+1};await it(s.styleSheet,u,n,c);continue}if(s.type===CSSRule.FONT_FACE_RULE){let u=(s.style.getPropertyValue("font-family")||"").trim(),c=V(u);if(!c||M(c))continue;let m=(s.style.getPropertyValue("font-weight")||"400").trim(),p=(s.style.getPropertyValue("font-style")||"normal").trim(),g=(s.style.getPropertyValue("font-stretch")||"100%").trim(),w=(s.style.getPropertyValue("src")||"").trim(),b=(s.style.getPropertyValue("unicode-range")||"").trim();if(!r.faceMatchesRequired(c,p,m,g))continue;let C=rt(b);if(!st(r.usedCodepoints,C))continue;let a={family:c,weightSpec:m,styleSpec:p,stretchSpec:g,unicodeRange:b,srcRaw:w,srcUrls:Q(w,e||location.href),href:e||location.href};if(r.simpleExcluder&&r.simpleExcluder(a,C))continue;if(/url\(/i.test(w)){let l=await at(w,e||location.href,r.useProxy);await n(`@font-face{font-family:${c};src:${l};font-style:${p};font-weight:${m};font-stretch:${g};${b?`unicode-range:${b};`:""}}`)}else await n(`@font-face{font-family:${c};src:${w};font-style:${p};font-weight:${m};font-stretch:${g};${b?`unicode-range:${b};`:""}}`)}}}async function ct({required:t,usedCodepoints:e,exclude:n=void 0,localFonts:r=[],useProxy:o=""}={}){t instanceof Set||(t=new Set),e instanceof Set||(e=new Set);let i=new Map;for(let a of t){let[l,d,y,h]=String(a).split("__");if(!l)continue;let S=i.get(l)||[];S.push({w:parseInt(d,10),s:y,st:parseInt(h,10)}),i.set(l,S)}function s(a,l,d,y){if(!i.has(a))return!1;let h=i.get(a),S=Ft(d),k=Et(l),A=Ut(y),F=S.min!==S.max,E=S.min,I=x=>k.kind==="normal"&&x==="normal"||k.kind!=="normal"&&(x==="italic"||x==="oblique"),U=!1;for(let x of h){let $=F?x.w>=S.min&&x.w<=S.max:x.w===E,L=I(D(x.s)),_=x.st>=A.min&&x.st<=A.max;if($&&L&&_){U=!0;break}}if(U)return!0;if(!F)for(let x of h){let $=I(D(x.s)),L=x.st>=A.min&&x.st<=A.max;if(Math.abs(E-x.w)<=300&&$&&L)return!0}if(!F&&k.kind==="normal"&&h.some($=>D($.s)!=="normal"))for(let $ of h){let L=Math.abs(E-$.w)<=300,_=$.st>=A.min&&$.st<=A.max;if(L&&_)return!0}return!1}let u=nt(n),c=Nt(t,n,r,o);if(f.resource?.has(c))return f.resource.get(c);let m=It(t),p=[],g=H;for(let a of document.querySelectorAll("style")){let l=a.textContent||"";for(let d of l.matchAll(g)){let y=(d[2]||d[4]||"").trim();if(!y||M(y))continue;!!document.querySelector(`link[rel="stylesheet"][href="${y}"]`)||p.push(y)}}p.length&&await Promise.all(p.map(a=>new Promise(l=>{if(document.querySelector(`link[rel="stylesheet"][href="${a}"]`))return l(null);let d=document.createElement("link");d.rel="stylesheet",d.href=a,d.setAttribute("data-snapdom","injected-import"),d.onload=()=>l(d),d.onerror=()=>l(null),document.head.appendChild(d)})));let w="",b=Array.from(document.querySelectorAll('link[rel="stylesheet"]')).filter(a=>!!a.href);for(let a of b)try{if(M(a.href))continue;let l="",d=!1;try{d=new URL(a.href,location.href).origin===location.origin}catch{}if(!d&&!_t(a.href,m))continue;if(d){let h=Array.from(document.styleSheets).find(S=>S.href===a.href);if(h)try{let S=h.cssRules||[];l=Array.from(S).map(k=>k.cssText).join("")}catch{}}if(!l){let h=await R(a.href,{as:"text",useProxy:o});if(h?.ok&&typeof h.data=="string"&&(l=h.data),M(a.href))continue}l=await Ot(l,a.href,o);let y="";for(let h of l.match(Tt)||[]){let S=(h.match(/font-family:\s*([^;]+);/i)?.[1]||"").trim(),k=V(S);if(!k||M(k))continue;let A=(h.match(/font-weight:\s*([^;]+);/i)?.[1]||"400").trim(),F=(h.match(/font-style:\s*([^;]+);/i)?.[1]||"normal").trim(),E=(h.match(/font-stretch:\s*([^;]+);/i)?.[1]||"100%").trim(),I=(h.match(/unicode-range:\s*([^;]+);/i)?.[1]||"").trim(),U=(h.match(/src\s*:\s*([^;}]+)[;}]/i)?.[1]||"").trim(),x=Q(U,a.href);if(!s(k,F,A,E))continue;let $=rt(I);if(!st(e,$))continue;let L={family:k,weightSpec:A,styleSpec:F,stretchSpec:E,unicodeRange:I,srcRaw:U,srcUrls:x,href:a.href};if(n&&u(L,$))continue;let _=/url\(/i.test(U)?await at(h,a.href,o):h;y+=_}y.trim()&&(w+=y)}catch{console.warn("[snapDOM] Failed to process stylesheet:",a.href)}let C={requiredIndex:i,usedCodepoints:e,faceMatchesRequired:s,simpleExcluder:n?nt(n):null,useProxy:o,visitedSheets:new Set,depth:0};for(let a of document.styleSheets)if(!(a.href&&b.some(l=>l.href===a.href)))try{let l=a.href||location.origin+"/";l&&C.visitedSheets.add(l),await it(a,l,async d=>{w+=d},C)}catch{}try{for(let a of document.fonts||[]){if(!a||!a.family||a.status!=="loaded"||!a._snapdomSrc)continue;let l=String(a.family).replace(/^['"]+|['"]+$/g,"");if(M(l)||!i.has(l)||n?.families&&n.families.some(y=>String(y).toLowerCase()===l.toLowerCase()))continue;let d=a._snapdomSrc;if(!String(d).startsWith("data:")){if(f.resource?.has(a._snapdomSrc))d=f.resource.get(a._snapdomSrc),f.font?.add(a._snapdomSrc);else if(!f.font?.has(a._snapdomSrc))try{let y=await R(a._snapdomSrc,{as:"dataURL",useProxy:o,silent:!0});if(y.ok&&typeof y.data=="string")d=y.data,f.resource?.set(a._snapdomSrc,d),f.font?.add(a._snapdomSrc);else continue}catch{console.warn("[snapDOM] Failed to fetch dynamic font src:",a._snapdomSrc);continue}}w+=`@font-face{font-family:'${l}';src:url(${d});font-style:${a.style||"normal"};font-weight:${a.weight||"normal"};}`}}catch{}for(let a of r){if(!a||typeof a!="object")continue;let l=String(a.family||"").replace(/^['"]+|['"]+$/g,"");if(!l||M(l)||!i.has(l)||n?.families&&n.families.some(A=>String(A).toLowerCase()===l.toLowerCase()))continue;let d=a.weight!=null?String(a.weight):"normal",y=a.style!=null?String(a.style):"normal",h=a.stretchPct!=null?`${a.stretchPct}%`:"100%",S=String(a.src||""),k=S;if(!k.startsWith("data:")){if(f.resource?.has(S))k=f.resource.get(S),f.font?.add(S);else if(!f.font?.has(S))try{let A=await R(S,{as:"dataURL",useProxy:o,silent:!0});if(A.ok&&typeof A.data=="string")k=A.data,f.resource?.set(S,k),f.font?.add(S);else continue}catch{console.warn("[snapDOM] Failed to fetch localFonts src:",S);continue}}w+=`@font-face{font-family:'${l}';src:url(${k});font-style:${y};font-weight:${d};font-stretch:${h};}`}return w&&(w=vt(w),f.resource?.set(c,w)),w}function lt(t){let e=new Set;if(!t)return e;let n=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT,null),r=s=>{let u=V(s.fontFamily);if(!u)return;let c=(m,p,g)=>`${u}__${B(m)}__${D(p)}__${Lt(g)}`;e.add(c(s.fontWeight,s.fontStyle,s.fontStretch))};r(getComputedStyle(t));let o=getComputedStyle(t,"::before");o&&o.content&&o.content!=="none"&&r(o);let i=getComputedStyle(t,"::after");for(i&&i.content&&i.content!=="none"&&r(i);n.nextNode();){let s=n.currentNode,u=getComputedStyle(s);r(u);let c=getComputedStyle(s,"::before");c&&c.content&&c.content!=="none"&&r(c);let m=getComputedStyle(s,"::after");m&&m.content&&m.content!=="none"&&r(m)}return e}function ft(t){let e=new Set,n=o=>{if(o)for(let i of o)e.add(i.codePointAt(0))},r=document.createTreeWalker(t,NodeFilter.SHOW_ELEMENT|NodeFilter.SHOW_TEXT,null);for(;r.nextNode();){let o=r.currentNode;if(o.nodeType===Node.TEXT_NODE)n(o.nodeValue||"");else if(o.nodeType===Node.ELEMENT_NODE){let i=o;for(let s of["::before","::after"]){let c=getComputedStyle(i,s)?.getPropertyValue("content");if(!(!c||c==="none"))if(/^"/.test(c)||/^'/.test(c))n(c.slice(1,-1));else{let m=c.match(/\\[0-9A-Fa-f]{1,6}/g);if(m)for(let p of m)try{e.add(parseInt(p.slice(1),16))}catch{}}}}}return e}async function ut(t,e=2){try{await document.fonts.ready}catch{}let n=Array.from(t||[]).filter(Boolean);if(n.length===0)return;let r=()=>{let o=document.createElement("div");o.style.cssText="position:absolute!important;left:-9999px!important;top:0!important;opacity:0!important;pointer-events:none!important;contain:layout size style;";for(let i of n){let s=document.createElement("span");s.textContent="AaBbGg1234\xC1\xC9\xCD\xD3\xDA\xE7\xF1\u2014\u221E",s.style.fontFamily=`"${i}"`,s.style.fontWeight="700",s.style.fontStyle="italic",s.style.fontSize="32px",s.style.lineHeight="1",s.style.whiteSpace="nowrap",s.style.margin="0",s.style.padding="0",o.appendChild(s)}document.body.appendChild(o),o.offsetWidth,document.body.removeChild(o)};for(let o=0;o<Math.max(1,e);o++)r(),await new Promise(i=>requestAnimationFrame(()=>requestAnimationFrame(i)))}async function mt(t,e,n,r={}){let o=[[t,e]],i=["background-image","mask","mask-image","-webkit-mask","-webkit-mask-image","mask-source","mask-box-image-source","mask-border-source","-webkit-mask-box-image-source","border-image","border-image-source"],s=["mask-position","mask-size","mask-repeat","-webkit-mask-position","-webkit-mask-size","-webkit-mask-repeat","mask-origin","mask-clip","-webkit-mask-origin","-webkit-mask-clip","-webkit-mask-position-x","-webkit-mask-position-y"],u=["background-position","background-position-x","background-position-y","background-size","background-repeat","background-origin","background-clip","background-attachment","background-blend-mode"],c=["border-image-slice","border-image-width","border-image-outset","border-image-repeat"];for(;o.length;){let[m,p]=o.shift();if(!p)continue;let g=n.get(m)||P(m);n.has(m)||n.set(m,g);let w=(()=>{let a=g.getPropertyValue("border-image"),l=g.getPropertyValue("border-image-source");return a&&a!=="none"||l&&l!=="none"})();for(let a of u){let l=g.getPropertyValue(a);l&&p.style.setProperty(a,l)}for(let a of i){let l=g.getPropertyValue(a);if(!l||l==="none")continue;let d=K(l),y=await Promise.all(d.map(h=>T(h,r)));y.some(h=>h&&h!=="none"&&!/^url\(undefined/.test(h))&&p.style.setProperty(a,y.join(", "))}for(let a of s){let l=g.getPropertyValue(a);!l||l==="initial"||p.style.setProperty(a,l)}if(w)for(let a of c){let l=g.getPropertyValue(a);!l||l==="initial"||p.style.setProperty(a,l)}let b=m.shadowRoot?Array.from(m.shadowRoot.children).filter(a=>a.tagName!=="STYLE"):Array.from(m.children),C=Array.from(p.children).filter(a=>!(a.dataset?.snapdomPseudo||a.tagName==="STYLE"&&a.dataset?.sd));for(let a=0;a<Math.min(b.length,C.length);a++)o.push([b[a],C[a]])}}async function Ce(t=document,e={}){let{embedFonts:n=!0,useProxy:r=""}=e,o=e.cache??e.cacheOpt??"full";X(o);try{await document.fonts?.ready}catch{}try{G()}catch{}f.session=f.session||{},f.session.styleCache||(f.session.styleCache=new WeakMap),f.image=f.image||new Map,f.background=f.background||new Map;try{await mt(t,void 0,f.session.styleCache,{useProxy:r})}catch{}let i=[],s=[];try{if(t&&t.nodeType===1){let c=t.querySelectorAll?Array.from(t.querySelectorAll("*")):[];s=[t,...c],i=[],t.tagName==="IMG"&&t.getAttribute("src")&&i.push(t),i.push(...Array.from(t.querySelectorAll?.("img[src]")||[]))}else t?.querySelectorAll&&(i=Array.from(t.querySelectorAll("img[src]")),s=Array.from(t.querySelectorAll("*")))}catch{}let u=[];for(let c of i){let m=c?.currentSrc||c?.src;if(m&&!f.image.has(m)){let p=Promise.resolve().then(async()=>{let g=await R(m,{as:"dataURL",useProxy:r});g?.ok&&typeof g.data=="string"&&f.image.set(m,g.data)}).catch(()=>{});u.push(p)}}for(let c of s){let m="";try{m=c?.style?.backgroundImage||"",(!m||m==="none")&&(m=P(c).backgroundImage)}catch{}if(m&&m!=="none"){let p=m.match(/url\((?:[^()"']+|"(?:[^"]*)"|'(?:[^']*)')\)/gi)||[];for(let g of p){let w=Promise.resolve().then(()=>T(g,{...e,useProxy:r})).catch(()=>{});u.push(w)}}}if(n)try{let c=lt(t),m=ft(t);if(typeof v=="function"?v():!!v){let g=new Set(Array.from(c).map(w=>String(w).split("__")[0]).filter(Boolean));await ut(g,3)}await ct({required:c,usedCodepoints:m,exclude:e.excludeFonts,localFonts:e.localFonts,useProxy:e.useProxy??r})}catch{}await Promise.allSettled(u)}export{Ce as preCache};