All files / src/renderer createNodePatcherRules.ts

100% Statements 27/27
100% Branches 12/12
100% Functions 2/2
100% Lines 25/25

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 10618x                                                             18x       309x       309x   309x   51x         51x   258x   70x       188x   188x   82x       188x   254x     188x             82x   82x   112x   112x   59x   59x           53x   10x   10x               82x  
import { attributeMarkerPrefix, endMarker, eventMarkerPrefix, NodePatcherRuleTypes } from "./createTemplate";
 
/**
 * The rule to "compile" to patch the DOM node
 */
export interface NodePatcherRule {
 
    /**
     * The type of patching to do to that node
     */
    type: NodePatcherRuleTypes;
 
    /**
     * The path to locate the node
     */
    path: number[];
 
    /**
     * The name of the attribute to patch
     * Only populated if it is an attribute or an event
     */
    name?: string;
}
 
/**
 * Creates the rules for the node patcher
 * @param node 
 * @param path 
 * @param rules 
 * @returns 
 */
export default function createNodePatcherRules(node: Node, path: number[] = [], rules: NodePatcherRule[] = []): NodePatcherRule[] {
 
    const {
        childNodes
    } = node;
 
    const {
        length
    } = childNodes;
 
    if ((node as Text).data === endMarker) {
 
        rules.push({
            type: NodePatcherRuleTypes.PATCH_NODE,
            path: [...path]
        });
 
        return rules; // Comments do not have attributes and children so we are done
    }
    else if (node.nodeType === Node.TEXT_NODE) {
 
        return rules; // No need to create rules for a text literal
    }
    else {
 
        const attributes = (node as HTMLElement).attributes;
 
        if (attributes !== undefined) {
 
            rules = createAttributePatcherRules(attributes, path, rules);
        }
    }
 
    for (let i = 0; i < length; ++i) {
 
        rules = createNodePatcherRules(childNodes[i], [...path, i], rules);
    }
 
    return rules;
}
 
function createAttributePatcherRules(attributes: NamedNodeMap, path: number[], rules: NodePatcherRule[]): NodePatcherRule[] {
 
    const {
        length
    } = attributes;
 
    for (let i = 0; i < length; ++i) {
 
        const value = attributes[i].value;
 
        if (value.startsWith(attributeMarkerPrefix)) {
 
            const name = value.split(':')[1];
 
            rules.push({
                type: NodePatcherRuleTypes.PATCH_ATTRIBUTE,
                path,
                name
            });
        }
        else if (value.startsWith(eventMarkerPrefix)) {
 
            const name = value.split(':')[1];
 
            rules.push({
                type: NodePatcherRuleTypes.PATCH_EVENT,
                path,
                name
            });
        }
    }
 
    return rules;
}