| import { DOCUMENT_MODE } from '../common/html.js'; |
| export const defaultTreeAdapter = { |
| //Node construction |
| createDocument() { |
| return { |
| nodeName: '#document', |
| mode: DOCUMENT_MODE.NO_QUIRKS, |
| childNodes: [], |
| }; |
| }, |
| createDocumentFragment() { |
| return { |
| nodeName: '#document-fragment', |
| childNodes: [], |
| }; |
| }, |
| createElement(tagName, namespaceURI, attrs) { |
| return { |
| nodeName: tagName, |
| tagName, |
| attrs, |
| namespaceURI, |
| childNodes: [], |
| parentNode: null, |
| }; |
| }, |
| createCommentNode(data) { |
| return { |
| nodeName: '#comment', |
| data, |
| parentNode: null, |
| }; |
| }, |
| createTextNode(value) { |
| return { |
| nodeName: '#text', |
| value, |
| parentNode: null, |
| }; |
| }, |
| //Tree mutation |
| appendChild(parentNode, newNode) { |
| parentNode.childNodes.push(newNode); |
| newNode.parentNode = parentNode; |
| }, |
| insertBefore(parentNode, newNode, referenceNode) { |
| const insertionIdx = parentNode.childNodes.indexOf(referenceNode); |
| parentNode.childNodes.splice(insertionIdx, 0, newNode); |
| newNode.parentNode = parentNode; |
| }, |
| setTemplateContent(templateElement, contentElement) { |
| templateElement.content = contentElement; |
| }, |
| getTemplateContent(templateElement) { |
| return templateElement.content; |
| }, |
| setDocumentType(document, name, publicId, systemId) { |
| const doctypeNode = document.childNodes.find((node) => node.nodeName === '#documentType'); |
| if (doctypeNode) { |
| doctypeNode.name = name; |
| doctypeNode.publicId = publicId; |
| doctypeNode.systemId = systemId; |
| } |
| else { |
| const node = { |
| nodeName: '#documentType', |
| name, |
| publicId, |
| systemId, |
| parentNode: null, |
| }; |
| defaultTreeAdapter.appendChild(document, node); |
| } |
| }, |
| setDocumentMode(document, mode) { |
| document.mode = mode; |
| }, |
| getDocumentMode(document) { |
| return document.mode; |
| }, |
| detachNode(node) { |
| if (node.parentNode) { |
| const idx = node.parentNode.childNodes.indexOf(node); |
| node.parentNode.childNodes.splice(idx, 1); |
| node.parentNode = null; |
| } |
| }, |
| insertText(parentNode, text) { |
| if (parentNode.childNodes.length > 0) { |
| const prevNode = parentNode.childNodes[parentNode.childNodes.length - 1]; |
| if (defaultTreeAdapter.isTextNode(prevNode)) { |
| prevNode.value += text; |
| return; |
| } |
| } |
| defaultTreeAdapter.appendChild(parentNode, defaultTreeAdapter.createTextNode(text)); |
| }, |
| insertTextBefore(parentNode, text, referenceNode) { |
| const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1]; |
| if (prevNode && defaultTreeAdapter.isTextNode(prevNode)) { |
| prevNode.value += text; |
| } |
| else { |
| defaultTreeAdapter.insertBefore(parentNode, defaultTreeAdapter.createTextNode(text), referenceNode); |
| } |
| }, |
| adoptAttributes(recipient, attrs) { |
| const recipientAttrsMap = new Set(recipient.attrs.map((attr) => attr.name)); |
| for (let j = 0; j < attrs.length; j++) { |
| if (!recipientAttrsMap.has(attrs[j].name)) { |
| recipient.attrs.push(attrs[j]); |
| } |
| } |
| }, |
| //Tree traversing |
| getFirstChild(node) { |
| return node.childNodes[0]; |
| }, |
| getChildNodes(node) { |
| return node.childNodes; |
| }, |
| getParentNode(node) { |
| return node.parentNode; |
| }, |
| getAttrList(element) { |
| return element.attrs; |
| }, |
| //Node data |
| getTagName(element) { |
| return element.tagName; |
| }, |
| getNamespaceURI(element) { |
| return element.namespaceURI; |
| }, |
| getTextNodeContent(textNode) { |
| return textNode.value; |
| }, |
| getCommentNodeContent(commentNode) { |
| return commentNode.data; |
| }, |
| getDocumentTypeNodeName(doctypeNode) { |
| return doctypeNode.name; |
| }, |
| getDocumentTypeNodePublicId(doctypeNode) { |
| return doctypeNode.publicId; |
| }, |
| getDocumentTypeNodeSystemId(doctypeNode) { |
| return doctypeNode.systemId; |
| }, |
| //Node types |
| isTextNode(node) { |
| return node.nodeName === '#text'; |
| }, |
| isCommentNode(node) { |
| return node.nodeName === '#comment'; |
| }, |
| isDocumentTypeNode(node) { |
| return node.nodeName === '#documentType'; |
| }, |
| isElementNode(node) { |
| return Object.prototype.hasOwnProperty.call(node, 'tagName'); |
| }, |
| // Source code location |
| setNodeSourceCodeLocation(node, location) { |
| node.sourceCodeLocation = location; |
| }, |
| getNodeSourceCodeLocation(node) { |
| return node.sourceCodeLocation; |
| }, |
| updateNodeSourceCodeLocation(node, endLocation) { |
| node.sourceCodeLocation = { ...node.sourceCodeLocation, ...endLocation }; |
| }, |
| }; |