"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.setAttr = exports.getAttr = exports.removeAttr = exports.createTextNode = exports.walkElements = exports.findElement = exports.findElementsByTagNames = exports.removeNode = exports.appendNode = exports.findNextNonTextNode = exports.findNodeIndex = exports.insertBeforeFirstScript = exports.unshiftElement = exports.createElement = void 0; const namespaces_1 = require("../processing/dom/namespaces"); const ATTR_NAMESPACE_LOCAL_NAME_SEPARATOR = ':'; function isElementNode(el) { return el.nodeName !== '#document' && el.nodeName !== '#text' && el.nodeName !== '#documentType' && el.nodeName !== '#comment'; } function getAttrName(attr) { return attr.prefix ? attr.prefix + ATTR_NAMESPACE_LOCAL_NAME_SEPARATOR + attr.name : attr.name; } function parseAttrName(attr) { const parts = attr.split(ATTR_NAMESPACE_LOCAL_NAME_SEPARATOR); if (parts.length === 2) { return { prefix: parts[0], name: parts[1], }; } return { name: parts[0], }; } function findAttr(el, name) { for (let i = 0; i < el.attrs.length; i++) { if (getAttrName(el.attrs[i]) === name) return el.attrs[i]; } return null; } function createElement(tagName, attrs) { return { nodeName: tagName, tagName: tagName, attrs: attrs, childNodes: [], }; } exports.createElement = createElement; function unshiftElement(el, parent) { var _a; el.namespaceURI = parent.namespaceURI; el.parentNode = parent; (_a = parent.childNodes) === null || _a === void 0 ? void 0 : _a.unshift(el); // eslint-disable-line no-unused-expressions } exports.unshiftElement = unshiftElement; function insertBeforeFirstScript(el, parent) { var _a; const firstScriptIndex = findNodeIndex(parent, node => node.tagName === 'script'); const insertIndex = firstScriptIndex !== -1 ? firstScriptIndex : ((_a = parent.childNodes) === null || _a === void 0 ? void 0 : _a.length) || 0; appendNode(el, parent, insertIndex); } exports.insertBeforeFirstScript = insertBeforeFirstScript; function findNodeIndex(parent, predicate) { return parent && parent.childNodes ? parent.childNodes.findIndex(predicate) : -1; } exports.findNodeIndex = findNodeIndex; function findNextNonTextNode(parent, startIndex) { if (!parent.childNodes) return null; let currentNode; while (currentNode = parent.childNodes[startIndex]) { // eslint-disable-line no-cond-assign if (currentNode.nodeName !== '#text') return currentNode; startIndex++; } return currentNode; } exports.findNextNonTextNode = findNextNonTextNode; function appendNode(node, parent, index) { var _a; node.namespaceURI = parent.namespaceURI; node.parentNode = parent; (_a = parent.childNodes) === null || _a === void 0 ? void 0 : _a.splice(index, 0, node); // eslint-disable-line no-unused-expressions } exports.appendNode = appendNode; function removeNode(node) { const parent = node.parentNode; if (!parent || !parent.childNodes) return; const elIndex = parent.childNodes.indexOf(node); parent.childNodes.splice(elIndex, 1); } exports.removeNode = removeNode; function findElementsByTagNames(root, tagNames) { const elements = {}; walkElements(root, el => { if (tagNames.includes(el.tagName)) { elements[el.tagName] = elements[el.tagName] || []; elements[el.tagName].push(el); } }); return elements; } exports.findElementsByTagNames = findElementsByTagNames; function findElement(el, predicate) { if (isElementNode(el) && predicate(el)) return el; if (!el.childNodes) return null; for (const child of el.childNodes) { const result = findElement(child, predicate); if (result) return result; } return null; } exports.findElement = findElement; function walkElements(el, processor) { if (isElementNode(el)) processor(el); if (el.childNodes) el.childNodes.forEach(child => walkElements(child, processor)); } exports.walkElements = walkElements; function createTextNode(content, parent) { return { nodeName: '#text', value: content, parentNode: parent, }; } exports.createTextNode = createTextNode; function removeAttr(el, name) { for (let i = 0; i < el.attrs.length; i++) { if (getAttrName(el.attrs[i]) === name) { el.attrs.splice(i, 1); return; } } } exports.removeAttr = removeAttr; function getAttr(el, name) { const attr = findAttr(el, name); return attr ? attr.value : null; } exports.getAttr = getAttr; function setAttr(el, name, value) { const attr = findAttr(el, name); if (attr) { attr.value = value; return value; } const parsedAttrName = parseAttrName(name); const newAttr = { name: parsedAttrName.name, value: value, namespace: void 0 }; if (parsedAttrName.prefix && namespaces_1.NAMESPACE_PREFIX_MAP[parsedAttrName.prefix]) newAttr.namespace = namespaces_1.NAMESPACE_PREFIX_MAP[parsedAttrName.prefix]; el.attrs.push(newAttr); return value; } exports.setAttr = setAttr;