UNPKG

@taiga-ui/cdk

Version:

Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance

117 lines (116 loc) 5.86 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStartOffsetOfAttribute = exports.hasElementAttribute = exports.findAttributeOnElementWithAttrs = exports.findAttributeOnElementWithTag = exports.findElementsWithAttributeOnTag = exports.findElementsWithAttribute = exports.findElementsWithDirective = exports.findElementsByTagNames = exports.findElementsByTagName = exports.findElementsInTemplateByFn = exports.findElementsByFn = void 0; const parse5_1 = require("parse5"); function findElementsByFn(nodes, predicateFn) { const elements = []; const visitNodes = (nodes) => { nodes.forEach((n) => { const node = n; if (node.childNodes) { visitNodes(node.childNodes); } if (predicateFn(node)) { elements.push(node); } }); }; visitNodes(nodes); return elements; } exports.findElementsByFn = findElementsByFn; function findElementsInTemplateByFn(html, predicateFn) { // utf8 with BOM adds an extra character to the beginning of the string if (html.charCodeAt(0) === 0xfeff) { html = html.slice(1); } const document = (0, parse5_1.parseFragment)(html, { sourceCodeLocationInfo: true }); return findElementsByFn(document.childNodes, predicateFn); } exports.findElementsInTemplateByFn = findElementsInTemplateByFn; function findElementsByTagName(html, tagName, // eslint-disable-next-line no-restricted-syntax filterFn = () => true) { return findElementsInTemplateByFn(html, (el) => el.tagName === tagName && filterFn(el)); } exports.findElementsByTagName = findElementsByTagName; function findElementsByTagNames(html, tagNames) { return findElementsInTemplateByFn(html, (el) => tagNames.includes(el.tagName)); } exports.findElementsByTagNames = findElementsByTagNames; /** * Parses a HTML fragment and traverses all AST nodes in order find elements that * include the specified directive as attribute or input. */ function findElementsWithDirective(html, attributeName) { const lowercasedAttrName = attributeName.toLowerCase(); const inputName = `[${lowercasedAttrName}]`; return findElementsInTemplateByFn(html, (el) => { var _a; return (_a = el.attrs) === null || _a === void 0 ? void 0 : _a.some(({ name }) => name === lowercasedAttrName || name === inputName); }); } exports.findElementsWithDirective = findElementsWithDirective; /** * Parses a HTML fragment and traverses all AST nodes in order find elements that * include the specified attribute. */ function findElementsWithAttribute(html, attributeName) { return findElementsInTemplateByFn(html, (el) => { var _a; return (_a = el.attrs) === null || _a === void 0 ? void 0 : _a.some((attr) => attr.name === attributeName.toLowerCase()); }); } exports.findElementsWithAttribute = findElementsWithAttribute; /** * Parses a HTML fragment and traverses all AST nodes in order find elements that include the specified attribute and tag name. * @param html * @param attributeName */ function findElementsWithAttributeOnTag(html, attributeNames, tagNames = [], // eslint-disable-next-line no-restricted-syntax filterFn = () => true) { return findElementsInTemplateByFn(html, (el) => { var _a; return (!attributeNames.length || ((_a = el.attrs) === null || _a === void 0 ? void 0 : _a.some((attr) => attributeNames.map((name) => name.toLowerCase()).includes(attr.name)))) && (tagNames.includes(el.tagName) || tagNames.includes('*') || !tagNames.length) && filterFn(el); }); } exports.findElementsWithAttributeOnTag = findElementsWithAttributeOnTag; /** * Finds elements with explicit tag names that also contain the specified attribute. Returns the * attribute start offset based on the specified HTML. */ function findAttributeOnElementWithTag(html, name, tagNames, // eslint-disable-next-line no-restricted-syntax filterFn = () => true) { return findElementsWithAttribute(html, name) .filter((element) => (tagNames.includes(element.tagName) || tagNames.includes('*')) && filterFn(element)) .map((element) => getStartOffsetOfAttribute(element, name)); } exports.findAttributeOnElementWithTag = findAttributeOnElementWithTag; /** * Finds elements that contain the given attribute and contain at least one of the other * specified attributes. Returns the primary attribute's start offset based on the specified HTML. */ function findAttributeOnElementWithAttrs(html, name, attrs, // eslint-disable-next-line no-restricted-syntax filterFn = () => true) { return findElementsWithAttribute(html, name) .filter((element) => attrs.some((attr) => hasElementAttribute(element, attr)) && filterFn(element)) .map((element) => getStartOffsetOfAttribute(element, name)); } exports.findAttributeOnElementWithAttrs = findAttributeOnElementWithAttrs; /** Shorthand function that checks if the specified element contains the given attribute. */ function hasElementAttribute(element, attributeName) { var _a; const lowercasedAttrName = attributeName.toLowerCase(); return (_a = element.attrs) === null || _a === void 0 ? void 0 : _a.some((attr) => attr.name === lowercasedAttrName || attr.name === `[${lowercasedAttrName}]`); } exports.hasElementAttribute = hasElementAttribute; /** Gets the start offset of the given attribute from a Parse5 element. */ function getStartOffsetOfAttribute(element, attributeName) { var _a, _b, _c; return (((_c = (_b = (_a = element.sourceCodeLocation) === null || _a === void 0 ? void 0 : _a.attrs) === null || _b === void 0 ? void 0 : _b[attributeName.toLowerCase()]) === null || _c === void 0 ? void 0 : _c.startOffset) || 0); } exports.getStartOffsetOfAttribute = getStartOffsetOfAttribute;