@zumer/snapdom 2.0.1 → 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.
- package/README.md +156 -73
- package/dist/{modules/chunks/chunk-DTQFIIVX.js → plugins.mjs} +2 -2
- package/dist/preCache.mjs +10 -0
- package/dist/snapdom.js +6 -6
- package/dist/snapdom.mjs +6 -6
- package/package.json +5 -5
- package/dist/modules/chunks/chunk-3JLSSUO4.js +0 -7
- package/dist/modules/chunks/chunk-3PHM6WOF.js +0 -7
- package/dist/modules/chunks/chunk-3VYIPD3A.js +0 -7
- package/dist/modules/chunks/chunk-4E2QQYX5.js +0 -7
- package/dist/modules/chunks/chunk-4IERUYP4.js +0 -7
- package/dist/modules/chunks/chunk-4Z46XXMY.js +0 -10
- package/dist/modules/chunks/chunk-53XQJAU5.js +0 -7
- package/dist/modules/chunks/chunk-5ZWTRQ52.js +0 -10
- package/dist/modules/chunks/chunk-ANSXOGKI.js +0 -7
- package/dist/modules/chunks/chunk-BF74J4A5.js +0 -8
- package/dist/modules/chunks/chunk-BUMT6T6O.js +0 -10
- package/dist/modules/chunks/chunk-CNTQFGEZ.js +0 -10
- package/dist/modules/chunks/chunk-CRBLWEX6.js +0 -10
- package/dist/modules/chunks/chunk-EBDTZNMR.js +0 -7
- package/dist/modules/chunks/chunk-FQK3JDTN.js +0 -10
- package/dist/modules/chunks/chunk-FTKOXG2W.js +0 -7
- package/dist/modules/chunks/chunk-G4EP52KJ.js +0 -10
- package/dist/modules/chunks/chunk-GZX3IERM.js +0 -8
- package/dist/modules/chunks/chunk-N2KKO64J.js +0 -10
- package/dist/modules/chunks/chunk-NM4NY5FQ.js +0 -7
- package/dist/modules/chunks/chunk-PZIG3IRP.js +0 -10
- package/dist/modules/chunks/chunk-Q55H7S7M.js +0 -7
- package/dist/modules/chunks/chunk-QBJ6HQLA.js +0 -10
- package/dist/modules/chunks/chunk-SSUBCN7X.js +0 -7
- package/dist/modules/chunks/chunk-T4JIPPZO.js +0 -7
- package/dist/modules/chunks/chunk-X6RBKLFD.js +0 -10
- package/dist/modules/chunks/rasterize-JS5G2XHH.js +0 -7
- package/dist/modules/chunks/rasterize-WOXTJCMX.js +0 -7
- package/dist/modules/exporters/download.js +0 -7
- package/dist/modules/exporters/toBlob.js +0 -7
- package/dist/modules/exporters/toCanvas.js +0 -7
- package/dist/modules/exporters/toImg.js +0 -7
- package/dist/modules/exporters/toJpg.js +0 -7
- package/dist/modules/exporters/toPng.js +0 -7
- package/dist/modules/exporters/toSvg.js +0 -7
- package/dist/modules/exporters/toWebp.js +0 -7
- package/dist/modules/plugins.js +0 -7
- package/dist/modules/preCache.js +0 -7
- 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
|
|
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
|
|
61
|
-
- [
|
|
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
|
|
148
|
-
|
|
149
|
-
SnapDOM ships multiple build variants, but using it is simple.
|
|
208
|
+
## Build Outputs
|
|
150
209
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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';
|
|
217
|
+
import { snapdom } from '@zumer/snapdom'; // → dist/snapdom.mjs
|
|
157
218
|
```
|
|
158
219
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
```sh
|
|
162
|
-
dist/modules/snapdom.js
|
|
163
|
-
```
|
|
164
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
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
|
-
await result.download({ format: 'jpg', filename: 'my-capture' });
|
|
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
|
|
@@ -242,9 +294,40 @@ Returns an object with reusable export methods:
|
|
|
242
294
|
| `snapdom.toWebp(el, options?)` | Returns a WebP image |
|
|
243
295
|
| `snapdom.download(el, options?)` | Triggers a download |
|
|
244
296
|
|
|
245
|
-
|
|
297
|
+
### Exporter-specific options
|
|
298
|
+
|
|
299
|
+
Some exporters accept a small set of **export-only options** in addition to the global capture options.
|
|
300
|
+
|
|
301
|
+
#### `download()`
|
|
302
|
+
|
|
303
|
+
| Option | Type | Default | Description |
|
|
304
|
+
| --- | --- | --- | --- |
|
|
305
|
+
| `filename` | `string` | `snapdom` | Download name. |
|
|
306
|
+
| `format` | `"png" \| "jpeg" \| "jpg" \| "webp" \| "svg"` | `"png"` | Output format for the downloaded file. |
|
|
307
|
+
|
|
308
|
+
**Example:**
|
|
309
|
+
|
|
310
|
+
```js
|
|
311
|
+
await result.download({
|
|
312
|
+
format: 'jpg',
|
|
313
|
+
quality: 0.92,
|
|
314
|
+
filename: 'my-capture'
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### `toBlob()`
|
|
319
|
+
|
|
320
|
+
| Option | Type | Default | Description |
|
|
321
|
+
| --- | --- | --- | --- |
|
|
322
|
+
| `type` | `"svg" \| "png" \| "jpeg" \| "jpg" \| "webp"` | `"svg"` | Blob type to generate. |
|
|
246
323
|
|
|
247
|
-
|
|
324
|
+
**Example:**
|
|
325
|
+
|
|
326
|
+
```js
|
|
327
|
+
const blob = await result.toBlob({ type: 'jpeg', quality: 0.92 });
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Options
|
|
248
331
|
|
|
249
332
|
All capture methods accept an `options` object:
|
|
250
333
|
|
|
@@ -263,7 +346,6 @@ All capture methods accept an `options` object:
|
|
|
263
346
|
| `backgroundColor` | string | `"#fff"` | Fallback color for JPG/WebP |
|
|
264
347
|
| `quality` | number | `1` | Quality for JPG/WebP (0 to 1) |
|
|
265
348
|
| `useProxy` | string | `''` | Proxy base for CORS fallbacks |
|
|
266
|
-
| `type` | string | `svg` | Default Blob type (`svg`\|`png`\|`jpg`\|`webp`) |
|
|
267
349
|
| `exclude` | string[] | - | CSS selectors to exclude |
|
|
268
350
|
| `excludeMode` | `"hide"`\|`"remove"` | `"hide"` | How `exclude` is applied |
|
|
269
351
|
| `filter` | function | - | Custom predicate `(el) => boolean` |
|
|
@@ -497,17 +579,19 @@ const out = await snapdom(element, {
|
|
|
497
579
|
|
|
498
580
|
### Plugin Lifecycle Hooks
|
|
499
581
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
|
503
|
-
|
|
504
|
-
| `
|
|
505
|
-
| `
|
|
506
|
-
| `
|
|
507
|
-
| `
|
|
508
|
-
| `
|
|
509
|
-
| `
|
|
510
|
-
| `
|
|
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`). |
|
|
511
595
|
|
|
512
596
|
> Returned values from `afterExport` are chained to the next plugin (transform pipeline).
|
|
513
597
|
|
|
@@ -756,35 +840,30 @@ Feel free to share suggestions or feedback in [GitHub Discussions](https://githu
|
|
|
756
840
|
|
|
757
841
|
## Development
|
|
758
842
|
|
|
759
|
-
|
|
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`)
|
|
760
849
|
|
|
850
|
+
**Build:**
|
|
761
851
|
```sh
|
|
762
|
-
# Clone the repository
|
|
763
852
|
git clone https://github.com/zumerlab/snapdom.git
|
|
764
853
|
cd snapdom
|
|
765
|
-
|
|
766
|
-
# Switch to dev branch
|
|
767
854
|
git checkout dev
|
|
768
|
-
|
|
769
|
-
# Install dependencies
|
|
770
855
|
npm install
|
|
771
|
-
|
|
772
|
-
# Compile the library (ESM, CJS, and minified versions)
|
|
773
856
|
npm run compile
|
|
857
|
+
```
|
|
774
858
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
# Run tests
|
|
859
|
+
**Test:**
|
|
860
|
+
```sh
|
|
861
|
+
npx playwright install # Required for browser tests
|
|
779
862
|
npm test
|
|
780
|
-
|
|
781
|
-
# Run Benchmarks
|
|
782
863
|
npm run test:benchmark
|
|
783
864
|
```
|
|
784
865
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
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).
|
|
788
867
|
|
|
789
868
|
|
|
790
869
|
## Contributors
|
|
@@ -794,9 +873,12 @@ For detailed contribution guidelines, please see [CONTRIBUTING](https://github.c
|
|
|
794
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>
|
|
795
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>
|
|
796
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>
|
|
797
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>
|
|
798
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>
|
|
799
|
-
<a href="https://github.com/
|
|
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>
|
|
800
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>
|
|
801
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>
|
|
802
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>
|
|
@@ -807,13 +889,14 @@ For detailed contribution guidelines, please see [CONTRIBUTING](https://github.c
|
|
|
807
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>
|
|
808
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>
|
|
809
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>
|
|
810
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>
|
|
811
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>
|
|
812
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>
|
|
813
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>
|
|
814
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>
|
|
815
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>
|
|
816
|
-
<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>
|
|
817
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>
|
|
818
901
|
</p>
|
|
819
902
|
<!-- CONTRIBUTORS:END -->
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* SnapDOM
|
|
3
|
-
* v2.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{
|
|
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};
|