@percy/dom 1.31.1 → 1.31.2-beta.1
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 +1 -1
- package/dist/bundle.js +71 -35
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ to a new stylesheet inserted into the document's head.
|
|
|
65
65
|
Canvas elements' drawing buffers are serialized as data URIs and the canvas elements are replaced
|
|
66
66
|
with image elements. The image elements reference the serialized data URI and have the same HTML
|
|
67
67
|
attributes as their respective canvas elements. The image elements also have a max-width of 100% to
|
|
68
|
-
|
|
68
|
+
accommodate responsive layouts in situations where canvases may be expected to resize with JS.
|
|
69
69
|
|
|
70
70
|
### Video elements
|
|
71
71
|
|
package/dist/bundle.js
CHANGED
|
@@ -336,14 +336,50 @@
|
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
// Helper function to create and insert image element
|
|
340
|
+
function createAndInsertImageElement(canvas, clone, percyElementId, imageUrl) {
|
|
341
|
+
let img = document.createElement('img');
|
|
342
|
+
|
|
343
|
+
// copy canvas element attributes to the image element
|
|
344
|
+
for (let {
|
|
345
|
+
name,
|
|
346
|
+
value
|
|
347
|
+
} of canvas.attributes) {
|
|
348
|
+
img.setAttribute(name, value);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// mark the image as serialized and set src attribute
|
|
352
|
+
img.setAttribute('data-percy-canvas-serialized', '');
|
|
353
|
+
img.setAttribute('data-percy-serialized-attribute-src', imageUrl);
|
|
354
|
+
|
|
355
|
+
// set a default max width to account for canvases that might resize with JS
|
|
356
|
+
img.style.maxWidth = img.style.maxWidth || '100%';
|
|
357
|
+
|
|
358
|
+
// insert the image into the cloned DOM and remove the cloned canvas element
|
|
359
|
+
let cloneEl = clone.querySelector(`[data-percy-element-id=${percyElementId}]`);
|
|
360
|
+
if (!cloneEl) {
|
|
361
|
+
throw new Error(`Clone element not found for percy-element-id: ${percyElementId}`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// `parentElement` for elements directly under shadow root is `null` -> Incase of Nested Shadow DOM.
|
|
365
|
+
if (cloneEl.parentElement) {
|
|
366
|
+
cloneEl.parentElement.insertBefore(img, cloneEl);
|
|
367
|
+
} else {
|
|
368
|
+
clone.insertBefore(img, cloneEl);
|
|
369
|
+
}
|
|
370
|
+
cloneEl.remove();
|
|
371
|
+
}
|
|
372
|
+
|
|
339
373
|
// Serialize in-memory canvas elements into images.
|
|
340
374
|
function serializeCanvas(ctx) {
|
|
341
375
|
let {
|
|
342
376
|
dom,
|
|
343
377
|
clone,
|
|
344
|
-
resources
|
|
378
|
+
resources,
|
|
379
|
+
ignoreCanvasSerializationErrors
|
|
345
380
|
} = ctx;
|
|
346
381
|
for (let canvas of dom.querySelectorAll('canvas')) {
|
|
382
|
+
let percyElementId = canvas.getAttribute('data-percy-element-id');
|
|
347
383
|
try {
|
|
348
384
|
// Note: the `.toDataURL` API requires WebGL canvas elements to use
|
|
349
385
|
// `preserveDrawingBuffer: true`. This is because `.toDataURL` uses the
|
|
@@ -353,41 +389,25 @@
|
|
|
353
389
|
// skip empty canvases
|
|
354
390
|
if (!dataUrl || dataUrl === 'data:,') continue;
|
|
355
391
|
|
|
356
|
-
//
|
|
357
|
-
let percyElementId = canvas.getAttribute('data-percy-element-id');
|
|
392
|
+
// create a resource for the canvas data
|
|
358
393
|
let resource = resourceFromDataURL(percyElementId, dataUrl);
|
|
359
394
|
resources.add(resource);
|
|
360
395
|
|
|
361
|
-
// create
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// mark the image as serialized (can be targeted by CSS)
|
|
376
|
-
img.setAttribute('data-percy-canvas-serialized', '');
|
|
377
|
-
// set a default max width to account for canvases that might resize with JS
|
|
378
|
-
img.style.maxWidth = img.style.maxWidth || '100%';
|
|
379
|
-
|
|
380
|
-
// insert the image into the cloned DOM and remove the cloned canvas element
|
|
381
|
-
let cloneEl = clone.querySelector(`[data-percy-element-id=${percyElementId}]`);
|
|
382
|
-
// `parentElement` for elements directly under shadow root is `null` -> Incase of Nested Shadow DOM.
|
|
383
|
-
if (cloneEl.parentElement) {
|
|
384
|
-
cloneEl.parentElement.insertBefore(img, cloneEl);
|
|
396
|
+
// create and insert image element with the resource URL
|
|
397
|
+
createAndInsertImageElement(canvas, clone, percyElementId, resource.url);
|
|
398
|
+
} catch (err) {
|
|
399
|
+
if (ignoreCanvasSerializationErrors) {
|
|
400
|
+
try {
|
|
401
|
+
// create and insert image element with empty src
|
|
402
|
+
ctx.warnings.add('Canvas Serialization failed, Replaced canvas with empty Image');
|
|
403
|
+
ctx.warnings.add('Error: ' + err.message);
|
|
404
|
+
createAndInsertImageElement(canvas, clone, percyElementId, '');
|
|
405
|
+
} catch (fallbackErr) {
|
|
406
|
+
ctx.warnings.add('Error creating fallback image element: ' + fallbackErr.message);
|
|
407
|
+
}
|
|
385
408
|
} else {
|
|
386
|
-
|
|
409
|
+
handleErrors(err, 'Error serializing canvas element: ', canvas);
|
|
387
410
|
}
|
|
388
|
-
cloneEl.remove();
|
|
389
|
-
} catch (err) {
|
|
390
|
-
handleErrors(err, 'Error serializing canvas element: ', canvas);
|
|
391
411
|
}
|
|
392
412
|
}
|
|
393
413
|
}
|
|
@@ -439,10 +459,24 @@
|
|
|
439
459
|
if (!['img', 'iframe'].includes((_domElement$tagName = domElement.tagName) === null || _domElement$tagName === void 0 ? void 0 : _domElement$tagName.toLowerCase())) return;
|
|
440
460
|
domElement.removeAttribute('loading');
|
|
441
461
|
}
|
|
462
|
+
function serializeScrollState(original, clone) {
|
|
463
|
+
if (!original || !clone) return;
|
|
464
|
+
|
|
465
|
+
// Check and set scrollTop if it exists and has a value
|
|
466
|
+
if (typeof original.scrollTop === 'number' && original.scrollTop !== 0) {
|
|
467
|
+
clone.setAttribute('data-percy-scrolltop', original.scrollTop.toString());
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Check and set scrollLeft if it exists and has a value
|
|
471
|
+
if (typeof original.scrollLeft === 'number' && original.scrollLeft !== 0) {
|
|
472
|
+
clone.setAttribute('data-percy-scrollleft', original.scrollLeft.toString());
|
|
473
|
+
}
|
|
474
|
+
}
|
|
442
475
|
|
|
443
476
|
// All transformations that we need to apply for a successful discovery and stable render
|
|
444
|
-
function applyElementTransformations(domElement) {
|
|
477
|
+
function applyElementTransformations(originalElement, domElement) {
|
|
445
478
|
dropLoadingAttribute(domElement);
|
|
479
|
+
serializeScrollState(originalElement, domElement);
|
|
446
480
|
}
|
|
447
481
|
|
|
448
482
|
let mimetype = null;
|
|
@@ -572,7 +606,7 @@
|
|
|
572
606
|
}
|
|
573
607
|
|
|
574
608
|
// We apply any element transformations here to avoid another treeWalk
|
|
575
|
-
applyElementTransformations(clone);
|
|
609
|
+
applyElementTransformations(node, clone);
|
|
576
610
|
serializeBase64(clone, resources, cache);
|
|
577
611
|
parent.appendChild(clone);
|
|
578
612
|
|
|
@@ -729,7 +763,8 @@
|
|
|
729
763
|
domTransformation = options === null || options === void 0 ? void 0 : options.dom_transformation,
|
|
730
764
|
stringifyResponse = options === null || options === void 0 ? void 0 : options.stringify_response,
|
|
731
765
|
disableShadowDOM = options === null || options === void 0 ? void 0 : options.disable_shadow_dom,
|
|
732
|
-
reshuffleInvalidTags = options === null || options === void 0 ? void 0 : options.reshuffle_invalid_tags
|
|
766
|
+
reshuffleInvalidTags = options === null || options === void 0 ? void 0 : options.reshuffle_invalid_tags,
|
|
767
|
+
ignoreCanvasSerializationErrors = options === null || options === void 0 ? void 0 : options.ignore_canvas_serialization_errors
|
|
733
768
|
} = options || {};
|
|
734
769
|
|
|
735
770
|
// keep certain records throughout serialization
|
|
@@ -740,7 +775,8 @@
|
|
|
740
775
|
cache: new Map(),
|
|
741
776
|
shadowRootElements: [],
|
|
742
777
|
enableJavaScript,
|
|
743
|
-
disableShadowDOM
|
|
778
|
+
disableShadowDOM,
|
|
779
|
+
ignoreCanvasSerializationErrors
|
|
744
780
|
};
|
|
745
781
|
ctx.dom = dom;
|
|
746
782
|
ctx.clone = cloneNodeAndShadow(ctx);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@percy/dom",
|
|
3
|
-
"version": "1.31.1",
|
|
3
|
+
"version": "1.31.2-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
"publishConfig": {
|
|
11
11
|
"access": "public",
|
|
12
|
-
"tag": "
|
|
12
|
+
"tag": "beta"
|
|
13
13
|
},
|
|
14
14
|
"main": "dist/bundle.js",
|
|
15
15
|
"browser": "dist/bundle.js",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"interactor.js": "^2.0.0-beta.10"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "c8ba03fdd3ab7543f741a68eb5c357e38b48129e"
|
|
39
39
|
}
|