All files / virtual-dom/helpers nodeToVirtualNode.ts

87.5% Statements 35/40
75.86% Branches 22/29
100% Functions 5/5
87.18% Lines 34/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 1117x 7x 7x 7x                 7x   74x         74x   45x   45x   1x       44x   48x   21x       44x           29x   29x     29x           29x                   44x         44x   44x   19x     25x   25x   45x   45x     25x         44x         44x   44x   41x   40x   40x       43x      
import { EMPTY_ARRAY, EMPTY_OBJECT } from "../../utils/shared";
import { isBlankOrWhiteSpace } from "../../utils/string";
import ElementNode from "../nodes/ElementNode";
import TextNode from "../nodes/TextNode";
 
/**
 * Creates a virtual node form a DOM one
 * Removes any white space text node from the element if any bedore creating the virtual node
 * @param node 
 * @param options 
 * @returns 
 */
export default function nodeToVirtualNode(node?: Node, options: any = {}): ElementNode | TextNode | null {
 
    Iif (node === null) {
 
        return null;
    }
 
    if (node instanceof HTMLElement) {
 
        const tag = node.nodeName.toLowerCase();
 
        if (tag === 'script' && !options.allowScripts) {
 
            throw Error('Script elements are not allowed unless the allowScripts option is set to true');
        }
 
        // Remove any child text node with white spaces only from the node
        node.childNodes.forEach(n => {
 
            if (n instanceof Text && isBlankOrWhiteSpace((n as Text).textContent)) {
 
                node.removeChild(n);
            }
        });
 
        return new ElementNode(
            tag,
            getAttributes(node.attributes),
            getChildren(node.childNodes, options)
        );
    }
    else Eif (node instanceof Text) {
 
        const content = node.textContent || '';
 
        // Do not include text with white space characters ' ', '\t', '\r', '\n'
        Iif (options.excludeTextWithWhiteSpacesOnly && 
            isBlankOrWhiteSpace(content)) {
 
            return null;
        }
 
        return new TextNode(content);
    }
    else { // Ignore comments, also we don't expect converting from fragment documents
 
        return null;
    }
}
 
function getAttributes(attributes: NamedNodeMap) : Record<PropertyKey, any> {
 
    Iif (attributes === null) {
 
        return EMPTY_OBJECT;
    }
 
    const count = attributes.length;
 
    if (count == 0) {
 
        return null;
    }
 
    const props = {};
 
    for (let i = 0; i < attributes.length; i++) {
 
        const { name, value } = attributes[i];
 
        (props as any)[name] = value;
    }
 
    return props;
}
 
function getChildren(childNodes: NodeListOf<ChildNode>, options: any): (ElementNode | TextNode)[] {
 
    Iif (childNodes === undefined) {
 
        return EMPTY_ARRAY;
    }
 
    var vnodes: (ElementNode | TextNode)[] = [];
 
    childNodes.forEach(childNode => {
 
        const vnode = nodeToVirtualNode(childNode, options);
 
        Eif (vnode != null) {
 
            vnodes.push(vnode);
        }
    });
 
    return vnodes;
}