@zumer/snapdom 2.18.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.18.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,13 +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",
37
38
  "test:firefox": "BROWSER=firefox npx vitest run --browser.headless --reporter=verbose",
38
39
  "test:webkit": "BROWSER=webkit npx vitest run --browser.headless --reporter=verbose",
39
- "test:full": "npm run lint:fix && BROWSER=all 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",
40
41
  "report:cross": "node scripts/cross-report.mjs",
41
42
  "test:coverage": "npx vitest run --browser.headless --coverage",
42
43
  "test:benchmark": "npx vitest bench --browser.headless --watch=false",
44
+ "site": "npm run compile && node scripts/serve-site.mjs",
43
45
  "bump:dry": "npx @zumerbox/bump -d",
44
46
  "bump": "npx @zumerbox/bump && npx @zumerbox/changelog",
45
47
  "build": "npm run compile && npm pack",
@@ -90,7 +92,8 @@
90
92
  "esbuild": "^0.28.1",
91
93
  "eslint": "^9.36.0",
92
94
  "globals": "^16.4.0",
93
- "playwright": "^1.52.0"
95
+ "playwright": "^1.52.0",
96
+ "typescript": "^7.0.2"
94
97
  },
95
98
  "overrides": {
96
99
  "vite": "^6"
@@ -82,14 +82,46 @@ export interface SnapdomOptions {
82
82
  /** How to apply `filter` ("hide" or "remove"). Default "hide". */
83
83
  filterMode?: "hide" | "remove";
84
84
 
85
- /** 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. */
86
110
  outerTransforms?: boolean;
87
111
  /**
88
- * Do not expand root bbox for shadows/blur/outline; also strip shadows/outline
89
- * 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).
90
115
  */
91
116
  outerShadows?: boolean;
92
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
+
93
125
  /**
94
126
  * Downsample inlined raster images to their visible resolution (display box × scale × dpr),
95
127
  * preserving the source codec (lossless PNG stays lossless). On by default; pass `false`
@@ -224,6 +256,16 @@ export interface SnapdomPlugin {
224
256
  */
225
257
  defineExports?(context: CaptureContext): ExportMap | Promise<ExportMap>;
226
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
+
227
269
  /** Runs ONCE after the FIRST successful export of this capture (good for cleanup). */
228
270
  afterSnap?(context: CaptureContext): void | Promise<void>;
229
271
  }
@@ -358,12 +400,6 @@ export declare namespace snapdom {
358
400
  options?: SnapdomOptions
359
401
  ): Promise<HTMLImageElement>;
360
402
 
361
- function toJpeg(
362
- element: Element,
363
- options?: SnapdomOptions
364
- ): Promise<HTMLImageElement>;
365
-
366
- /** Alias for `toJpeg`. */
367
403
  function toJpg(
368
404
  element: Element,
369
405
  options?: SnapdomOptions