@zumer/snapdom 2.16.0 → 2.22.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zumer/snapdom",
3
- "version": "2.16.0",
3
+ "version": "2.22.0",
4
4
  "description": "Fast, modern alternative to html2canvas — captures HTML elements to images (PNG, JPG, SVG, WebP) with exceptional speed and accuracy.",
5
5
  "type": "module",
6
6
  "main": "./dist/snapdom.js",
@@ -33,9 +33,15 @@
33
33
  "compile": "node esbuild.config.mjs",
34
34
  "lint": "eslint src __tests__ --ext .js",
35
35
  "lint:fix": "eslint src __tests__ --ext .js --fix",
36
- "test": "npm run lint:fix && npx vitest run --browser.headless --reporter=verbose",
36
+ "test:types": "tsc --noEmit",
37
+ "test": "npm run lint:fix && npm run test:types && npx vitest run --browser.headless --reporter=verbose",
38
+ "test:firefox": "BROWSER=firefox npx vitest run --browser.headless --reporter=verbose",
39
+ "test:webkit": "BROWSER=webkit npx vitest run --browser.headless --reporter=verbose",
40
+ "test:full": "npm run lint:fix && npm run test:types && BROWSER=all npx vitest run --browser.headless --reporter=verbose",
41
+ "report:cross": "node scripts/cross-report.mjs",
37
42
  "test:coverage": "npx vitest run --browser.headless --coverage",
38
43
  "test:benchmark": "npx vitest bench --browser.headless --watch=false",
44
+ "site": "npm run compile && node scripts/serve-site.mjs",
39
45
  "bump:dry": "npx @zumerbox/bump -d",
40
46
  "bump": "npx @zumerbox/bump && npx @zumerbox/changelog",
41
47
  "build": "npm run compile && npm pack",
@@ -82,10 +88,14 @@
82
88
  "@eslint/js": "^9.36.0",
83
89
  "@vitest/browser": "^3.1.2",
84
90
  "@vitest/coverage-v8": "^3.1.2",
85
- "@zumer/snapdiff": "^0.1.1",
91
+ "@zumer/snapdiff": "^0.2.2",
86
92
  "esbuild": "^0.28.1",
87
93
  "eslint": "^9.36.0",
88
94
  "globals": "^16.4.0",
89
- "playwright": "^1.52.0"
95
+ "playwright": "^1.52.0",
96
+ "typescript": "^7.0.2"
97
+ },
98
+ "overrides": {
99
+ "vite": "^6"
90
100
  }
91
101
  }
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * snapDOM – ultra-fast DOM-to-image capture
3
- * TypeScript definitions (v1.9.14)
3
+ * TypeScript definitions (v2.16)
4
4
  *
5
5
  * Notes:
6
6
  * - Style compression is internal (no public option).
7
7
  * - Icon fonts are always embedded; `embedFonts` controls non-icon fonts only.
8
- * - This file preserves backward compatibility with earlier 1.9.x defs.
8
+ * - This file preserves backward compatibility with earlier defs.
9
9
  */
10
10
 
11
11
  /* =========================
@@ -27,6 +27,8 @@ export interface LocalFont {
27
27
  src: string; // URL or data: URL
28
28
  weight?: string | number;
29
29
  style?: string;
30
+ /** font-stretch as a percentage (e.g. 100). Default 100. */
31
+ stretchPct?: number;
30
32
  }
31
33
 
32
34
  export interface ExcludeFonts {
@@ -54,9 +56,9 @@ export interface SnapdomOptions {
54
56
  /** Target height of the export (keeps aspect if only one dimension is provided). */
55
57
  height?: number;
56
58
 
57
- /** Background fallback color (used esp. for JPEG). Default "#fff". */
59
+ /** Background fallback color. Default: `"#ffffff"` for JPEG/WebP, `null` (transparent) otherwise. */
58
60
  backgroundColor?: string;
59
- /** Quality for JPEG/WebP (0..1). Default 1. */
61
+ /** Quality for JPEG/WebP (0..1). Default 0.92. */
60
62
  quality?: number;
61
63
  /** Output format for capture/export helpers. Default "png". */
62
64
  format?: BlobType;
@@ -80,18 +82,50 @@ export interface SnapdomOptions {
80
82
  /** How to apply `filter` ("hide" or "remove"). Default "hide". */
81
83
  filterMode?: "hide" | "remove";
82
84
 
83
- /** outerTransforms the root: remove translate/rotate, keep scale/skew. */
85
+ /**
86
+ * Layout reconciliation: mount the styled clone in-document once, compare every node's
87
+ * box against the live DOM and pin only diverging sizes. Measurement over heuristics.
88
+ * Opt-in (adds one in-document layout of the clone). Default false.
89
+ */
90
+ reconcile?: boolean;
91
+
92
+ /**
93
+ * Memoizes repeated captures of this element: a scoped MutationObserver marks it dirty on
94
+ * external change, and an unchanged repeat capture returns the cached result without
95
+ * re-running the pipeline. Opt-in — costs a persistent observer per element. Without it,
96
+ * snapdom warns once (console.warn) if the same element is captured 3+ times within 2s.
97
+ * Default false.
98
+ */
99
+ burst?: boolean;
100
+
101
+ /**
102
+ * With `burst: true`, forces a fresh capture on this call for changes the automatic
103
+ * MutationObserver tracking can't see: canvas pixel draws, programmatic CSSOM edits
104
+ * (stylesheet.insertRule/deleteRule, cssRule.style.* on a rule rather than an element).
105
+ * Ignored without `burst: true`. Default false.
106
+ */
107
+ invalidate?: boolean;
108
+
109
+ /** outerTransforms the root: remove translate/rotate, keep scale/skew. Default true. */
84
110
  outerTransforms?: boolean;
85
111
  /**
86
- * Do not expand root bbox for shadows/blur/outline; also strip shadows/outline
87
- * from the cloned root to get a tight capture box.
112
+ * Expand root bbox for shadows/blur/outline instead of stripping them from the
113
+ * cloned root. Default false (root shadows/outline are stripped, blur bleed is
114
+ * still included).
88
115
  */
89
116
  outerShadows?: boolean;
90
117
 
118
+ /**
119
+ * Capture only a region instead of the full element: `'viewport'` (what the user
120
+ * currently sees) or a page-coordinate rect. Offscreen subtrees are pruned before
121
+ * styling/inlining, so this is faster than a full capture. Default null (no clip).
122
+ */
123
+ clip?: "viewport" | { x: number; y: number; width: number; height: number } | null;
124
+
91
125
  /**
92
126
  * Downsample inlined raster images to their visible resolution (display box × scale × dpr),
93
- * preserving the source codec (lossless PNG stays lossless). Opt-in; off by default — output is
94
- * byte-identical to omitting it.
127
+ * preserving the source codec (lossless PNG stays lossless). On by default; pass `false`
128
+ * to embed images verbatim.
95
129
  */
96
130
  compress?: boolean;
97
131
 
@@ -103,6 +137,23 @@ export interface SnapdomOptions {
103
137
  iconFonts?: IconFontMatcher | IconFontMatcher[];
104
138
  /** Skip specific non-icon fonts (by family/domain/subset). */
105
139
  excludeFonts?: ExcludeFonts;
140
+ /** Extra domains allowed for cross-origin font stylesheet fetches (e.g. self-hosted CDNs). */
141
+ fontStylesheetDomains?: string[];
142
+
143
+ /**
144
+ * Skip style properties when snapshotting computed styles (e.g. `/^--/` to exclude
145
+ * CSS variables on pages with thousands of custom props).
146
+ */
147
+ excludeStyleProps?: RegExp | ((prop: string) => boolean);
148
+
149
+ /** Safari warmup iterations for WebKit #219770 (1..3). Default 3. */
150
+ safariWarmupAttempts?: number;
151
+
152
+ /** Verbose diagnostics via console.warn. Default false. */
153
+ debug?: boolean;
154
+
155
+ /** Default filename (without extension) for download(). Default "snapDOM". */
156
+ filename?: string;
106
157
 
107
158
  /**
108
159
  * Fallback image when <img> fails to load.
@@ -205,6 +256,16 @@ export interface SnapdomPlugin {
205
256
  */
206
257
  defineExports?(context: CaptureContext): ExportMap | Promise<ExportMap>;
207
258
 
259
+ /**
260
+ * Per-node hook, called for every element while the clone is built (after exclude/filter,
261
+ * before built-in iframe/canvas/video/audio handling). First plugin returning a value wins:
262
+ * - Node → used as the finished clone for that node (mapped to source, box styles applied)
263
+ * - null → skip the node entirely
264
+ * - undefined → continue with the normal pipeline
265
+ * Runs on every node: keep checks cheap.
266
+ */
267
+ resolveNode?(node: Element, context: CaptureContext): Node | null | undefined | Promise<Node | null | undefined>;
268
+
208
269
  /** Runs ONCE after the FIRST successful export of this capture (good for cleanup). */
209
270
  afterSnap?(context: CaptureContext): void | Promise<void>;
210
271
  }
@@ -245,6 +306,12 @@ export interface CaptureResult {
245
306
  /** Canonical data URL of the SVG snapshot (when available). */
246
307
  url: string;
247
308
 
309
+ /** Returns the raw SVG data URL (same as `url`). */
310
+ toRaw(): string;
311
+
312
+ /** Run any registered export by name (core or plugin), e.g. `to("png")`. */
313
+ to(type: string, options?: any): Promise<any>;
314
+
248
315
  /**
249
316
  * @deprecated Use `toSvg()` for an <img> that renders the SVG snapshot.
250
317
  * Historical alias kept for compatibility.
@@ -301,6 +368,12 @@ export declare namespace snapdom {
301
368
 
302
369
  /** Shortcut helpers that run a one-off capture+export. */
303
370
 
371
+ /** Returns the raw SVG data URL of a one-off capture. */
372
+ function toRaw(
373
+ element: Element,
374
+ options?: SnapdomOptions
375
+ ): Promise<string>;
376
+
304
377
  /** @deprecated Returns an SVG <img>; prefer `toSvg`. */
305
378
  function toImg(
306
379
  element: Element,
@@ -327,12 +400,6 @@ export declare namespace snapdom {
327
400
  options?: SnapdomOptions
328
401
  ): Promise<HTMLImageElement>;
329
402
 
330
- function toJpeg(
331
- element: Element,
332
- options?: SnapdomOptions
333
- ): Promise<HTMLImageElement>;
334
-
335
- /** Alias for `toJpeg`. */
336
403
  function toJpg(
337
404
  element: Element,
338
405
  options?: SnapdomOptions