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 {
|
import {
|
||||||
isBodyElement,
|
isBodyElement,
|
||||||
isCanvasElement,
|
isCanvasElement,
|
||||||
|
isCustomElement,
|
||||||
isElementNode,
|
isElementNode,
|
||||||
isHTMLElementNode,
|
isHTMLElementNode,
|
||||||
isIFrameElement,
|
isIFrameElement,
|
||||||
isImageElement,
|
isImageElement,
|
||||||
isScriptElement,
|
isScriptElement,
|
||||||
isSelectElement,
|
isSelectElement,
|
||||||
|
isSlotElement,
|
||||||
isStyleElement,
|
isStyleElement,
|
||||||
isSVGElementNode,
|
isSVGElementNode,
|
||||||
isTextareaElement,
|
isTextareaElement,
|
||||||
@ -63,7 +65,7 @@ export class DocumentCloner {
|
|||||||
throw new Error('Cloned element does not have an owner document');
|
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> {
|
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;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +244,20 @@ export class DocumentCloner {
|
|||||||
return clonedCanvas;
|
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)) {
|
if (isTextNode(node)) {
|
||||||
return document.createTextNode(node.data);
|
return document.createTextNode(node.data);
|
||||||
}
|
}
|
||||||
@ -260,16 +286,22 @@ export class DocumentCloner {
|
|||||||
const counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
|
const counters = this.counters.parse(new CSSParsedCounterDeclaration(this.context, style));
|
||||||
const before = this.resolvePseudoContent(node, clone, styleBefore, PseudoElementType.BEFORE);
|
const before = this.resolvePseudoContent(node, clone, styleBefore, PseudoElementType.BEFORE);
|
||||||
|
|
||||||
for (let child = node.firstChild; child; child = child.nextSibling) {
|
if (isCustomElement(node)) {
|
||||||
if (
|
copyStyles = true;
|
||||||
!isElementNode(child) ||
|
}
|
||||||
(!isScriptElement(child) &&
|
|
||||||
!child.hasAttribute(IGNORE_ATTRIBUTE) &&
|
for (
|
||||||
(typeof this.options.ignoreElements !== 'function' || !this.options.ignoreElements(child)))
|
let child = node.shadowRoot ? node.shadowRoot.firstChild : node.firstChild;
|
||||||
) {
|
child;
|
||||||
if (!this.options.copyStyles || !isElementNode(child) || !isStyleElement(child)) {
|
child = child.nextSibling
|
||||||
clone.appendChild(this.cloneNode(child));
|
) {
|
||||||
|
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);
|
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);
|
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 isTextareaElement = (node: Element): node is HTMLTextAreaElement => node.tagName === 'TEXTAREA';
|
||||||
export const isSelectElement = (node: Element): node is HTMLSelectElement => node.tagName === 'SELECT';
|
export const isSelectElement = (node: Element): node is HTMLSelectElement => node.tagName === 'SELECT';
|
||||||
export const isSlotElement = (node: Element): node is HTMLSlotElement => node.tagName === 'SLOT';
|
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(img);
|
||||||
wrapper.appendChild(info);
|
wrapper.appendChild(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.shadowRoot.adoptedStyleSheets = [sheet];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define('autonomous-custom-element', AutonomousCustomElement);
|
customElements.define('autonomous-custom-element', AutonomousCustomElement);
|
||||||
|
@ -3,10 +3,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Web components tests</title>
|
<title>Web components tests</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<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>
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user