@percy/dom 1.12.0 → 1.14.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.
Files changed (2) hide show
  1. package/dist/bundle.js +42 -47
  2. package/package.json +2 -2
package/dist/bundle.js CHANGED
@@ -9,9 +9,9 @@
9
9
  // Returns a mostly random uid.
10
10
  function uid() {
11
11
  return `_${Math.random().toString(36).substr(2, 9)}`;
12
- } // Marks elements that are to be serialized later with a data attribute.
13
-
12
+ }
14
13
 
14
+ // Marks elements that are to be serialized later with a data attribute.
15
15
  function prepareDOM(dom) {
16
16
  for (let elem of dom.querySelectorAll('input, textarea, select, iframe, canvas, video, style')) {
17
17
  if (!elem.getAttribute('data-percy-element-id')) {
@@ -25,77 +25,76 @@
25
25
  for (let elem of dom.querySelectorAll('input, textarea, select')) {
26
26
  let inputId = elem.getAttribute('data-percy-element-id');
27
27
  let cloneEl = clone.querySelector(`[data-percy-element-id="${inputId}"]`);
28
-
29
28
  switch (elem.type) {
30
29
  case 'checkbox':
31
30
  case 'radio':
32
31
  if (elem.checked) {
33
32
  cloneEl.setAttribute('checked', '');
34
33
  }
35
-
36
34
  break;
37
-
38
35
  case 'select-one':
39
36
  if (elem.selectedIndex !== -1) {
40
37
  cloneEl.options[elem.selectedIndex].setAttribute('selected', 'true');
41
38
  }
42
-
43
39
  break;
44
-
45
40
  case 'select-multiple':
46
41
  for (let option of elem.selectedOptions) {
47
42
  cloneEl.options[option.index].setAttribute('selected', 'true');
48
43
  }
49
-
50
44
  break;
51
-
52
45
  case 'textarea':
53
46
  cloneEl.innerHTML = elem.value;
54
47
  break;
55
-
56
48
  default:
57
49
  cloneEl.setAttribute('value', elem.value);
58
50
  }
59
51
  }
60
52
  }
61
53
 
54
+ // Adds a `<base>` element to the serialized iframe's `<head>`. This is necessary when
62
55
  // embedded documents are serialized and their contents become root-relative.
63
-
64
56
  function setBaseURI(dom) {
65
57
  if (!new URL(dom.baseURI).hostname) return;
66
58
  let $base = document.createElement('base');
67
59
  $base.href = dom.baseURI;
68
60
  dom.querySelector('head').prepend($base);
69
- } // Recursively serializes iframe documents into srcdoc attributes.
70
-
61
+ }
71
62
 
63
+ // Recursively serializes iframe documents into srcdoc attributes.
72
64
  function serializeFrames(dom, clone, _ref) {
73
65
  let {
74
66
  enableJavaScript
75
67
  } = _ref;
76
-
77
68
  for (let frame of dom.querySelectorAll('iframe')) {
78
69
  let percyElementId = frame.getAttribute('data-percy-element-id');
79
70
  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
71
+ let builtWithJs = !frame.srcdoc && (!frame.src || frame.src.split(':')[0] === 'javascript');
82
72
 
73
+ // delete frames within the head since they usually break pages when
74
+ // rerendered and do not effect the visuals of a page
83
75
  if (clone.head.contains(cloneEl)) {
84
- cloneEl.remove(); // if the frame document is accessible and not empty, we can serialize it
76
+ cloneEl.remove();
77
+
78
+ // if the frame document is accessible and not empty, we can serialize it
85
79
  } else if (frame.contentDocument && frame.contentDocument.documentElement) {
86
80
  // 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
81
+ if (enableJavaScript && builtWithJs) continue;
88
82
 
89
- if (!builtWithJs && !frame.contentWindow.performance.timing.loadEventEnd) continue; // recersively serialize contents
83
+ // the frame has yet to load and wasn't built with js, it is unsafe to serialize
84
+ if (!builtWithJs && !frame.contentWindow.performance.timing.loadEventEnd) continue;
90
85
 
86
+ // recersively serialize contents
91
87
  let serialized = serializeDOM({
92
88
  domTransformation: setBaseURI,
93
89
  dom: frame.contentDocument,
94
90
  enableJavaScript
95
- }); // assign to srcdoc and remove src
91
+ });
96
92
 
93
+ // assign to srcdoc and remove src
97
94
  cloneEl.setAttribute('srcdoc', serialized);
98
- cloneEl.removeAttribute('src'); // delete inaccessible frames built with js when js is disabled because they
95
+ cloneEl.removeAttribute('src');
96
+
97
+ // delete inaccessible frames built with js when js is disabled because they
99
98
  // break asset discovery by creating non-captured requests that hang
100
99
  } else if (!enableJavaScript && builtWithJs) {
101
100
  cloneEl.remove();
@@ -107,22 +106,20 @@
107
106
  function isCSSOM(styleSheet) {
108
107
  // no href, has a rulesheet, and has an owner node
109
108
  return !styleSheet.href && styleSheet.cssRules && styleSheet.ownerNode;
110
- } // Returns false if any stylesheet rules do not match between two stylesheets
111
-
109
+ }
112
110
 
111
+ // Returns false if any stylesheet rules do not match between two stylesheets
113
112
  function styleSheetsMatch(sheetA, sheetB) {
114
113
  for (let i = 0; i < sheetA.cssRules.length; i++) {
115
114
  var _sheetB$cssRules$i;
116
-
117
115
  let ruleA = sheetA.cssRules[i].cssText;
118
116
  let ruleB = (_sheetB$cssRules$i = sheetB.cssRules[i]) === null || _sheetB$cssRules$i === void 0 ? void 0 : _sheetB$cssRules$i.cssText;
119
117
  if (ruleA !== ruleB) return false;
120
118
  }
121
-
122
119
  return true;
123
- } // Outputs in-memory CSSOM into their respective DOM nodes.
124
-
120
+ }
125
121
 
122
+ // Outputs in-memory CSSOM into their respective DOM nodes.
126
123
  function serializeCSSOM(dom, clone) {
127
124
  for (let styleSheet of dom.styleSheets) {
128
125
  if (isCSSOM(styleSheet)) {
@@ -146,26 +143,30 @@
146
143
  // Note: the `.toDataURL` API requires WebGL canvas elements to use
147
144
  // `preserveDrawingBuffer: true`. This is because `.toDataURL` uses the
148
145
  // drawing buffer, which is cleared after each render for WebGL by default.
149
- let dataUrl = canvas.toDataURL(); // skip empty canvases
146
+ let dataUrl = canvas.toDataURL();
150
147
 
151
- if (!dataUrl || dataUrl === 'data:,') continue; // create an image element in the cloned dom
148
+ // skip empty canvases
149
+ if (!dataUrl || dataUrl === 'data:,') continue;
152
150
 
151
+ // create an image element in the cloned dom
153
152
  let img = clone.createElement('img');
154
- img.src = dataUrl; // copy canvas element attributes to the image element such as style, class,
155
- // or data attributes that may be targeted by CSS
153
+ img.src = dataUrl;
156
154
 
155
+ // copy canvas element attributes to the image element such as style, class,
156
+ // or data attributes that may be targeted by CSS
157
157
  for (let {
158
158
  name,
159
159
  value
160
160
  } of canvas.attributes) {
161
161
  img.setAttribute(name, value);
162
- } // mark the image as serialized (can be targeted by CSS)
163
-
164
-
165
- img.setAttribute('data-percy-canvas-serialized', ''); // set a default max width to account for canvases that might resize with JS
162
+ }
166
163
 
167
- img.style.maxWidth = img.style.maxWidth || '100%'; // insert the image into the cloned DOM and remove the cloned canvas element
164
+ // mark the image as serialized (can be targeted by CSS)
165
+ img.setAttribute('data-percy-canvas-serialized', '');
166
+ // set a default max width to account for canvases that might resize with JS
167
+ img.style.maxWidth = img.style.maxWidth || '100%';
168
168
 
169
+ // insert the image into the cloned DOM and remove the cloned canvas element
169
170
  let percyElementId = canvas.getAttribute('data-percy-element-id');
170
171
  let cloneEl = clone.querySelector(`[data-percy-element-id=${percyElementId}]`);
171
172
  cloneEl.parentElement.insertBefore(img, cloneEl);
@@ -185,17 +186,17 @@
185
186
  let height = canvas.height = video.videoHeight;
186
187
  let dataUrl;
187
188
  canvas.getContext('2d').drawImage(video, 0, 0, width, height);
188
-
189
189
  try {
190
190
  dataUrl = canvas.toDataURL();
191
- } catch {} // If the canvas produces a blank image, skip
192
-
191
+ } catch {}
193
192
 
193
+ // If the canvas produces a blank image, skip
194
194
  if (!dataUrl || dataUrl === 'data:,') continue;
195
195
  cloneEl.setAttribute('poster', dataUrl);
196
196
  }
197
197
  }
198
198
 
199
+ // Returns a copy or new doctype for a document.
199
200
  function doctype(dom) {
200
201
  let {
201
202
  name = 'html',
@@ -203,7 +204,6 @@
203
204
  systemId = ''
204
205
  } = (dom === null || dom === void 0 ? void 0 : dom.doctype) ?? {};
205
206
  let deprecated = '';
206
-
207
207
  if (publicId && systemId) {
208
208
  deprecated = ` PUBLIC "${publicId}" "${systemId}"`;
209
209
  } else if (publicId) {
@@ -211,11 +211,10 @@
211
211
  } else if (systemId) {
212
212
  deprecated = ` SYSTEM "${systemId}"`;
213
213
  }
214
-
215
214
  return `<!DOCTYPE ${name}${deprecated}>`;
216
- } // Serializes a document and returns the resulting DOM string.
217
-
215
+ }
218
216
 
217
+ // Serializes a document and returns the resulting DOM string.
219
218
  function serializeDOM(options) {
220
219
  let {
221
220
  dom = document,
@@ -230,14 +229,11 @@
230
229
  enableJavaScript
231
230
  });
232
231
  serializeVideos(dom, clone);
233
-
234
232
  if (!enableJavaScript) {
235
233
  serializeCSSOM(dom, clone);
236
234
  serializeCanvas(dom, clone);
237
235
  }
238
-
239
236
  let doc = clone.documentElement;
240
-
241
237
  if (domTransformation) {
242
238
  try {
243
239
  domTransformation(doc);
@@ -245,7 +241,6 @@
245
241
  console.error('Could not transform the dom:', err.message);
246
242
  }
247
243
  }
248
-
249
244
  return doctype(dom) + doc.outerHTML;
250
245
  }
251
246
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/dom",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,5 +34,5 @@
34
34
  "devDependencies": {
35
35
  "interactor.js": "^2.0.0-beta.10"
36
36
  },
37
- "gitHead": "4303b74df91f60e36065141289d2ef2277d1d6fc"
37
+ "gitHead": "fd72688e449d6dd3eafd346fc07879cb3bb01a4e"
38
38
  }