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:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						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>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user