mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
fix: adopted stylesheets (#2785)
This commit is contained in:
parent
1cc853a318
commit
74696faf47
@ -2,12 +2,14 @@ import {Bounds} from '../css/layout/bounds';
|
||||
import {
|
||||
isBodyElement,
|
||||
isCanvasElement,
|
||||
isCustomElement,
|
||||
isElementNode,
|
||||
isHTMLElementNode,
|
||||
isIFrameElement,
|
||||
isImageElement,
|
||||
isScriptElement,
|
||||
isSelectElement,
|
||||
isSlotElement,
|
||||
isStyleElement,
|
||||
isSVGElementNode,
|
||||
isTextareaElement,
|
||||
@ -63,7 +65,7 @@ export class DocumentCloner {
|
||||
throw new Error('Cloned element does not have an owner document');
|
||||
}
|
||||
|
||||
this.documentElement = this.cloneNode(element.ownerDocument.documentElement) as HTMLElement;
|
||||
this.documentElement = this.cloneNode(element.ownerDocument.documentElement, false) as HTMLElement;
|
||||
}
|
||||
|
||||
toIFrame(ownerDocument: Document, windowSize: Bounds): Promise<HTMLIFrameElement> {
|
||||
@ -160,6 +162,17 @@ export class DocumentCloner {
|
||||
}
|
||||
}
|
||||
|
||||
if (isCustomElement(clone)) {
|
||||
return this.createCustomElementClone(clone);
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
createCustomElementClone(node: HTMLElement): HTMLElement {
|
||||
const clone = document.createElement('html2canvascustomelement');
|
||||
copyCSSStyles(node.style, clone);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
@ -231,7 +244,20 @@ export class DocumentCloner {
|
||||
return clonedCanvas;
|
||||
}
|
||||
|
||||
cloneNode(node: Node): Node {
|
||||
appendChildNode(clone: HTMLElement | SVGElement, child: Node, copyStyles: boolean): void {
|
||||
if (
|
||||
!isElementNode(child) ||
|
||||
(!isScriptElement(child) &&
|
||||
!child.hasAttribute(IGNORE_ATTRIBUTE) &&
|
||||
(typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child)))
|
||||
) {
|
||||
if (!this.options.copyStyles || !isElementNode(child) || !isStyleElement(child)) {
|
||||
clone.appendChild(this.cloneNode(child, copyStyles));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cloneNode(node: Node, copyStyles: boolean): Node {
|
||||
if (isTextNode(node)) {
|
||||
return document.createTextNode(node.data);
|
||||
}
|
||||
@ -260,16 +286,22 @@ export class DocumentCloner {
|
||||
const counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
|
||||
const before = this.resolvePseudoContent(node, clone, styleBefore, PseudoElementType.BEFORE);
|
||||
|
||||
for (let child = node.firstChild; child; child = child.nextSibling) {
|
||||
if (
|
||||
!isElementNode(child) ||
|
||||
(!isScriptElement(child) &&
|
||||
!child.hasAttribute(IGNORE_ATTRIBUTE) &&
|
||||
(typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child)))
|
||||
) {
|
||||
if (!this.options.copyStyles || !isElementNode(child) || !isStyleElement(child)) {
|
||||
clone.appendChild(this.cloneNode(child));
|
||||
if (isCustomElement(node)) {
|
||||
copyStyles = true;
|
||||
}
|
||||
|
||||
for (
|
||||
let child = node.shadowRoot ? node.shadowRoot.firstChild : node.firstChild;
|
||||
child;
|
||||
child = child.nextSibling
|
||||
) {
|
||||
if (isElementNode(child) && isSlotElement(child) && typeof child.assignedNodes === 'function') {
|
||||
const assignedNodes = child.assignedNodes() as ChildNode[];
|
||||
if (assignedNodes.length) {
|
||||
assignedNodes.forEach((assignedNode) => this.appendChildNode(clone, assignedNode, copyStyles));
|
||||
}
|
||||
} else {
|
||||
this.appendChildNode(clone, child, copyStyles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -284,7 +316,10 @@ export class DocumentCloner {
|
||||
|
||||
this.counters.pop(counters);
|
||||
|
||||
if (style && (this.options.copyStyles || isSVGElementNode(node)) && !isIFrameElement(node)) {
|
||||
if (
|
||||
(style && (this.options.copyStyles || isSVGElementNode(node)) && !isIFrameElement(node)) ||
|
||||
copyStyles
|
||||
) {
|
||||
copyCSSStyles(style, clone);
|
||||
}
|
||||
|
||||
|
@ -131,3 +131,5 @@ export const isScriptElement = (node: Element): node is HTMLScriptElement => nod
|
||||
export const isTextareaElement = (node: Element): node is HTMLTextAreaElement => node.tagName === 'TEXTAREA';
|
||||
export const isSelectElement = (node: Element): node is HTMLSelectElement => node.tagName === 'SELECT';
|
||||
export const isSlotElement = (node: Element): node is HTMLSlotElement => node.tagName === 'SLOT';
|
||||
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
|
||||
export const isCustomElement = (node: Element): node is HTMLElement => node.tagName.indexOf('-') > 0;
|
||||
|
@ -40,6 +40,10 @@ class AutonomousCustomElement extends HTMLElement {
|
||||
wrapper.appendChild(img);
|
||||
wrapper.appendChild(info);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.shadowRoot.adoptedStyleSheets = [sheet];
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('autonomous-custom-element', AutonomousCustomElement);
|
||||
|
@ -3,10 +3,11 @@
|
||||
<head>
|
||||
<title>Web components tests</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<script>
|
||||
const sheet = new CSSStyleSheet();
|
||||
sheet.replaceSync('* { color: red !important; }')
|
||||
</script>
|
||||
<script type="text/javascript" src="../../test.js"></script>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
Loading…
Reference in New Issue
Block a user