### Changelog All notable changes to this project will be documented in this file. #### [v3.6.0](https://github.com/zumerlab/snapdom/compare/v3.5.0...v3.6.0) > 28 October 2026 **Features** - **engine:** ship html-in-canvas in the default build, with a guide [`8294802`](https://github.com/zumerlab/snapdom/commit/8294802cedd1d850573d57b369e2130667d9e490) - **stream:** add animations: false to stop following running animations [`932df5e`](https://github.com/zumerlab/snapdom/commit/932df5e7620ebcd9d5206d16fbd683383d77e0b3) **Performance** - **clone:** check the slice again after a shared pause [`aef63a0`](https://github.com/zumerlab/snapdom/commit/aef63a073b8466e35b3d375514232415d3b29fd6) **Docs** - add a plugins version badge to the READMEs [`3bf9489`](https://github.com/zumerlab/snapdom/commit/3bf9489774c89e771cd58dc624e2af35ddbe38ae) **Chores** - **parity:** launch the Chrome at CHROME_PATH when set [`c56f581`](https://github.com/zumerlab/snapdom/commit/c56f581a8a240f933b3a54ccd532e4fc99740772) #### [v3.5.0](https://github.com/zumerlab/snapdom/compare/v3.4.0...v3.5.0) > 27 October 2026 **Fixes** - **clip:** fold culled block siblings into one spacer per run [`#549`](https://github.com/zumerlab/snapdom/pull/549) - **prepare:** reset the capture root's self-alignment [`#548`](https://github.com/zumerlab/snapdom/pull/548) - **counter:** render none, disc, circle and square counter styles [`#547`](https://github.com/zumerlab/snapdom/pull/547) - **counter:** keep commas and parentheses inside the counters() separator [`#546`](https://github.com/zumerlab/snapdom/pull/546) - **background:** ignore parentheses inside quoted url() when splitting layers [`#545`](https://github.com/zumerlab/snapdom/pull/545) - **engine:** make html-in-canvas safe and as exact as the svg engine [`069bacf`](https://github.com/zumerlab/snapdom/commit/069bacf5928d0db295c2f3e024356c03f7b20f9b) - **images:** keep a failed image's box and warn on tainted canvases [`80f4898`](https://github.com/zumerlab/snapdom/commit/80f48980366ab199c102cae5acec38c3230815c9) - **fonts:** stop waiting on a Safari font set stuck at loading [`0e4b5dd`](https://github.com/zumerlab/snapdom/commit/0e4b5dd293c04dde4a8c6c360d06d66d52f8b91d) - **clip:** start a fractional clip on the output pixel grid [`f9d23d0`](https://github.com/zumerlab/snapdom/commit/f9d23d0eef7d473fc65033e0614f67691926342b) - **toCanvas:** wait for nested svg images before drawing on Firefox [`171350b`](https://github.com/zumerlab/snapdom/commit/171350b5fbae951465f7e9979bd5ceda411f810a) - **stream:** report only dirty rects inside the canvas [`f9302d4`](https://github.com/zumerlab/snapdom/commit/f9302d4bd8b76f4dcab81c83314778cf9074b2a3) - **stream:** keep a patch inside the ancestors that clip its host [`eed95f9`](https://github.com/zumerlab/snapdom/commit/eed95f9455160aba6501202688bf07b9c2b0c1a4) - **plugins:** export the ascii helpers from the barrel and type toStream [`de84e5c`](https://github.com/zumerlab/snapdom/commit/de84e5c965c78dd5b0147db4fac8b4c8889f8608) **Performance** - **fonts:** embed a near-weight face only where it can paint [`ad2bd88`](https://github.com/zumerlab/snapdom/commit/ad2bd8864c5ba312abe49d5d9d21cbd9b6486f1c) - **fonts:** leave out webfont families the page never drew [`59e0f8a`](https://github.com/zumerlab/snapdom/commit/59e0f8a625eb9f2b2c5a8e747645164ef1b29954) - **fonts:** warm only the font variants a Safari capture uses [`3e92aba`](https://github.com/zumerlab/snapdom/commit/3e92abaf3660f5fb7dcf63c2421c24ca4fff0278) **Docs** - **site:** shorter copy in one voice, SEO metadata [`84b1e3f`](https://github.com/zumerlab/snapdom/commit/84b1e3ffc2abcedd225fd47174579db1e6b8e678) - **labs:** add the html-in-canvas lab [`f7bb642`](https://github.com/zumerlab/snapdom/commit/f7bb642d83ece9f6efdca0825ab87bb7b2274650) - **site:** add a WebRTC overlay lab [`6dbc571`](https://github.com/zumerlab/snapdom/commit/6dbc571658a3e160ea15a09e8668c88c84d69eb1) - **how-to:** add the guide for images without CORS [`3cb73f2`](https://github.com/zumerlab/snapdom/commit/3cb73f292c290d954414bae650eeaedc74024dd6) - **site:** home hero as a camera, live stream demo [`cfa68d3`](https://github.com/zumerlab/snapdom/commit/cfa68d3c30db4fb1fe9fce6d1801fb712cfa04e0) - **labs:** ASCII mirror, stream chained with asciiFromCanvas [`f405001`](https://github.com/zumerlab/snapdom/commit/f405001b5d54df01b33ae1dd0c531cad03e697e4) - **how-to:** add the migration guide from html2canvas [`3472e84`](https://github.com/zumerlab/snapdom/commit/3472e8490c5609189c2102b95c1ca0f9cf68154e) - **site:** spinning CSS cube in the ASCII demo and the ASCII mirror lab [`ca8d8a4`](https://github.com/zumerlab/snapdom/commit/ca8d8a48f622afb251ada00376d1fdd63852979d) - **site:** one typeface, plain labels [`91ec7f6`](https://github.com/zumerlab/snapdom/commit/91ec7f65f5bbd4300ead000da551205a7631b855) - **seo:** llms.txt with common questions and comparisons [`90f5542`](https://github.com/zumerlab/snapdom/commit/90f5542b21b237431a2e719e30cd09cc2a583d7c) - **site:** import asciiStream from the published plugin in the ASCII lab [`d3df5a8`](https://github.com/zumerlab/snapdom/commit/d3df5a8f2090ecbc47f94782e094ef509a0f40ff) - **site:** red New pill on fresh demos in the sidebars [`6397060`](https://github.com/zumerlab/snapdom/commit/639706036e041b1f3f7429a41007783792baa051) - **site:** mark the video and WebRTC overlay labs as new [`d856131`](https://github.com/zumerlab/snapdom/commit/d8561316e211a67ad9fd25fab30b60ce6a1e799f) - **labs:** connect the WebRTC overlay lab on Safari after camera access [`9c6ce62`](https://github.com/zumerlab/snapdom/commit/9c6ce627a44d8c3e41f63a442d2bc6707e81bbe9) - **made-with:** add Open CDM and Meta2d.js [`30ad40a`](https://github.com/zumerlab/snapdom/commit/30ad40a484d57f9e0c51f3cff63bf8d921799664) - **site:** load the new plugins in the labs from unpkg, not esm.sh [`88a3322`](https://github.com/zumerlab/snapdom/commit/88a33222958a617353c5afaaccfd1bb8dad02ada) - align Chinese README and FEATURES with the new description [`ee4a73c`](https://github.com/zumerlab/snapdom/commit/ee4a73c38672b26d6bde9724459eda46b72c198e) - **site:** use the README hero as the link preview card [`c0dfbba`](https://github.com/zumerlab/snapdom/commit/c0dfbba850aaf525151bf1b39ef265e79ba65736) **Tests** - **pack:** list the stream files and the helper exports [`c9126ef`](https://github.com/zumerlab/snapdom/commit/c9126ef0665c7ff0b78e63c3d7604738e1a483b9) - **stream:** keep the runner's pointer out of the stream tests [`18ff2a1`](https://github.com/zumerlab/snapdom/commit/18ff2a15dfe84bd4f407fdc07ad941ab96f9ffa2) **Chores** - **publish:** give canvas-engine dev builds their own canvas tag [`ff51059`](https://github.com/zumerlab/snapdom/commit/ff510599aa01483f2ddbb7addbc322e73c45c4b7) - align package and README description with the site [`5936c95`](https://github.com/zumerlab/snapdom/commit/5936c9541a383fe740c42108db6dd8d3944fd30c) - update contributors list [`34e01ce`](https://github.com/zumerlab/snapdom/commit/34e01ce14ef92583623da27f99a6f0c928a9a3c4) - add thanks.dev to the funding channels [`01f77a2`](https://github.com/zumerlab/snapdom/commit/01f77a26910ffa4dabf26981c9451901f4f6204e) #### [v3.4.0](https://github.com/zumerlab/snapdom/compare/v3.3.7...v3.4.0) > 24 October 2026 ##### ✨ feat - feat: add snapdom.stream, a live canvas that repaints only what changed [`5ef8168`](https://github.com/zumerlab/snapdom/commit/5ef81689cbddb95c50575325c1141c973d88af03) - feat: export JPEG files beyond the canvas limit [`a595422`](https://github.com/zumerlab/snapdom/commit/a595422556912e244dd0c5d02243624b2a522c73) - feat(stream): add broadcast overlay templates [`85f0d31`](https://github.com/zumerlab/snapdom/commit/85f0d317db4c98790b6d43ff15e78a85c3c2e4da) - feat(debug): keep the console quiet unless debug is true [`91a95f5`](https://github.com/zumerlab/snapdom/commit/91a95f59fd720a1167210ee8a0bec91dd78fe329) - feat(stream): patch out-of-flow boxes that move or resize [`0eab5ca`](https://github.com/zumerlab/snapdom/commit/0eab5ca2499b964dc08096b3249c684240461f2c) - feat(engine): lay a capture root out at a subpixel offset on request [`59ddd11`](https://github.com/zumerlab/snapdom/commit/59ddd11d22080a379d9045478ce7fbd790f48fec) ##### 🛠 fix - fix(fonts): embed families whose name holds "__" [`#542`](https://github.com/zumerlab/snapdom/pull/542) - fix: right-to-left fidelity found by the new RTL demos [`193ab04`](https://github.com/zumerlab/snapdom/commit/193ab04bb29f8030c06a4803b71deae037a8c98e) - fix(icons): keep an icon font's share of the line in the clone [`09ebf09`](https://github.com/zumerlab/snapdom/commit/09ebf09562395b26ca5d36ec7daf2e6e79341031) - fix(svg): size a body capture from the body box, not the margins around it [`9bddee9`](https://github.com/zumerlab/snapdom/commit/9bddee95474c9da2521ea283b2037bae01f20adf) - fix: keep live-page mounts styled under a strict style-src CSP [`80313aa`](https://github.com/zumerlab/snapdom/commit/80313aa16c8417c75e697fb40720d8a2022902e1) - fix(toCanvas): keep emoji and late nested images in Safari exports [`3842f3e`](https://github.com/zumerlab/snapdom/commit/3842f3e0301e6984f7a7827b34b261f762bcb2eb) - fix(svg): place page-anchored boxes of a body capture where the page does [`c992d6e`](https://github.com/zumerlab/snapdom/commit/c992d6e9b72e827860780747ecdb0cf915662d75) - fix(styles): resolve oklch, lab and color() through a canvas for gradient text [`7aa2290`](https://github.com/zumerlab/snapdom/commit/7aa229032f2d34c4af0c26e456feb2a3f5264f0b) - fix(clone): capture opaque WebGL canvases that clear every frame [`49512cf`](https://github.com/zumerlab/snapdom/commit/49512cfc79004c7ac8de348ab9eacb0301bb0d78) - fix(prepare): top-align an atomic inline capture root [`e76e9d8`](https://github.com/zumerlab/snapdom/commit/e76e9d8e985fd42e4b3e1aa235a9ffdfe745da1c) - fix(toCanvas): keep 1px borders in downscaled Firefox exports at DPR 1 [`a3ee108`](https://github.com/zumerlab/snapdom/commit/a3ee10833efd537488b2cf41303b2276ff10555f) - fix(prepare): carry the capture root's language into the clone [`442f845`](https://github.com/zumerlab/snapdom/commit/442f845c3e7609cb7d76a0fd673a8c6bf04319d8) - fix(fetch): strip whitespace from the header of fetched data URLs [`b255f98`](https://github.com/zumerlab/snapdom/commit/b255f9890609d0ae9fef85293a2ed2b329ad5be6) - fix(svg): grow a right-to-left body capture on the side its content spills [`5de36e9`](https://github.com/zumerlab/snapdom/commit/5de36e942f399c0b307eec945ce6e0aa188a47ba) - fix(styles): never freeze the width of a MathML token [`1fc05b9`](https://github.com/zumerlab/snapdom/commit/1fc05b9c1587ff592e6aa8217d3e3fc7411958a7) - perf(stream): keep full frames from freezing the page [`ab4b6c4`](https://github.com/zumerlab/snapdom/commit/ab4b6c40d3cacde110f449fc4466ae75ab44d0bb) - fix(engine): give a __subpixel root its exact width at phase zero too [`0198ded`](https://github.com/zumerlab/snapdom/commit/0198dedd93cc54c81f8b36cbcf6e94b2f416d692) ##### 📦 other (chore/refactor/test/demo) - test(visual): load Orbit locally in d3-zumly and stamp a fixed text [`05fe871`](https://github.com/zumerlab/snapdom/commit/05fe871bf8bcf1b8f081332c9411587174ca45dc) - demo: add stream demos for WebGL textures, video overlays and a lab [`137546b`](https://github.com/zumerlab/snapdom/commit/137546ba6d154f1515c3864b392991fcaba42360) - refactor(stream): move the stream into @zumer/snapdom-plugins/stream [`eb6e990`](https://github.com/zumerlab/snapdom/commit/eb6e990601f68d7664095b389d66102f3bbabad6) - test: add a live parity check of every demo against the page [`0873b9d`](https://github.com/zumerlab/snapdom/commit/0873b9d5ea4e6aee8d142ba164350cc138d62b82) - test: cover counters, cross-origin font imports, clip fonts, selection, backdrop siblings and canvas retry [`938cc5c`](https://github.com/zumerlab/snapdom/commit/938cc5c3409b9f24aa0c4f76fbb81ee20c28378f) - demo(stream): bend live video through liquid glass overlay boxes [`5145eaf`](https://github.com/zumerlab/snapdom/commit/5145eaf937eeb7c671f90e7a9584bc6e2f3c559f) - demo(stream): place two live elements in a 3D virtual set [`d28eaa7`](https://github.com/zumerlab/snapdom/commit/d28eaa7698fe172bca96c5d60a6509859c2f24e1) - demo(stream): style the overlay templates with shader looks [`4287419`](https://github.com/zumerlab/snapdom/commit/42874195ac053e0a3737c7fc1c7dcd6fdf949a01) - demo(stream): send an HTML overlay inside a WebRTC video track [`8557f5e`](https://github.com/zumerlab/snapdom/commit/8557f5ef5e2b3d0cbb7053146339a2ea9d2a5dd6) - test(visual): serve Roboto locally to d21 and d25 [`824abab`](https://github.com/zumerlab/snapdom/commit/824abab21e87a03dc996059b968cbe8df5d61c81) - test(visual): add d-modern-css and d-text-layout demos [`654601b`](https://github.com/zumerlab/snapdom/commit/654601b7d9140078d2067f1f88f26f3094d4a18a) - demo(stream): a playground for the overlay templates [`f995bf4`](https://github.com/zumerlab/snapdom/commit/f995bf40144535b9b5c1090add0cc3b4ca9932ba) - chore(scripts): cut package.json scripts down to the release flow [`2de95bb`](https://github.com/zumerlab/snapdom/commit/2de95bb459310d0ad3ba9cb915bcac0818d79374) - test(visual): add d-rtl-body and d-rtl-layout demos [`6969b2e`](https://github.com/zumerlab/snapdom/commit/6969b2ec22356332dd9f6a6c0ea724617cd9fe5d) - chore(scripts): bring back publish:dev, test:coverage and cross:report [`37fba91`](https://github.com/zumerlab/snapdom/commit/37fba91f8115a3e5ae5201ffd8a96fdac7dc4b51) - test(engine): pin the __subpixel root layout in the core [`54aaf64`](https://github.com/zumerlab/snapdom/commit/54aaf64ce29cf8dd56045275d8e8ab478c7291c5) - test: stop two tests from failing under the full BROWSER=all run [`1b25c3d`](https://github.com/zumerlab/snapdom/commit/1b25c3da75ed784049269906f8af46faf1444b40) - test(visual): serve d24's fonts locally [`bd97b5d`](https://github.com/zumerlab/snapdom/commit/bd97b5db54e74c002d4e085c4003c185939f4732) - test: run four workers per engine under BROWSER=all [`462b243`](https://github.com/zumerlab/snapdom/commit/462b243e68dfa37bfff591e2b1596e4d097ed057) - test(parity): tolerate sub-pixel drift, time-box each demo [`6426184`](https://github.com/zumerlab/snapdom/commit/642618404370b512987d5b2cf3f9bcd39614e3ea) - chore(coverage): mark Firefox- and WebKit-only blocks with c8 ignore [`5c565cb`](https://github.com/zumerlab/snapdom/commit/5c565cba801861f67d7c37f8f6cf3adca0ffa358) - chore(plugins): require SnapDOM 3.3.8 for the stream [`ad3db94`](https://github.com/zumerlab/snapdom/commit/ad3db9413adb57c933d269a17b1e659482b4a454) - refactor(stream): allow form controls as patch hosts again [`b78f610`](https://github.com/zumerlab/snapdom/commit/b78f6108e8a326b91b5fa3b15701f28c6a0fdf92) - test(parity): wait for d60's own capture, note d11 and d42 [`44bb292`](https://github.com/zumerlab/snapdom/commit/44bb29219e6edccdec9b90961c0bb76113acbc58) - test: give the #531 stroked-text test 30 s for its WebKit screenshots [`d69ac62`](https://github.com/zumerlab/snapdom/commit/d69ac628ac70510ab2e06525745a2987471a94b2) - chore(scripts): leave the visual suites out of test:coverage [`5f6be3a`](https://github.com/zumerlab/snapdom/commit/5f6be3a1e579f080aaafba22435671f432f01e67) #### [v3.3.7](https://github.com/zumerlab/snapdom/compare/v3.3.6...v3.3.7) > 22 October 2026 - fix(export): keep WebP exports within the format's 16383px side limit (#536) [`#537`](https://github.com/zumerlab/snapdom/pull/537) - fix(prepare): resolve percentage min/max sizes on the capture root [`#533`](https://github.com/zumerlab/snapdom/pull/533) - fix(toCanvas): return the canvas with an identity transform [`#534`](https://github.com/zumerlab/snapdom/pull/534) - fix(safari): keep text-shadow on stroked text [`#531`](https://github.com/zumerlab/snapdom/pull/531) - fix(firefox): paint background-clip: text gradients [`#530`](https://github.com/zumerlab/snapdom/pull/530) - fix(lineClamp): keep every clamped line with a fractional line height [`#529`](https://github.com/zumerlab/snapdom/pull/529) - fix(clone): keep a textarea's live size in the clone [`#528`](https://github.com/zumerlab/snapdom/pull/528) - fix(clone): copy SVG geometry set by CSS rules (#535) [`f320c1a`](https://github.com/zumerlab/snapdom/commit/f320c1a835536b1f7a417df00240e2c1b3e39c86) - docs(site): align the rest of the site with the new pitch [`ad2c112`](https://github.com/zumerlab/snapdom/commit/ad2c11258457353970e3741e1f7f920bf1b490ac) - fix(diff): detect filtered nth and imported sibling rules (#539) [`9713933`](https://github.com/zumerlab/snapdom/commit/9713933ab1262c4625382993d94b32841261747d) - test(export): cover dpr and type alias in the WebP limit, skip without a WebP encoder (#536) [`fead291`](https://github.com/zumerlab/snapdom/commit/fead291a70970c8dfa95d80418c3a5f317a0ef4a) #### [v3.3.6](https://github.com/zumerlab/snapdom/compare/v3.3.5...v3.3.6) > 19 October 2026 - fix(svg): only apply devicePixelRatio layout zoom when the page lays out on the device grid [`#526`](https://github.com/zumerlab/snapdom/pull/526) - fix(toCanvas): crop layered content correctly on WebKit [`#527`](https://github.com/zumerlab/snapdom/pull/527) - chore: update vitest and related dependencies to version 4.1.12; configure vitest to use playwright as the browser provider [`eb3e658`](https://github.com/zumerlab/snapdom/commit/eb3e658282f008ce66d7e4f4ffd641b28316eee8) - Add new PNG assets for "weizwz" and "xun082" to the documentation [`fa7e3d2`](https://github.com/zumerlab/snapdom/commit/fa7e3d2a0334d529e78144fd8c7b018bf015f60f) - Refactor code structure for improved readability and maintainability [`a74c682`](https://github.com/zumerlab/snapdom/commit/a74c68254d3247b1bccd980cfdc9ee963571d452) - Add ink-aware clip culling tests (#525) and improve ink reach logic in clone [`d662c21`](https://github.com/zumerlab/snapdom/commit/d662c2170082615e1e4adca7e79d7d5737aad199) - refactor(svg): drop the public layoutZoom option [`783f684`](https://github.com/zumerlab/snapdom/commit/783f6849ce613cac59960d1a835993bd29eb7788) - Add tests for the ::before/::after rule without content and improve pseudo-element generation logic in the cloning function. [`d14b2bd`](https://github.com/zumerlab/snapdom/commit/d14b2bddfa85742813014d1de11799922beaa8d2) #### [v3.3.5](https://github.com/zumerlab/snapdom/compare/v3.3.4...v3.3.5) > 17 October 2026 - fix(reconcile): measure without upgrading page custom elements [`#523`](https://github.com/zumerlab/snapdom/pull/523) - fix(clip): re-anchor a fixed outer <svg> like a fixed HTML box [`#522`](https://github.com/zumerlab/snapdom/pull/522) - perf: release the idle decode iframe, cheaper reconcile walk [`6822e82`](https://github.com/zumerlab/snapdom/commit/6822e826e0e5910c3c6e567b501aa18045939ff6) - fix(styles): read cross-origin sheets through a fetched copy [`3592434`](https://github.com/zumerlab/snapdom/commit/35924344ab28c3d15f1d837795250e59f95f29db) - fix(styles): keep frozen heights from losing 1/64px in Chromium [`36e7e29`](https://github.com/zumerlab/snapdom/commit/36e7e29913c54e2bf6df6455740c9a2f37401264) - docs: note that download() uses DPR 1 and scale sets its resolution [`793500b`](https://github.com/zumerlab/snapdom/commit/793500bcb20f6e7f8a5345cbbbfec6a0b9cf21b3) #### [v3.3.4](https://github.com/zumerlab/snapdom/compare/v3.3.3...v3.3.4) > 13 October 2026 - fix(flex): preserve subpixel overflow [`e1fbac7`](https://github.com/zumerlab/snapdom/commit/e1fbac75bf2579204e24252288e51f9f1a1a02c7) - fix(firefox): preserve justified text size [`9834923`](https://github.com/zumerlab/snapdom/commit/98349234e8875ad0525278c8f93bd44483e8d4c1) - fix(flex): keep overflowing flex items at their live width (#520) [`4c47d70`](https://github.com/zumerlab/snapdom/commit/4c47d70ed597d90cde32392266b31a977be925d6) - fix(styles): preserve used border widths [`875fb3f`](https://github.com/zumerlab/snapdom/commit/875fb3fd8e9ac09c33396c0ba0fb870abe6ff313) - fix: handle detached links in ancestor walks (#519) [`294dae5`](https://github.com/zumerlab/snapdom/commit/294dae56e856ca19496f8f118ff9ffb81e210d52) #### [v3.3.3](https://github.com/zumerlab/snapdom/compare/v3.3.0...v3.3.3) > 9 October 2026 - feat(vector): improve SVG export by omitting inactive mask longhands and retaining active masks [`12a197c`](https://github.com/zumerlab/snapdom/commit/12a197cd5d5a1aa97d486f7e3006596735ae804e) - fix: preserve positioned content in scrolled captures [`84096ea`](https://github.com/zumerlab/snapdom/commit/84096ea66b28a7b6521bacb51993c381a636e7c2) - chore(plugins): update to version 4.0.1, add GitHub Sponsors metadata, and enhance release scripts [`a9e72f8`](https://github.com/zumerlab/snapdom/commit/a9e72f886a467977ab9ec5a5f239d7a3804639e3) - chore(plugins): add funding and require SnapDOM 3.3.0 [`61e7ff5`](https://github.com/zumerlab/snapdom/commit/61e7ff5e3e15e7e6fd2097a084b542b2972a04db) - chore(plugins): update to version 4.0.1 and add plugin bumping scripts [`1fbe3d9`](https://github.com/zumerlab/snapdom/commit/1fbe3d9cc76abc878eb202d9685366a5f3fc7a89) #### [v3.3.0](https://github.com/zumerlab/snapdom/compare/v3.2.0...v3.3.0) > 4 October 2026 ##### ✨ feat - feat: add editable vector export and enhance PDF capabilities [`019603a`](https://github.com/zumerlab/snapdom/commit/019603ad0c63fbcbf8000fff84afff0f3b5b1f30) - feat(docs): refresh navigation and live demos [`bbc59da`](https://github.com/zumerlab/snapdom/commit/bbc59da6894f6382dad8c395adb653d551d6b6e1) - feat(plugins): add open-source vector export [`299c561`](https://github.com/zumerlab/snapdom/commit/299c56168d03911eeb59022c6a7695edebf7bd79) - feat: improve plugin export contracts [`b828762`](https://github.com/zumerlab/snapdom/commit/b82876263fd2201d35a5023fe57c1bcecc4dd7be) - feat: replace pdf-image with full PDF export [`8acda94`](https://github.com/zumerlab/snapdom/commit/8acda94672c91bbd06cc70fb87dc574f1fc30346) ##### 🛠 fix - fix: one [SnapDOM] prefix and plain-language console messages [`bbde42f`](https://github.com/zumerlab/snapdom/commit/bbde42f8dad31b523b64b2f6ca89adbb17b2245a) - fix: center checkbox and radio replacements in a stretched box [`#516`](https://github.com/zumerlab/snapdom/pull/516) - fix: halve Firefox grid rasters before the dpr 1 downscale [`#516`](https://github.com/zumerlab/snapdom/pull/516) - fix: rasterize Firefox exports below the layout grid at the grid (#516) [`817390e`](https://github.com/zumerlab/snapdom/commit/817390ea47e26b1e9708b1a7778eb136e0f94528) - fix: keep one-line boxes from wrapping in the capture (#516) [`575537e`](https://github.com/zumerlab/snapdom/commit/575537e936a6511c80a2735a7c4a4dbc0914d389) - fix: capture text at its inflated size in Firefox for Android (#516) [`5213172`](https://github.com/zumerlab/snapdom/commit/52131728799c705782788f8f967425a66f7bf16c) - fix: size form control replacement SVGs with CSS under layout zoom (#516) [`2d6d41d`](https://github.com/zumerlab/snapdom/commit/2d6d41dcd738813d3441e2b62ce4c1af9d3a1d3d) - fix: resolve var() in SVG gradient stops (#515) [`b13ed28`](https://github.com/zumerlab/snapdom/commit/b13ed287d0747fa8c94d86b2faa65f3a7724ea18) - fix: emit the placeholder rule only when a placeholder was cloned [`eb26e15`](https://github.com/zumerlab/snapdom/commit/eb26e1530ef39bdde695d52cfc5355b537898103) - fix: keep placeholder color CSS off void inputs (#512) [`#514`](https://github.com/zumerlab/snapdom/pull/514) - fix(capture): drop xmlns attributes set through setAttribute (#511) [`#513`](https://github.com/zumerlab/snapdom/pull/513) - fix: read transform-origin on transformed pseudo-elements (#509) [`39ff290`](https://github.com/zumerlab/snapdom/commit/39ff2908481811b37c629538bf7cf89869ba7753) ##### 📦 other (chore/docs/refactor/…) - docs: update plugin capabilities [`9c0b8a3`](https://github.com/zumerlab/snapdom/commit/9c0b8a347b3a75f22a849f3c2d70c1fa1c235843) - docs: home page from the design handoff [`e88be16`](https://github.com/zumerlab/snapdom/commit/e88be16c658a41d7508c57d8a33fbcfcb376e4ed) - docs: Labs overview, Showcase, Made with and Plugins join the 3-pane template [`59046e9`](https://github.com/zumerlab/snapdom/commit/59046e9e2f6e91d6c5fe6c495c272c34aacfa25f) - docs: move Docs, How-to, Guides, Compare, Blog and Labs pages to the 3-pane template [`f0dbc79`](https://github.com/zumerlab/snapdom/commit/f0dbc79c30b877999af5a54c763f15fc54cf9bba) - docs: 3-pane Capabilities and Ecosystem pages from the design handoff [`d8b6688`](https://github.com/zumerlab/snapdom/commit/d8b6688dfa8c4c89e6ac260d1bcc95f355c076ca) - test: stop the network gate from skipping demos on a fast link, rerun what it skips [`96fc884`](https://github.com/zumerlab/snapdom/commit/96fc88411f80f49edfc48bcae66614a984f0617b) - test: serve the d15 image from a local second origin [`083cbd9`](https://github.com/zumerlab/snapdom/commit/083cbd9f05b53d11586dc26634f3940c00eafaf7) - test: restore imageSmoothingQuality only where the engine has it [`#516`](https://github.com/zumerlab/snapdom/pull/516) #### [v3.2.0](https://github.com/zumerlab/snapdom/compare/v3.1.1...v3.2.0) > 28 September 2026 - feat: export PNG files beyond the canvas limit [`6e6b5eb`](https://github.com/zumerlab/snapdom/commit/6e6b5ebb64b8a4185653af2ba5ead42aff7fbf4b) - fix: lay out captures on the device-pixel grid in Firefox too [`#508`](https://github.com/zumerlab/snapdom/pull/508) - fix: lay out captures on the live device-pixel grid in Chromium [`#508`](https://github.com/zumerlab/snapdom/pull/508) - fix: keep stacked rows aligned on fractional-DPR screens (#508) [`1327c55`](https://github.com/zumerlab/snapdom/commit/1327c55eb60cb16b541e96fc399c81a5d5e6038e) - fix: adjust scrollbar gutter calculations for fractional border widths (#508) [`67acb0c`](https://github.com/zumerlab/snapdom/commit/67acb0c3997d91957da3d49fbd4d51980e49018c) - fix: keep the settled decode frame when retrying in Firefox [`ab48bce`](https://github.com/zumerlab/snapdom/commit/ab48bce371df7e30b04b25da6e174d8fb0f765b8) - update crop option [`19a7e55`](https://github.com/zumerlab/snapdom/commit/19a7e55b660cac9a83da0f16f6663dde6be618bc) - chore: shorten console messages [`5bc3511`](https://github.com/zumerlab/snapdom/commit/5bc3511ac891256c75c9cd8e2ec4611c68cea128) - chore: color the benchmark verdicts in the terminal [`8d93e24`](https://github.com/zumerlab/snapdom/commit/8d93e24da9f986123a5dbd7adc7ca4be665c3192) - test: compare encoded PNGs with the canvas readback [`7a19be9`](https://github.com/zumerlab/snapdom/commit/7a19be9c5b166e74656e4b5a54f5141cd2cb1b49) #### [v3.1.1](https://github.com/zumerlab/snapdom/compare/v3.1.0...v3.1.1) > 24 September 2026 - fix: paint embedded fonts on first capture (#506) [`f207b37`](https://github.com/zumerlab/snapdom/commit/f207b3740e532ae75fbe4dd0e6c4d8f9e948a5c9) - fix: isolate custom element style defaults [`0e7cbf0`](https://github.com/zumerlab/snapdom/commit/0e7cbf007efc48bdbfbfc89bb2b70372f622fba7) - fix: preserve document overflow in captures. Ref #505 [`a736115`](https://github.com/zumerlab/snapdom/commit/a73611584e9571f9bb7989d34e2f82f7dc57a354) - perf: skip display:none subtrees when cloning. Ref #507 [`f4af040`](https://github.com/zumerlab/snapdom/commit/f4af0405964949ad606ef4fc12e653075c386e96) - fix: complete sitemap and add canonical URLs for Pro pages [`5b02330`](https://github.com/zumerlab/snapdom/commit/5b02330fdc6a6591752e7078dceda5ec9dc26559) #### [v3.1.0](https://github.com/zumerlab/snapdom/compare/v3.0.0...v3.1.0) > 21 September 2026 - feat(capture): bring back fast: false as a time-sliced capture [`7b7d218`](https://github.com/zumerlab/snapdom/commit/7b7d218e9aeec29e8f613c5f896f38cd65e36165) - feat(capture): meter, progress and slider part rules into the capture [`8a32f08`](https://github.com/zumerlab/snapdom/commit/8a32f081a24a904e25c9fa9983b80b4f24a4c4aa) - perf(styles): prune shadow-root style reads with a per-capture universe [`9f3ef77`](https://github.com/zumerlab/snapdom/commit/9f3ef77310830944a24500476a29f2317ec3d302) - fix: restore ArcGIS table captures. Ref #503 [`ac8cae6`](https://github.com/zumerlab/snapdom/commit/ac8cae66ece4a8390d5f95c5ff53a7b74a7a8b2c) ### [v3.0.0](https://github.com/zumerlab/snapdom/compare/v3.0.0-beta.1...v3.0.0) > 14 September 2026 The first stable release of SnapDOM v3 brings automatic capture reuse, incremental recapture, automatic font embedding, and new capture APIs. Core and official plugins now share the v3 release line. If you're upgrading from v2, read the [migration guide](README.md#migrating-from-v2). The [v2 source](https://github.com/zumerlab/snapdom/tree/v2) remains available. #### Features and performance - Automatically reuse eligible unchanged captures and rebuild affected subtrees for safe local mutations. - Isolate concurrent captures with per-capture sessions. - Automatically embed the web fonts used by the captured content. - Capture HTML strings with `fromString()`. - Prepare learned captures on hover or focus with `preCapture()`. The SVG engine remains the default. The native html-in-canvas engine remains experimental and requires a custom build. #### Breaking changes - `width` and `height` now take precedence over `scale`. - Font embedding is enabled automatically. - `preCache` has been removed, and obsolete capture options are no longer supported. - Core redaction is limited to password fields. - `afterExport` hooks observe results without chaining their return values. See the [migration guide](README.md#migrating-from-v2) for the complete upgrade instructions. #### Layout and rendering fixes - Correct alignment in pseudo-element boxes, scroll containers, and images. [#498](https://github.com/zumerlab/snapdom/pull/498) - Fix transformed-element reconciliation and offscreen captures. [9b28ab4](https://github.com/zumerlab/snapdom/commit/9b28ab4d28b7ac56f324e2677ae47b3c22ba55ba), [460b75e](https://github.com/zumerlab/snapdom/commit/460b75ec0108436c874bf623d3d3c5f1adea134c) - Prevent fractional-width rounding from introducing unwanted line wrapping. [cffd222](https://github.com/zumerlab/snapdom/commit/cffd222a1c125bb3b57ea5a23e1d862efa31e381) - Preserve explicit wrapper heights and author-specified widths on blockified spans. [df94e3e](https://github.com/zumerlab/snapdom/commit/df94e3ee361679c83224c4e989529dfb761ec93e), [f3c75d3](https://github.com/zumerlab/snapdom/commit/f3c75d3afd64e3bda751c952295b97994d634dd9) - Match browser behavior for `visibility` and `content-visibility`. [21251f7](https://github.com/zumerlab/snapdom/commit/21251f70ea6153b73541fcf6eed20d766d283c0c) - Measure text truncation without replacing live text nodes. [418d18f](https://github.com/zumerlab/snapdom/commit/418d18fcbd3336d1ba1546797f398db893d62d5e) - Neutralize CSS `zoom` on the capture root. [14b2047](https://github.com/zumerlab/snapdom/commit/14b204701483d66ffa6dfa0866dcdb906fa9bcc8) - Preserve inherited fill colors in SVG `` icons. [1b6cd96](https://github.com/zumerlab/snapdom/commit/1b6cd968d5ecce1bc125619eda6baf38bb18c105) #### Fonts and pseudo-elements - Preserve font styles for icon glyphs, including italic icons. [#496](https://github.com/zumerlab/snapdom/pull/496) - Skip non-generated pseudo-elements and carry over animation-suppression fixes from v2. [#497](https://github.com/zumerlab/snapdom/pull/497) - Retain custom `@font-face` rules when the requested weight or stretch is far from the declared value. [#478](https://github.com/zumerlab/snapdom/pull/478) - Keep other font families in a stylesheet when one family is identified as an icon font. [a154f18](https://github.com/zumerlab/snapdom/commit/a154f18a7acd24e511f2a8abdefab5a765b5ec51) - Emit only the `@font-face` descriptors declared in the source. [8d0345a](https://github.com/zumerlab/snapdom/commit/8d0345a4843dd255e293f67f45a5ad13ba0c6ed2) #### Canvas, Shadow DOM, and compatibility - Bound canvas frame waits, warn when a canvas is empty, and preserve the frame captured before `toDataURL()` for WebGL canvases. [de521b8](https://github.com/zumerlab/snapdom/commit/de521b819afad1586bfdb91677d8e6b0a6b2639d), [1c44d1d](https://github.com/zumerlab/snapdom/commit/1c44d1d468f8fb40a44a4fbaa7fad1fbeb9fad91) - Clone slotted light DOM only once and exclude light DOM that has not been assigned to a slot. [f4b1859](https://github.com/zumerlab/snapdom/commit/f4b18590445a2bb1eff980f0b27948dbdf637abb), [b75e88b](https://github.com/zumerlab/snapdom/commit/b75e88b27480f111ab19983b27d8e79ca1e559d8) - Support DOM type checks for elements from other windows and iframes. [84359e5](https://github.com/zumerlab/snapdom/commit/84359e557b369e1706e283119e53c4c163c3116a) - Fix global-variable leakage in the legacy bundle. [80fe19d](https://github.com/zumerlab/snapdom/commit/80fe19d5edc5a38fae9ca53291a2e8261c4575fe) - Correct iframe guidance that suggested enabling an option already enabled. [98de375](https://github.com/zumerlab/snapdom/commit/98de37594af6e3891173d091695bf021240482ff) #### Plugins and exports - Align official plugins with v3 for HTML, context, element maps, PDF, image effects, and GIF/video recording. - Expose capture geometry, exact export options, and canvas cropping to plugins. [7abb29a](https://github.com/zumerlab/snapdom/commit/7abb29a40ebb2b8159cc539dfb94254e675fac46) - Accept clone roots from other windows and iframes in the color-tint plugin. [ed8c31a](https://github.com/zumerlab/snapdom/commit/ed8c31ad114b1f425722f25e6e04924c56dad2fe) #### Documentation - Align package references, version tags, and the plugin showcase with the shipped releases. [fb616b6](https://github.com/zumerlab/snapdom/commit/fb616b6edbc84b81f9af9762a2db8ec775d57ebf), [533e7e7](https://github.com/zumerlab/snapdom/commit/533e7e72eecb8d3f1b8a7ae9388e34899d8a336b) - Document the plugin hook contract and correct the plugins subpath import. [9ed3632](https://github.com/zumerlab/snapdom/commit/9ed36329858349fddd7a4b1635733852c2cb439e), [c439ca1](https://github.com/zumerlab/snapdom/commit/c439ca1c88e10e238af37ef3baebd15964a727ae) - Correct server-side capture guidance and add guides covering DOM capture boundaries and integration patterns. [2fa74fa](https://github.com/zumerlab/snapdom/commit/2fa74fa90656398a632241afeaeeff323d05982c), [0118a27](https://github.com/zumerlab/snapdom/commit/0118a275803f8e20b67d6a40d0bf54513208dc66) - Rewrite `llms.txt` and `llms-full.txt` to match the source implementation. [de95504](https://github.com/zumerlab/snapdom/commit/de95504cce446431697387b843cce84a705ebb62) - Improve documentation layouts, technical guides, and search-engine crawl signals. [e134a69](https://github.com/zumerlab/snapdom/commit/e134a69f467ee2e929d2f3fe7f8172416d56f7b0), [0f876d6](https://github.com/zumerlab/snapdom/commit/0f876d60fef613220ddb10e2efa67778771dfa08) #### Testing and maintenance - Expose internal visual demos for testing, expand regression coverage, and split the visual suite into six shards. [5766151](https://github.com/zumerlab/snapdom/commit/5766151f8867eb2e64a6321a0af6f01fe25d65f0), [56b1e01](https://github.com/zumerlab/snapdom/commit/56b1e013e843e528b8256baacea12b22090e599a) - Improve network-dependent test scheduling and wait for iframe stylesheets, imported fonts, and image decoding before capture. [8ae2371](https://github.com/zumerlab/snapdom/commit/8ae237176e7cc4af32add41f54eb58811fd846ca), [1df2291](https://github.com/zumerlab/snapdom/commit/1df22912d2be17435e945567041f40a8a7f8e303), [b5161af](https://github.com/zumerlab/snapdom/commit/b5161afc51bbd7cc5e231815f277ffd7f1b40ecd) - Make regression tests independent of the capture engine and pin `devicePixelRatio` in DPR-dependent tests. [8fe0a08](https://github.com/zumerlab/snapdom/commit/8fe0a081f19f62a5f8274359f0a307b76ea476da), [fb7311a](https://github.com/zumerlab/snapdom/commit/fb7311ab34de7db28fb29abf352ee03d73a36d7a) - Stop pushing changelog changes automatically from `npm run build`. [d341737](https://github.com/zumerlab/snapdom/commit/d341737f9fd48f8b2440ea8153502c7dd37fac4d) #### [v3.0.0-beta.1](https://github.com/zumerlab/snapdom/compare/v3.0.0-beta.0...v3.0.0-beta.1) > 10 September 2026 - fix: three layout misalignments in pseudo boxes, scroll containers and images [`#498`](https://github.com/zumerlab/snapdom/issues/498) - fix: reuse canvas targets from iframe documents [`7befc15`](https://github.com/zumerlab/snapdom/commit/7befc150c28b70f1fb8b66cf215fdbf998fcc25c) - test: accept Gecko's serialization of the fractional image width (#498) [`6050325`](https://github.com/zumerlab/snapdom/commit/60503257d197526a7cb9f8e537c43aa92b70c4c5) #### v3.0.0-beta.0 > 8 September 2026 The first v3 beta. **Breaking**: read the migration table in the README before upgrading. 💥 breaking - `width` / `height` now win over `scale`. v2 multiplied them; v3 treats `width`/`height` as the absolute output size and applies `scale` only when neither is set. - The `needs: 'dom'` plugin stage is gone. A capture that takes no clone does no capturing. - `cache` collapsed to `'soft'` (default) and `'disabled'`; `'auto'`/`'full'` map to `'soft'`. - `fast` removed — its behaviour is unconditional now. - `burst`, `compress`, `resolvePicturePlaceholders` and `pictureResolver` are no longer documented or supported options. Capture reuse, image downsampling and responsive/lazy image resolution remain engine behavior. Remove these settings; custom image loading/timeouts belong in the application before capture. The engine still reads `burst`, `compress` and `resolvePicturePlaceholders` for internal use; do not rely on them. - The named TypeScript interface `PluginExportFacade` is removed, but the `ctx.exports` facade remains. Infer it in `defineExports` or use `NonNullable`. - `afterExport` return values are ignored. In v2.24.16 they only became the next hook's payload; they never replaced the caller's export result. Use `defineExports` for custom output. - Core masks `type="password"` only. Everything the browser paints in the clear is captured as is; use the `redactInputs` plugin for the old behaviour. - `embedFonts` defaults to `'auto'`. - `preCache` is removed, along with the `/preCache` subpath and `window.preCache`. Eligible static elements are memoized from their first capture, so the capture is its own warm-up; `snapdom.preCapture()` can take it before the click. - No CommonJS build, by decision, and no `require` condition in `exports`. Up to 2.24.1 `require()` pointed at the IIFE and returned `{}`, so nothing that worked is lost. On Node 20.19+ / 22.12+ `require()` loads the ESM build; older Node throws `ERR_REQUIRE_ESM`. - The `@zumer/snapdom-plugins/html-in-canvas` subpath of plugins 2.2.2 is gone. Use the core's `engine: 'html-in-canvas'` instead (experimental, not in the shipped bundle). ⚡ perf - Per-capture sessions replace the module-level mutable session; the whole `#463` bug class is now structurally unrepresentable. - Automatic memoization from the first eligible static capture (at most 64 live memos, least recently used evicted): an unchanged repeat is served from memory; a local mutation uses differential recapture only when byte-faithful splicing can be proved, otherwise it falls back to a full capture (mutating poll 563ms → 16ms). - One author-style scan yields the property universe and per-pseudo selector gates, replacing three `getComputedStyle` resolutions per node with one `matches()`. ✨ features - `snapdom.fromString(html, options)` captures a markup string with no mount wiring. **Trusted HTML only** — it goes through `innerHTML` into the real document. - Plugin stages (`needs`), `defineExports` for custom export formats, and an official plugin package: `@zumer/snapdom-plugins`. - `snapdom.preCapture()`: link prefetch for captures. Intent on a control (pointer enter, focus, press) captures the eligible element that control asked for previously, with the same options. Attribution is limited to the triggering event task; unrelated later timers are not learned. 🛠 fix - Restore the v2 `filter` / `filterMode` contract alongside `exclude` / `excludeMode`. Both can operate in the same capture with independent hide/remove modes. A pre-release checkout briefly removed `filter`; it is restored, with both controls and modes independent. Predicate support in `exclude` remains an optional addition. - Hidden block spacers retain precise CSS dimensions, including fractional sizes and padding/borders. Safari page zoom can round integer layout measurements upward; those rounded values no longer shift content after filtered or excluded blocks. - Function-valued `filter`, `exclude`, `excludeStyleProps` and `fallbackURL` cause new captures to evaluate current callback state instead of reusing an earlier capture/style/fallback decision. Changing a closure does not require `invalidate`; exporting an existing result still uses its original captured state. - The `/plugins` subpath maps to the same file as the root instead of being a separate bundle with its own module state; registering through the subpath now reaches `snapdom()`. Its `types` condition points at the root declarations, so consumers with `skipLibCheck: false` typecheck. - `dist/snapdom.js` is a real IIFE. It was emitting bare top-level statements, publishing 442 minified bindings as globals to every `