File size: 2,236 Bytes
30c32c8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * Convert a part of a mutation DOM to a mutation VM object, recursively.
 * @param {object} dom DOM object for mutation tag.
 * @return {object} Object representing useful parts of this mutation.
 */
const mutatorTagToObject = function (dom) {
    if (dom.tagName === '#text') return dom.textContent
    const parseChildren = (obj, dom) => {
        for (let i = 0; i < dom.children.length; i++) {
            obj.children.push(
                mutatorTagToObject(dom.children[i])
            );
        }
        return obj.children[0];
    };
    let obj = Object.create(null);
    obj.tagName = dom.tagName;
    obj.children = [];
    if (!dom.tagName) {
        console.warn('invalid dom; skiping to reading children');
        obj = parseChildren(obj, dom);
        return obj;
    }
    for (let idx = 0; idx < dom.attributes.length; idx++) {
        const attrib = dom.attributes[idx];
        const attribName = attrib.name;
        if (attribName === 'xmlns') continue;
        obj[attribName] = attrib.value;
        // Note: the capitalization of block info in the following lines is important.
        // The lowercase is read in from xml which normalizes case. The VM uses camel case everywhere else.
        if (attribName === 'blockinfo') {
            obj.blockInfo = JSON.parse(obj.blockinfo);
            delete obj.blockinfo;
        }
    }

    parseChildren(obj, dom);
    return obj;
};

/**
 * Adapter between mutator XML or DOM and block representation which can be
 * used by the Scratch runtime.
 * @param {(object|string)} mutation Mutation XML string or DOM.
 * @return {object} Object representing the mutation.
 */
const mutationAdpater = function (mutation) {
    let mutationParsed;
    // Check if the mutation is already parsed; if not, parse it.
    if (typeof mutation === 'object') {
        mutationParsed = mutation;
    } else {
        const parser = new DOMParser();
        const doc = parser.parseFromString(mutation, "application/xml");
        mutationParsed = doc;
        if (mutationParsed.nodeName === '#document') {
            mutationParsed = mutationParsed.children[0];
        }
    }
    
    return mutatorTagToObject(mutationParsed);
};

module.exports = mutationAdpater;