86 lines
2.9 KiB
JavaScript
86 lines
2.9 KiB
JavaScript
import { drawDomElement } from './drawing/draw-dom-element';
|
|
import { processNode } from './drawing/process-node';
|
|
import { handleTextNode } from './drawing/text/handle-text-node';
|
|
import { createTreeWalkerCleanupAfterChildren } from './tree-walker-cleanup-after-children';
|
|
import { skipToNextNonDescendant } from './walk-tree';
|
|
const walkOverNode = ({ node, context, logLevel, parentRect, internalState, rootElement, onlyBackgroundClip, }) => {
|
|
if (node instanceof HTMLElement || node instanceof SVGElement) {
|
|
return processNode({
|
|
element: node,
|
|
context,
|
|
draw: drawDomElement(node),
|
|
logLevel,
|
|
parentRect,
|
|
internalState,
|
|
rootElement,
|
|
});
|
|
}
|
|
if (node instanceof Text) {
|
|
return handleTextNode({
|
|
node,
|
|
context,
|
|
logLevel,
|
|
parentRect,
|
|
internalState,
|
|
rootElement,
|
|
onlyBackgroundClip,
|
|
});
|
|
}
|
|
throw new Error('Unknown node type');
|
|
};
|
|
const getFilterFunction = (node) => {
|
|
if (!(node instanceof Element)) {
|
|
// Must be a text node!
|
|
return NodeFilter.FILTER_ACCEPT;
|
|
}
|
|
// SVG does have children, but we process SVG elements in its
|
|
// entirety
|
|
if (node.parentElement instanceof SVGSVGElement) {
|
|
return NodeFilter.FILTER_REJECT;
|
|
}
|
|
const computedStyle = getComputedStyle(node);
|
|
if (computedStyle.display === 'none') {
|
|
return NodeFilter.FILTER_REJECT;
|
|
}
|
|
return NodeFilter.FILTER_ACCEPT;
|
|
};
|
|
export const compose = async ({ element, context, logLevel, parentRect, internalState, onlyBackgroundClip, }) => {
|
|
const treeWalker = document.createTreeWalker(element, onlyBackgroundClip
|
|
? NodeFilter.SHOW_TEXT
|
|
: NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, getFilterFunction);
|
|
// Skip to the first text node
|
|
if (onlyBackgroundClip) {
|
|
treeWalker.nextNode();
|
|
if (!treeWalker.currentNode) {
|
|
return;
|
|
}
|
|
}
|
|
const { checkCleanUpAtBeginningOfIteration, addCleanup, cleanupInTheEndOfTheIteration, } = createTreeWalkerCleanupAfterChildren(treeWalker);
|
|
while (true) {
|
|
checkCleanUpAtBeginningOfIteration();
|
|
const val = await walkOverNode({
|
|
node: treeWalker.currentNode,
|
|
context,
|
|
logLevel,
|
|
parentRect,
|
|
internalState,
|
|
rootElement: element,
|
|
onlyBackgroundClip,
|
|
});
|
|
if (val.type === 'skip-children') {
|
|
if (!skipToNextNonDescendant(treeWalker)) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
if (val.cleanupAfterChildren) {
|
|
addCleanup(treeWalker.currentNode, val.cleanupAfterChildren);
|
|
}
|
|
if (!treeWalker.nextNode()) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
cleanupInTheEndOfTheIteration();
|
|
};
|