@percy/dom
Advanced tools
Comparing version 1.19.2-alpha.0 to 1.19.2
@@ -13,3 +13,4 @@ (function() { | ||
dom, | ||
clone | ||
clone, | ||
warnings | ||
} = _ref; | ||
@@ -43,14 +44,2 @@ for (let elem of dom.querySelectorAll('input, textarea, select')) { | ||
} | ||
// find inputs inside shadow host and recursively serialize them. | ||
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeInputElements({ | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot | ||
}); | ||
} | ||
} | ||
} | ||
@@ -61,2 +50,3 @@ | ||
function setBaseURI(dom) { | ||
/* istanbul ignore if: sanity check */ | ||
if (!new URL(dom.baseURI).hostname) return; | ||
@@ -120,17 +110,2 @@ let $base = document.createElement('base'); | ||
} | ||
// find iframes inside shadow host and recursively serialize them. | ||
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeFrames({ | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot, | ||
warnings, | ||
resources, | ||
enableJavaScript | ||
}); | ||
} | ||
} | ||
} | ||
@@ -188,5 +163,3 @@ | ||
if (!disableShadowDOM && domElement.shadowRoot) { | ||
if (!domElement.getAttribute('data-percy-shadow-host')) { | ||
domElement.setAttribute('data-percy-shadow-host', ''); | ||
} | ||
domElement.setAttribute('data-percy-shadow-host', ''); | ||
if (!domElement.getAttribute('data-percy-element-id')) { | ||
@@ -214,4 +187,18 @@ domElement.setAttribute('data-percy-element-id', uid()); | ||
} | ||
function styleSheetFromNode(node) { | ||
/* istanbul ignore if: sanity check */ | ||
if (node.sheet) return node.sheet; | ||
// Outputs in-memory CSSOM into their respective DOM nodes. | ||
// Cloned style nodes don't have a sheet instance unless they are within | ||
// a document; we get it by temporarily adding the rules to DOM | ||
const tempStyle = document.createElement('style'); | ||
tempStyle.setAttribute('data-percy-style-helper', ''); | ||
tempStyle.innerHTML = node.innerHTML; | ||
const clone = document.cloneNode(); | ||
clone.appendChild(tempStyle); | ||
const sheet = tempStyle.sheet; | ||
// Cleanup node | ||
tempStyle.remove(); | ||
return sheet; | ||
} | ||
function serializeCSSOM(_ref) { | ||
@@ -221,16 +208,11 @@ let { | ||
clone, | ||
warnings, | ||
resources | ||
resources, | ||
cache | ||
} = _ref; | ||
let adoptedStylesMap = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; | ||
// in-memory CSSOM into their respective DOM nodes. | ||
for (let styleSheet of dom.styleSheets) { | ||
if (isCSSOM(styleSheet)) { | ||
let styleId = styleSheet.ownerNode.getAttribute('data-percy-element-id'); | ||
if (!styleId) { | ||
let attributes = Array.from(styleSheet.ownerNode.attributes).map(attr => `${attr.name}: ${attr.value}`); | ||
warnings.add(`stylesheet with attributes - [ ${attributes} ] - was not serialized`); | ||
continue; | ||
} | ||
let cloneOwnerNode = clone.querySelector(`[data-percy-element-id="${styleId}"]`); | ||
if (styleSheetsMatch(styleSheet, cloneOwnerNode.sheet)) continue; | ||
if (styleSheetsMatch(styleSheet, styleSheetFromNode(cloneOwnerNode))) continue; | ||
let style = document.createElement('style'); | ||
@@ -246,18 +228,18 @@ style.type = 'text/css'; | ||
// clone stylesheets in shadowRoot | ||
// https://github.com/WICG/construct-stylesheets/issues/93 | ||
if (!adoptedStylesMap) { | ||
adoptedStylesMap = new Map(); | ||
} | ||
// clone Adopted Stylesheets | ||
// Regarding ordering of the adopted stylesheets - https://github.com/WICG/construct-stylesheets/issues/93 | ||
for (let sheet of dom.adoptedStyleSheets) { | ||
const styleLink = document.createElement('link'); | ||
styleLink.setAttribute('rel', 'stylesheet'); | ||
if (!adoptedStylesMap.has(sheet)) { | ||
if (!cache.has(sheet)) { | ||
const styles = Array.from(sheet.cssRules).map(cssRule => cssRule.cssText).join('\n'); | ||
let resource = resourceFromText(uid(), 'text/css', styles); | ||
resources.add(resource); | ||
adoptedStylesMap.set(sheet, resource.url); | ||
cache.set(sheet, resource.url); | ||
} | ||
styleLink.setAttribute('data-percy-serialized-attribute-href', adoptedStylesMap.get(sheet)); | ||
if (clone.constructor.name === 'HTMLDocument') { | ||
styleLink.setAttribute('data-percy-adopted-stylesheets-serialized', 'true'); | ||
styleLink.setAttribute('data-percy-serialized-attribute-href', cache.get(sheet)); | ||
/* istanbul ignore next: tested, but coverage is stripped */ | ||
if (clone.constructor.name === 'HTMLDocument' || clone.constructor.name === 'DocumentFragment') { | ||
// handle document and iframe | ||
@@ -269,15 +251,2 @@ clone.body.prepend(styleLink); | ||
} | ||
// find stylesheets inside shadow host and recursively serialize them. | ||
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeCSSOM({ | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot, | ||
resources | ||
}, adoptedStylesMap); | ||
} | ||
} | ||
} | ||
@@ -335,15 +304,2 @@ | ||
} | ||
// find canvas inside shadow host and recursively serialize them. | ||
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeCanvas({ | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot, | ||
resources | ||
}); | ||
} | ||
} | ||
} | ||
@@ -385,16 +341,2 @@ | ||
} | ||
// find video inside shadow host and recursively serialize them. | ||
for (let shadowHost of dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeVideos({ | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot, | ||
resources, | ||
warnings | ||
}); | ||
} | ||
} | ||
} | ||
@@ -451,9 +393,7 @@ | ||
const cloneNodeAndShadow = ctx => { | ||
let cloneDocumentElement = deepClone(ctx.dom.documentElement, ctx.disableShadowDOM); | ||
// TODO: we're not properly appending documentElement (html node) in the clone document, this can cause side effects in original document. | ||
// convert document fragment to document object | ||
let cloneDocument = ctx.dom.cloneNode(); | ||
// dissolve document fragment in clone document | ||
cloneDocument.appendChild(cloneDocumentElement); | ||
return cloneDocument; | ||
let cloneDocumentFragment = deepClone(ctx.dom.documentElement, ctx.disableShadowDOM); | ||
cloneDocumentFragment.documentElement = cloneDocumentFragment.firstChild; | ||
cloneDocumentFragment.head = cloneDocumentFragment.querySelector('head'); | ||
cloneDocumentFragment.body = cloneDocumentFragment.querySelector('body'); | ||
return cloneDocumentFragment; | ||
}; | ||
@@ -481,3 +421,3 @@ | ||
let clone = ctx.clone; | ||
let scriptEl = clone.createElement('script'); | ||
let scriptEl = document.createElement('script'); | ||
scriptEl.setAttribute('id', '__percy_shadowdom_helper'); | ||
@@ -534,2 +474,24 @@ scriptEl.setAttribute('data-percy-injected', true); | ||
} | ||
function serializeElements(ctx) { | ||
serializeInputElements(ctx); | ||
serializeFrames(ctx); | ||
serializeVideos(ctx); | ||
if (!ctx.enableJavaScript) { | ||
serializeCSSOM(ctx); | ||
serializeCanvas(ctx); | ||
} | ||
for (const shadowHost of ctx.dom.querySelectorAll('[data-percy-shadow-host]')) { | ||
let percyElementId = shadowHost.getAttribute('data-percy-element-id'); | ||
let cloneShadowHost = ctx.clone.querySelector(`[data-percy-element-id="${percyElementId}"]`); | ||
if (shadowHost.shadowRoot && cloneShadowHost.shadowRoot) { | ||
serializeElements({ | ||
...ctx, | ||
dom: shadowHost.shadowRoot, | ||
clone: cloneShadowHost.shadowRoot | ||
}); | ||
} else { | ||
ctx.warnings.add('data-percy-shadow-host does not have shadowRoot'); | ||
} | ||
} | ||
} | ||
@@ -551,2 +513,3 @@ // Serializes a document and returns the resulting DOM string. | ||
warnings: new Set(), | ||
cache: new Map(), | ||
enableJavaScript, | ||
@@ -557,9 +520,3 @@ disableShadowDOM | ||
ctx.clone = cloneNodeAndShadow(ctx); | ||
serializeInputElements(ctx); | ||
serializeFrames(ctx); | ||
serializeVideos(ctx); | ||
if (!enableJavaScript) { | ||
serializeCSSOM(ctx); | ||
serializeCanvas(ctx); | ||
} | ||
serializeElements(ctx); | ||
if (domTransformation) { | ||
@@ -566,0 +523,0 @@ try { |
{ | ||
"name": "@percy/dom", | ||
"version": "1.19.2-alpha.0", | ||
"version": "1.19.2", | ||
"license": "MIT", | ||
@@ -37,3 +37,3 @@ "repository": { | ||
}, | ||
"gitHead": "d9bf82889731f5cdc3f7fa4fe836cc5232ee8fb6" | ||
"gitHead": "609ae53aa84ab2f7054a21214b36dccd71025780" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
26608
4
485