218 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						|
 | 
						|
const { DOCUMENT_MODE } = require('../common/html');
 | 
						|
 | 
						|
//Node construction
 | 
						|
exports.createDocument = function() {
 | 
						|
    return {
 | 
						|
        nodeName: '#document',
 | 
						|
        mode: DOCUMENT_MODE.NO_QUIRKS,
 | 
						|
        childNodes: []
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.createDocumentFragment = function() {
 | 
						|
    return {
 | 
						|
        nodeName: '#document-fragment',
 | 
						|
        childNodes: []
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.createElement = function(tagName, namespaceURI, attrs) {
 | 
						|
    return {
 | 
						|
        nodeName: tagName,
 | 
						|
        tagName: tagName,
 | 
						|
        attrs: attrs,
 | 
						|
        namespaceURI: namespaceURI,
 | 
						|
        childNodes: [],
 | 
						|
        parentNode: null
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.createCommentNode = function(data) {
 | 
						|
    return {
 | 
						|
        nodeName: '#comment',
 | 
						|
        data: data,
 | 
						|
        parentNode: null
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
const createTextNode = function(value) {
 | 
						|
    return {
 | 
						|
        nodeName: '#text',
 | 
						|
        value: value,
 | 
						|
        parentNode: null
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
//Tree mutation
 | 
						|
const appendChild = (exports.appendChild = function(parentNode, newNode) {
 | 
						|
    parentNode.childNodes.push(newNode);
 | 
						|
    newNode.parentNode = parentNode;
 | 
						|
});
 | 
						|
 | 
						|
const insertBefore = (exports.insertBefore = function(parentNode, newNode, referenceNode) {
 | 
						|
    const insertionIdx = parentNode.childNodes.indexOf(referenceNode);
 | 
						|
 | 
						|
    parentNode.childNodes.splice(insertionIdx, 0, newNode);
 | 
						|
    newNode.parentNode = parentNode;
 | 
						|
});
 | 
						|
 | 
						|
exports.setTemplateContent = function(templateElement, contentElement) {
 | 
						|
    templateElement.content = contentElement;
 | 
						|
};
 | 
						|
 | 
						|
exports.getTemplateContent = function(templateElement) {
 | 
						|
    return templateElement.content;
 | 
						|
};
 | 
						|
 | 
						|
exports.setDocumentType = function(document, name, publicId, systemId) {
 | 
						|
    let doctypeNode = null;
 | 
						|
 | 
						|
    for (let i = 0; i < document.childNodes.length; i++) {
 | 
						|
        if (document.childNodes[i].nodeName === '#documentType') {
 | 
						|
            doctypeNode = document.childNodes[i];
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if (doctypeNode) {
 | 
						|
        doctypeNode.name = name;
 | 
						|
        doctypeNode.publicId = publicId;
 | 
						|
        doctypeNode.systemId = systemId;
 | 
						|
    } else {
 | 
						|
        appendChild(document, {
 | 
						|
            nodeName: '#documentType',
 | 
						|
            name: name,
 | 
						|
            publicId: publicId,
 | 
						|
            systemId: systemId
 | 
						|
        });
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
exports.setDocumentMode = function(document, mode) {
 | 
						|
    document.mode = mode;
 | 
						|
};
 | 
						|
 | 
						|
exports.getDocumentMode = function(document) {
 | 
						|
    return document.mode;
 | 
						|
};
 | 
						|
 | 
						|
exports.detachNode = function(node) {
 | 
						|
    if (node.parentNode) {
 | 
						|
        const idx = node.parentNode.childNodes.indexOf(node);
 | 
						|
 | 
						|
        node.parentNode.childNodes.splice(idx, 1);
 | 
						|
        node.parentNode = null;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
exports.insertText = function(parentNode, text) {
 | 
						|
    if (parentNode.childNodes.length) {
 | 
						|
        const prevNode = parentNode.childNodes[parentNode.childNodes.length - 1];
 | 
						|
 | 
						|
        if (prevNode.nodeName === '#text') {
 | 
						|
            prevNode.value += text;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    appendChild(parentNode, createTextNode(text));
 | 
						|
};
 | 
						|
 | 
						|
exports.insertTextBefore = function(parentNode, text, referenceNode) {
 | 
						|
    const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
 | 
						|
 | 
						|
    if (prevNode && prevNode.nodeName === '#text') {
 | 
						|
        prevNode.value += text;
 | 
						|
    } else {
 | 
						|
        insertBefore(parentNode, createTextNode(text), referenceNode);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
exports.adoptAttributes = function(recipient, attrs) {
 | 
						|
    const recipientAttrsMap = [];
 | 
						|
 | 
						|
    for (let i = 0; i < recipient.attrs.length; i++) {
 | 
						|
        recipientAttrsMap.push(recipient.attrs[i].name);
 | 
						|
    }
 | 
						|
 | 
						|
    for (let j = 0; j < attrs.length; j++) {
 | 
						|
        if (recipientAttrsMap.indexOf(attrs[j].name) === -1) {
 | 
						|
            recipient.attrs.push(attrs[j]);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
//Tree traversing
 | 
						|
exports.getFirstChild = function(node) {
 | 
						|
    return node.childNodes[0];
 | 
						|
};
 | 
						|
 | 
						|
exports.getChildNodes = function(node) {
 | 
						|
    return node.childNodes;
 | 
						|
};
 | 
						|
 | 
						|
exports.getParentNode = function(node) {
 | 
						|
    return node.parentNode;
 | 
						|
};
 | 
						|
 | 
						|
exports.getAttrList = function(element) {
 | 
						|
    return element.attrs;
 | 
						|
};
 | 
						|
 | 
						|
//Node data
 | 
						|
exports.getTagName = function(element) {
 | 
						|
    return element.tagName;
 | 
						|
};
 | 
						|
 | 
						|
exports.getNamespaceURI = function(element) {
 | 
						|
    return element.namespaceURI;
 | 
						|
};
 | 
						|
 | 
						|
exports.getTextNodeContent = function(textNode) {
 | 
						|
    return textNode.value;
 | 
						|
};
 | 
						|
 | 
						|
exports.getCommentNodeContent = function(commentNode) {
 | 
						|
    return commentNode.data;
 | 
						|
};
 | 
						|
 | 
						|
exports.getDocumentTypeNodeName = function(doctypeNode) {
 | 
						|
    return doctypeNode.name;
 | 
						|
};
 | 
						|
 | 
						|
exports.getDocumentTypeNodePublicId = function(doctypeNode) {
 | 
						|
    return doctypeNode.publicId;
 | 
						|
};
 | 
						|
 | 
						|
exports.getDocumentTypeNodeSystemId = function(doctypeNode) {
 | 
						|
    return doctypeNode.systemId;
 | 
						|
};
 | 
						|
 | 
						|
//Node types
 | 
						|
exports.isTextNode = function(node) {
 | 
						|
    return node.nodeName === '#text';
 | 
						|
};
 | 
						|
 | 
						|
exports.isCommentNode = function(node) {
 | 
						|
    return node.nodeName === '#comment';
 | 
						|
};
 | 
						|
 | 
						|
exports.isDocumentTypeNode = function(node) {
 | 
						|
    return node.nodeName === '#documentType';
 | 
						|
};
 | 
						|
 | 
						|
exports.isElementNode = function(node) {
 | 
						|
    return !!node.tagName;
 | 
						|
};
 | 
						|
 | 
						|
// Source code location
 | 
						|
exports.setNodeSourceCodeLocation = function(node, location) {
 | 
						|
    node.sourceCodeLocation = location;
 | 
						|
};
 | 
						|
 | 
						|
exports.getNodeSourceCodeLocation = function(node) {
 | 
						|
    return node.sourceCodeLocation;
 | 
						|
};
 |