import map from 'licia/map';
import filter from 'licia/filter';
import each from 'licia/each';
import trim from 'licia/trim';
import contain from 'licia/contain';
const nodes = new Map();
const nodeIds = new Map();
let id = 1;
export function getOrCreateNodeId(node: any) {
let nodeId = nodeIds.get(node);
if (nodeId) return nodeId;
nodeId = id++;
nodeIds.set(node, nodeId);
nodes.set(nodeId, node);
return nodeId;
}
export function clear() {
nodes.clear();
nodeIds.clear();
}
export function getNodeId(node: any) {
return nodeIds.get(node);
}
export function wrap(node: any, { depth = 1 } = {}) {
const nodeId = getOrCreateNodeId(node);
const ret: any = {
nodeName: node.nodeName,
nodeType: node.nodeType,
localName: node.localName || '',
nodeValue: node.nodeValue || '',
nodeId,
backendNodeId: nodeId,
};
if (node.parentNode) {
ret.parentId = getOrCreateNodeId(node.parentNode);
}
if (node.attributes) {
const attributes: string[] = [];
each(node.attributes, ({ name, value }) => attributes.push(name, value));
ret.attributes = attributes;
}
const childNodes = filterNodes(node.childNodes);
ret.childNodeCount = childNodes.length;
const hasOneTextNode =
ret.childNodeCount === 1 && childNodes[0].nodeType === 3;
if (depth > 0 || hasOneTextNode) {
ret.children = getChildNodes(node, depth);
}
return ret;
}
export function getChildNodes(node: any, depth: number) {
const childNodes = filterNodes(node.childNodes);
return map(childNodes, node => wrap(node, { depth: depth - 1 }));
}
export function getPreviousNode(node: any) {
let previousNode = node.previousSibling;
if (!previousNode) return;
while (!isValidNode(previousNode) && previousNode.previousSibling) {
previousNode = previousNode.previousSibling;
}
if (previousNode && isValidNode(previousNode)) {
return previousNode;
}
}
export function filterNodes(childNodes: any[]) {
return filter(childNodes, (node: any) => isValidNode(node));
}
function isValidNode(node: Node) {
if (node.nodeType === 1) {
const className = (node as Element).getAttribute('class') || '';
if (contain(className, '__chii-hide__')) return false;
}
return !(node.nodeType === 3 && trim(node.nodeValue || '') === '');
}
export function getNode(nodeId: number) {
return nodes.get(nodeId);
}