mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Render :before and :after pseudoelements
This commit is contained in:
parent
959b75a441
commit
b3db735415
@ -14,6 +14,8 @@ export const NodeParser = (
|
||||
const container = new NodeContainer(node, null, imageLoader);
|
||||
const stack = new StackingContext(container, null, true);
|
||||
|
||||
createPseudoHideStyles(node.ownerDocument);
|
||||
|
||||
if (__DEV__) {
|
||||
logger.log(`Starting node parsing`);
|
||||
}
|
||||
@ -28,6 +30,11 @@ export const NodeParser = (
|
||||
};
|
||||
|
||||
const IGNORED_NODE_NAMES = ['SCRIPT', 'HEAD', 'TITLE', 'OBJECT', 'BR', 'OPTION'];
|
||||
const URL_REGEXP = /^url\((.+)\)$/i;
|
||||
const PSEUDO_BEFORE = ':before';
|
||||
const PSEUDO_AFTER = ':after';
|
||||
const PSEUDO_HIDE_ELEMENT_CLASS_BEFORE = '___html2canvas___pseudoelement_before';
|
||||
const PSEUDO_HIDE_ELEMENT_CLASS_AFTER = '___html2canvas___pseudoelement_after';
|
||||
|
||||
const parseNodeTree = (
|
||||
node: HTMLElement,
|
||||
@ -46,7 +53,10 @@ const parseNodeTree = (
|
||||
} else if (childNode.nodeType === Node.ELEMENT_NODE) {
|
||||
if (IGNORED_NODE_NAMES.indexOf(childNode.nodeName) === -1) {
|
||||
const childElement = flowRefineToHTMLElement(childNode);
|
||||
inlinePseudoElement(childElement, PSEUDO_BEFORE);
|
||||
inlinePseudoElement(childElement, PSEUDO_AFTER);
|
||||
const container = new NodeContainer(childElement, parent, imageLoader);
|
||||
|
||||
if (container.isVisible()) {
|
||||
const treatAsRealStackingContext = createsRealStackingContext(
|
||||
container,
|
||||
@ -76,6 +86,43 @@ const parseNodeTree = (
|
||||
}
|
||||
};
|
||||
|
||||
const inlinePseudoElement = (node: HTMLElement, pseudoElt: ':before' | ':after'): void => {
|
||||
const style = node.ownerDocument.defaultView.getComputedStyle(node, pseudoElt);
|
||||
if (
|
||||
!style ||
|
||||
!style.content ||
|
||||
style.content === 'none' ||
|
||||
style.content === '-moz-alt-content' ||
|
||||
style.display === 'none'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const content = stripQuotes(style.content);
|
||||
const image = content.match(URL_REGEXP);
|
||||
const anonymousReplacedElement = node.ownerDocument.createElement(
|
||||
image ? 'img' : 'html2canvaspseudoelement'
|
||||
);
|
||||
if (image) {
|
||||
// $FlowFixMe
|
||||
anonymousReplacedElement.src = image[1];
|
||||
} else {
|
||||
anonymousReplacedElement.appendChild(node.ownerDocument.createTextNode(content));
|
||||
}
|
||||
|
||||
anonymousReplacedElement.style = style.cssText;
|
||||
anonymousReplacedElement.className = `${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE} ${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}`;
|
||||
node.className +=
|
||||
pseudoElt === PSEUDO_BEFORE
|
||||
? ` ${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}`
|
||||
: ` ${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}`;
|
||||
if (pseudoElt === PSEUDO_BEFORE) {
|
||||
node.insertBefore(anonymousReplacedElement, node.firstChild);
|
||||
} else {
|
||||
node.appendChild(anonymousReplacedElement);
|
||||
}
|
||||
};
|
||||
|
||||
const createsRealStackingContext = (container: NodeContainer, node: HTMLElement): boolean => {
|
||||
return (
|
||||
container.isRootElement() ||
|
||||
@ -100,3 +147,31 @@ const isBodyWithTransparentRoot = (container: NodeContainer, node: HTMLElement):
|
||||
|
||||
//$FlowFixMe
|
||||
const flowRefineToHTMLElement = (node: Node): HTMLElement => node;
|
||||
|
||||
const stripQuotes = (content: string): string => {
|
||||
const first = content.substr(0, 1);
|
||||
return first === content.substr(content.length - 1) && first.match(/['"]/)
|
||||
? content.substr(1, content.length - 2)
|
||||
: content;
|
||||
};
|
||||
|
||||
const PSEUDO_HIDE_ELEMENT_STYLE = `{
|
||||
content: "" !important;
|
||||
display: none !important;
|
||||
}`;
|
||||
|
||||
const createPseudoHideStyles = (document: Document) => {
|
||||
createStyles(
|
||||
document,
|
||||
`.${PSEUDO_HIDE_ELEMENT_CLASS_BEFORE}${PSEUDO_BEFORE}${PSEUDO_HIDE_ELEMENT_STYLE}
|
||||
.${PSEUDO_HIDE_ELEMENT_CLASS_AFTER}${PSEUDO_AFTER}${PSEUDO_HIDE_ELEMENT_STYLE}`
|
||||
);
|
||||
};
|
||||
|
||||
const createStyles = (document: Document, styles) => {
|
||||
const style = document.createElement('style');
|
||||
style.innerHTML = styles;
|
||||
if (document.body) {
|
||||
document.body.appendChild(style);
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user