@percy/dom 1.0.0-beta.7 → 1.0.0-beta.73

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 CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  Serializes a document's DOM into a DOM string suitable for re-rendering.
4
4
 
5
+ - [Usage](#usage)
6
+ - [ES6 imports](#es6-imports)
7
+ - [Browser injection](#browser-injection)
8
+ - [Options](#options)
9
+ - [Serialized Content](#serialize-content)
10
+ - [Input elements](#input-elements)
11
+ - [Frame elements](#frame-elements)
12
+ - [CSSOM rules](#cssom-rules)
13
+ - [Canvas elements](#canvas-elements)
14
+ - [Other elements](#other-elements)
15
+
5
16
  ## Usage
6
17
 
7
18
  ### ES6 imports
@@ -10,7 +21,7 @@ Serializes a document's DOM into a DOM string suitable for re-rendering.
10
21
  import serializeDOM from '@percy/dom';
11
22
 
12
23
  // optional arguments shown with defaults
13
- const domSnapshot = serializeDOM(/* options */)
24
+ const domSnapshot = serializeDOM(options)
14
25
  ```
15
26
 
16
27
  ### Browser injection
@@ -18,13 +29,13 @@ const domSnapshot = serializeDOM(/* options */)
18
29
  ```js
19
30
  // via puppeteer
20
31
  await page.addScriptTag({ path: require.resolve('@percy/dom') })
21
- const domSnapshot = await page.evaluate(() => PercyDOM.serialize(/* options */))
32
+ const domSnapshot = await page.evaluate(() => PercyDOM.serialize(options))
22
33
  ```
23
34
 
24
- ### Available options
35
+ ### Options
25
36
 
26
- - `enableJavaScript` - when true, does not serialize some DOM elements
27
- - `domTransformation` - function to transform the DOM after serialization
37
+ - `enableJavaScript` When true, does not serialize some DOM elements
38
+ - `domTransformation` Function to transform the DOM after serialization
28
39
 
29
40
  ## Serialized Content
30
41
 
package/dist/bundle.js ADDED
@@ -0,0 +1,227 @@
1
+ (function() {
2
+ (function (exports) {
3
+ 'use strict';
4
+
5
+ const process = (typeof globalThis !== "undefined" && globalThis.process) || {};
6
+ process.env = process.env || {};
7
+ process.env.__PERCY_BROWSERIFIED__ = true;
8
+
9
+ // Returns a mostly random uid.
10
+ function uid() {
11
+ return `_${Math.random().toString(36).substr(2, 9)}`;
12
+ } // Marks elements that are to be serialized later with a data attribute.
13
+
14
+
15
+ function prepareDOM(dom) {
16
+ for (let elem of dom.querySelectorAll('input, textarea, select, iframe, canvas')) {
17
+ if (!elem.getAttribute('data-percy-element-id')) {
18
+ elem.setAttribute('data-percy-element-id', uid());
19
+ }
20
+ }
21
+ }
22
+
23
+ // Translates JavaScript properties of inputs into DOM attributes.
24
+ function serializeInputElements(dom, clone) {
25
+ for (let elem of dom.querySelectorAll('input, textarea, select')) {
26
+ let inputId = elem.getAttribute('data-percy-element-id');
27
+ let cloneEl = clone.querySelector(`[data-percy-element-id="${inputId}"]`);
28
+
29
+ switch (elem.type) {
30
+ case 'checkbox':
31
+ case 'radio':
32
+ if (elem.checked) {
33
+ cloneEl.setAttribute('checked', '');
34
+ }
35
+
36
+ break;
37
+
38
+ case 'select-one':
39
+ if (elem.selectedIndex !== -1) {
40
+ cloneEl.options[elem.selectedIndex].setAttribute('selected', 'true');
41
+ }
42
+
43
+ break;
44
+
45
+ case 'select-multiple':
46
+ for (let option of elem.selectedOptions) {
47
+ cloneEl.options[option.index].setAttribute('selected', 'true');
48
+ }
49
+
50
+ break;
51
+
52
+ case 'textarea':
53
+ cloneEl.innerHTML = elem.value;
54
+ break;
55
+
56
+ default:
57
+ cloneEl.setAttribute('value', elem.value);
58
+ }
59
+ }
60
+ }
61
+
62
+ // embedded documents are serialized and their contents become root-relative.
63
+
64
+ function setBaseURI(dom) {
65
+ if (!new URL(dom.baseURI).hostname) return;
66
+ let $base = document.createElement('base');
67
+ $base.href = dom.baseURI;
68
+ dom.querySelector('head').prepend($base);
69
+ } // Recursively serializes iframe documents into srcdoc attributes.
70
+
71
+
72
+ function serializeFrames(dom, clone, _ref) {
73
+ let {
74
+ enableJavaScript
75
+ } = _ref;
76
+
77
+ for (let frame of dom.querySelectorAll('iframe')) {
78
+ let percyElementId = frame.getAttribute('data-percy-element-id');
79
+ let cloneEl = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`);
80
+ let builtWithJs = !frame.srcdoc && (!frame.src || frame.src.split(':')[0] === 'javascript'); // delete frames within the head since they usually break pages when
81
+ // rerendered and do not effect the visuals of a page
82
+
83
+ if (clone.head.contains(cloneEl)) {
84
+ cloneEl.remove(); // if the frame document is accessible and not empty, we can serialize it
85
+ } else if (frame.contentDocument && frame.contentDocument.documentElement) {
86
+ // js is enabled and this frame was built with js, don't serialize it
87
+ if (enableJavaScript && builtWithJs) continue; // the frame has yet to load and wasn't built with js, it is unsafe to serialize
88
+
89
+ if (!builtWithJs && !frame.contentWindow.performance.timing.loadEventEnd) continue; // recersively serialize contents
90
+
91
+ let serialized = serializeDOM({
92
+ domTransformation: setBaseURI,
93
+ dom: frame.contentDocument,
94
+ enableJavaScript
95
+ }); // assign to srcdoc and remove src
96
+
97
+ cloneEl.setAttribute('srcdoc', serialized);
98
+ cloneEl.removeAttribute('src'); // delete inaccessible frames built with js when js is disabled because they
99
+ // break asset discovery by creating non-captured requests that hang
100
+ } else if (!enableJavaScript && builtWithJs) {
101
+ cloneEl.remove();
102
+ }
103
+ }
104
+ }
105
+
106
+ // Returns true if a stylesheet is a CSSOM-based stylesheet.
107
+ function isCSSOM(styleSheet) {
108
+ var _styleSheet$ownerNode, _styleSheet$ownerNode2;
109
+
110
+ // no href, has a rulesheet, and isn't already in the DOM
111
+ return !styleSheet.href && styleSheet.cssRules && !((_styleSheet$ownerNode = styleSheet.ownerNode) !== null && _styleSheet$ownerNode !== void 0 && (_styleSheet$ownerNode2 = _styleSheet$ownerNode.innerText) !== null && _styleSheet$ownerNode2 !== void 0 && _styleSheet$ownerNode2.trim().length);
112
+ } // Outputs in-memory CSSOM into their respective DOM nodes.
113
+
114
+
115
+ function serializeCSSOM(dom, clone) {
116
+ for (let styleSheet of dom.styleSheets) {
117
+ if (isCSSOM(styleSheet)) {
118
+ let style = clone.createElement('style');
119
+ style.type = 'text/css';
120
+ style.setAttribute('data-percy-cssom-serialized', 'true');
121
+ style.innerHTML = Array.from(styleSheet.cssRules).reduce((prev, cssRule) => prev + cssRule.cssText, '');
122
+ clone.head.appendChild(style);
123
+ }
124
+ }
125
+ }
126
+
127
+ // Serialize in-memory canvas elements into images.
128
+ function serializeCanvas(dom, clone) {
129
+ for (let canvas of dom.querySelectorAll('canvas')) {
130
+ // Note: the `.toDataURL` API requires WebGL canvas elements to use
131
+ // `preserveDrawingBuffer: true`. This is because `.toDataURL` uses the
132
+ // drawing buffer, which is cleared after each render for WebGL by default.
133
+ let dataUrl = canvas.toDataURL(); // skip empty canvases
134
+
135
+ if (!dataUrl || dataUrl === 'data:,') continue; // create an image element in the cloned dom
136
+
137
+ let img = clone.createElement('img');
138
+ img.src = dataUrl; // copy canvas element attributes to the image element such as style, class,
139
+ // or data attributes that may be targeted by CSS
140
+
141
+ for (let {
142
+ name,
143
+ value
144
+ } of canvas.attributes) {
145
+ img.setAttribute(name, value);
146
+ } // mark the image as serialized (can be targeted by CSS)
147
+
148
+
149
+ img.setAttribute('data-percy-canvas-serialized', ''); // set a default max width to account for canvases that might resize with JS
150
+
151
+ img.style.maxWidth = img.style.maxWidth || '100%'; // insert the image into the cloned DOM and remove the cloned canvas element
152
+
153
+ let percyElementId = canvas.getAttribute('data-percy-element-id');
154
+ let cloneEl = clone.querySelector(`[data-percy-element-id=${percyElementId}]`);
155
+ cloneEl.parentElement.insertBefore(img, cloneEl);
156
+ cloneEl.remove();
157
+ }
158
+ }
159
+
160
+ function doctype(dom) {
161
+ var _dom$doctype;
162
+
163
+ let {
164
+ name = 'html',
165
+ publicId = '',
166
+ systemId = ''
167
+ } = (_dom$doctype = dom === null || dom === void 0 ? void 0 : dom.doctype) !== null && _dom$doctype !== void 0 ? _dom$doctype : {};
168
+ let deprecated = '';
169
+
170
+ if (publicId && systemId) {
171
+ deprecated = ` PUBLIC "${publicId}" "${systemId}"`;
172
+ } else if (publicId) {
173
+ deprecated = ` PUBLIC "${publicId}"`;
174
+ } else if (systemId) {
175
+ deprecated = ` SYSTEM "${systemId}"`;
176
+ }
177
+
178
+ return `<!DOCTYPE ${name}${deprecated}>`;
179
+ } // Serializes a document and returns the resulting DOM string.
180
+
181
+
182
+ function serializeDOM(options) {
183
+ let {
184
+ dom = document,
185
+ // allow snake_case or camelCase
186
+ enableJavaScript = options === null || options === void 0 ? void 0 : options.enable_javascript,
187
+ domTransformation = options === null || options === void 0 ? void 0 : options.dom_transformation
188
+ } = options || {};
189
+ prepareDOM(dom);
190
+ let clone = dom.cloneNode(true);
191
+ serializeInputElements(dom, clone);
192
+ serializeFrames(dom, clone, {
193
+ enableJavaScript
194
+ });
195
+
196
+ if (!enableJavaScript) {
197
+ serializeCSSOM(dom, clone);
198
+ serializeCanvas(dom, clone);
199
+ }
200
+
201
+ let doc = clone.documentElement;
202
+
203
+ if (domTransformation) {
204
+ try {
205
+ domTransformation(doc);
206
+ } catch (err) {
207
+ console.error('Could not transform the dom:', err.message);
208
+ }
209
+ }
210
+
211
+ return doctype(dom) + doc.outerHTML;
212
+ }
213
+
214
+ exports["default"] = serializeDOM;
215
+ exports.serialize = serializeDOM;
216
+ exports.serializeDOM = serializeDOM;
217
+
218
+ Object.defineProperty(exports, '__esModule', { value: true });
219
+
220
+ })(this.PercyDOM = this.PercyDOM || {});
221
+ }).call(window);
222
+
223
+ if (typeof define === "function" && define.amd) {
224
+ define([], () => window.PercyDOM);
225
+ } else if (typeof module === "object" && module.exports) {
226
+ module.exports = window.PercyDOM;
227
+ }
package/package.json CHANGED
@@ -1,45 +1,38 @@
1
1
  {
2
2
  "name": "@percy/dom",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0-beta.73",
4
4
  "license": "MIT",
5
- "main": "dist/index.js",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/percy/cli",
8
+ "directory": "packages/dom"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "main": "dist/bundle.js",
14
+ "browser": "dist/bundle.js",
6
15
  "files": [
7
16
  "dist"
8
17
  ],
9
18
  "scripts": {
10
- "build": "webpack",
19
+ "build": "node ../../scripts/build",
11
20
  "lint": "eslint --ignore-path ../../.gitignore .",
12
- "test": "cross-env NODE_ENV=test karma start --single-run",
21
+ "test": "node ../../scripts/test",
13
22
  "test:coverage": "yarn test --coverage"
14
23
  },
15
- "publishConfig": {
16
- "access": "public"
17
- },
18
- "babel": {
19
- "extends": "../../babel.config.js",
20
- "presets": [
21
- [
22
- "@babel/env",
23
- {
24
- "targets": "last 2 version"
25
- }
26
- ]
27
- ]
24
+ "rollup": {
25
+ "output": {
26
+ "name": "PercyDOM"
27
+ },
28
+ "test": {
29
+ "output": {
30
+ "exports": "named"
31
+ }
32
+ }
28
33
  },
29
34
  "devDependencies": {
30
- "babel-loader": "^8.0.6",
31
- "cheerio": "^1.0.0-rc.3",
32
- "interactor.js": "^1.6.0",
33
- "karma": "^5.0.9",
34
- "karma-chrome-launcher": "^3.1.0",
35
- "karma-coverage": "^2.0.1",
36
- "karma-firefox-launcher": "^1.3.0",
37
- "karma-mocha": "^2.0.1",
38
- "karma-mocha-reporter": "^2.2.5",
39
- "karma-webpack": "^4.0.2",
40
- "regenerator-runtime": "^0.13.3",
41
- "webpack": "^4.41.6",
42
- "webpack-cli": "^3.3.11"
35
+ "interactor.js": "^2.0.0-beta.10"
43
36
  },
44
- "gitHead": "5be796ec8f17958e93ada0b634899b945c9b0d60"
37
+ "gitHead": "aa8160e02bea3e04ab1d3605762f89fbe79605d4"
45
38
  }
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.PercyDOM=t():e.PercyDOM=t()}(window,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";function n(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(!e)return;if("string"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(e,t)}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,a=function(){};return{s:a,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,u=!0,c=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return u=e.done,e},e:function(e){c=!0,i=e},f:function(){try{u||null==r.return||r.return()}finally{if(c)throw i}}}}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function a(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(!e)return;if("string"==typeof e)return i(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(e,t)}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,u=!0,c=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return u=e.done,e},e:function(e){c=!0,a=e},f:function(){try{u||null==r.return||r.return()}finally{if(c)throw a}}}}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function u(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(!e)return;if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return c(e,t)}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i=!0,u=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return i=e.done,e},e:function(e){u=!0,a=e},f:function(){try{i||null==r.return||r.return()}finally{if(u)throw a}}}}function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function l(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(!e)return;if("string"==typeof e)return f(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return f(e,t)}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i=!0,u=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return i=e.done,e},e:function(e){u=!0,a=e},f:function(){try{i||null==r.return||r.return()}finally{if(u)throw a}}}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function s(e){var t;return!e.href&&e.cssRules&&!(null===(t=e.ownerNode)||void 0===t?void 0:t.innerText.trim().length)}function y(e,t){var r;if("undefined"==typeof Symbol||null==e[Symbol.iterator]){if(Array.isArray(e)||(r=function(e,t){if(!e)return;if("string"==typeof e)return d(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);"Object"===r&&e.constructor&&(r=e.constructor.name);if("Map"===r||"Set"===r)return Array.from(e);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(e,t)}(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i=!0,u=!1;return{s:function(){r=e[Symbol.iterator]()},n:function(){var e=r.next();return i=e.done,e},e:function(e){u=!0,a=e},f:function(){try{i||null==r.return||r.return()}finally{if(u)throw a}}}}function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function m(e){var t=e||{},r=t.dom,o=void 0===r?document:r,i=t.enableJavaScript,c=t.domTransformation;!function(e){var t,r=n(e.querySelectorAll("input, textarea, select, iframe, canvas"));try{for(r.s();!(t=r.n()).done;){var o=t.value;o.getAttribute("data-percy-element-id")||o.setAttribute("data-percy-element-id","_".concat(Math.random().toString(36).substr(2,9)))}}catch(e){r.e(e)}finally{r.f()}}(o);var f=o.cloneNode(!0);!function(e,t){var r,n=a(e.querySelectorAll("input, textarea, select"));try{for(n.s();!(r=n.n()).done;){var o=r.value,i=o.getAttribute("data-percy-element-id"),u=t.querySelector('[data-percy-element-id="'.concat(i,'"]'));switch(o.type){case"checkbox":case"radio":o.checked&&u.setAttribute("checked","");break;case"select-one":-1!==o.selectedIndex&&u.options[o.selectedIndex].setAttribute("selected","true");break;case"select-multiple":var c,l=a(o.selectedOptions);try{for(l.s();!(c=l.n()).done;){var f=c.value;u.options[f.index].setAttribute("selected","true")}}catch(e){l.e(e)}finally{l.f()}break;case"textarea":u.innerHTML=o.value;break;default:u.setAttribute("value",o.value)}}}catch(e){n.e(e)}finally{n.f()}}(o,f),function(e,t,r){var n,o=r.enableJavaScript,a=u(e.querySelectorAll("iframe"));try{for(a.s();!(n=a.n()).done;){var i=n.value,c=i.getAttribute("data-percy-element-id"),l=t.querySelector('[data-percy-element-id="'.concat(c,'"]')),f=!(i.srcdoc||i.src&&"javascript"!==i.src.split(":")[0]);if(t.head.contains(l))l.remove();else if(i.contentDocument){if(o&&f)continue;if(!f&&!i.contentWindow.performance.timing.loadEventEnd)continue;var s=m({dom:i.contentDocument,enableJavaScript:o});l.setAttribute("srcdoc",s),l.removeAttribute("src")}else!o&&f&&l.remove()}}catch(e){a.e(e)}finally{a.f()}}(o,f,{enableJavaScript:i}),i||(function(e,t){var r,n=l(e.styleSheets);try{for(n.s();!(r=n.n()).done;){var o=r.value;if(s(o)){var a=t.createElement("style");a.type="text/css",a.setAttribute("data-percy-cssom-serialized","true"),a.innerHTML=Array.from(o.cssRules).reduce((function(e,t){return e+t.cssText}),""),t.head.appendChild(a)}}}catch(e){n.e(e)}finally{n.f()}}(o,f),function(e,t){var r,n=y(e.querySelectorAll("canvas"));try{for(n.s();!(r=n.n()).done;){var o,a=r.value,i=t.createElement("img"),u=y(a.attributes);try{for(u.s();!(o=u.n()).done;){var c=o.value,l=c.name,f=c.value;i.setAttribute(l,f)}}catch(e){u.e(e)}finally{u.f()}i.src=a.toDataURL(),i.setAttribute("data-percy-canvas-serialized",""),i.style.maxWidth=i.style.maxWidth||"100%";var s=a.getAttribute("data-percy-element-id"),d=t.querySelector("[data-percy-element-id=".concat(s,"]"));d.parentElement.insertBefore(i,d),d.remove()}}catch(e){n.e(e)}finally{n.f()}}(o,f));var d=f.documentElement;if(c)try{c(d)}catch(e){console.error("Could not transform the dom:",e.message)}return function(e){var t,r=null!==(t=null==e?void 0:e.doctype)&&void 0!==t?t:{},n=r.name,o=void 0===n?"html":n,a=r.publicId,i=void 0===a?"":a,u=r.systemId,c=void 0===u?"":u,l="";return i&&c?l=' PUBLIC "'.concat(i,'" "').concat(c,'"'):i?l=' PUBLIC "'.concat(i,'"'):c&&(l=' SYSTEM "'.concat(c,'"')),"<!DOCTYPE ".concat(o).concat(l,">")}(o)+d.outerHTML}r.r(t),r.d(t,"default",(function(){return m})),r.d(t,"serialize",(function(){return m}))}])}));