UNPKG

@thednp/domparser

Version:

🍝 Super light HTML parser for isomorphic applications.

1 lines 30.9 kB
{"version":3,"file":"prototype-C9KlvL7Y.cjs","names":["selector: string","node: DOMNode","parts: SelectorPart[]","node: ChildNode","isTag","node: DOMNode","nodeName: T","text: string","child: ChildNode","parent: DOMNode | RootNode","ownerDocument?: RootNode","newContent: string","isNode","nodeName: string","ALL: ChildElementList","CHILDREN: ChildElementList","CHILDNODES: ChildNodeList","DOM_ERROR","tagName:\n & string\n & (keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap)","first?: NodeLikeAttributes | MaybeChildNode","_ns: string","tagName:\n & string\n & (keyof SVGElementTagNameMap & keyof HTMLElementTagNameMap)","content: string","id: string","node","selector: string","childNode: DOMNode","childNode: ChildNode","arr: ChildNode[]","tagName: string","className: string","child: DOMNode","n: string | number | ChildNode","tagName: string & TagNames","childNodes: ChildNodeList"],"sources":["../src/parts/selectors.ts","../src/parts/prototype.ts"],"sourcesContent":["// selectors.ts\nimport { startsWith, toLowerCase } from \"./util.ts\";\nimport type { DOMNode, MatchFunction, SelectorPart } from \"./types.ts\";\n\n/**\n * Create a selector cache to help improve `match` based queries\n * (matches, querySelector, querySelectorAll).\n */\nclass SelectorCacheMap extends Map<string, MatchFunction> {\n private hits = 0;\n private misses = 0;\n\n constructor() {\n super();\n this.misses = 0;\n this.hits = 0;\n }\n hit() {\n this.hits += 1;\n }\n miss() {\n this.hits += 1;\n }\n getMatchFunction(selector: string, maxSize = 100): MatchFunction {\n let matchFn = this.get(selector);\n\n if (!matchFn) {\n this.miss();\n // If cache is full, remove oldest entry\n if (this.size >= maxSize) {\n const firstKey = this.keys().next().value;\n /* istanbul ignore else @preserve */\n if (firstKey) this.delete(firstKey);\n }\n\n // Parse selector parts once and create a matcher function\n const parts = selector.split(\",\").map((s) => s.trim());\n\n matchFn = (node: DOMNode): boolean =>\n parts.some((part) => matchesSingleSelector(node, part));\n\n this.set(selector, matchFn);\n } else {\n this.hit();\n }\n\n return matchFn;\n }\n clear() {\n super.clear();\n this.misses = 0;\n this.hits = 0;\n }\n getStats() {\n return {\n size: this.size,\n hits: this.hits,\n misses: this.misses,\n // prevent division by ZERO\n hitRate: this.hits / ((this.hits + this.misses) || 1),\n };\n }\n}\n\nexport const selectorCache = new SelectorCacheMap();\n\n// Selector RegExp\nconst SELECTOR_REGEX = /([.#]?[\\w-]+|\\[[\\w-]+(?:=[^\\]]+)?\\])+/g;\n\n/**\n * Parses a CSS selector string into an array of selector parts.\n * Each part represents a segment of the selector (e.g., tag name, class, id, attribute).\n * @param selector The CSS selector string to parse.\n * @returns An array of `SelectorPart` objects representing the parsed selector.\n */\nconst parseSelector = (selector: string): SelectorPart[] => {\n const parts: SelectorPart[] = [];\n const matches =\n selector.match(SELECTOR_REGEX) || /* istanbul ignore next @preserve */ [];\n\n for (const match of matches) {\n if (startsWith(match, \"#\")) {\n parts.push({ type: \"#\", name: \"id\", value: match.slice(1) });\n } else if (startsWith(match, \".\")) {\n parts.push({ type: \".\", name: \"class\", value: match.slice(1) });\n } else if (startsWith(match, \"[\")) {\n const [name, value] = match.slice(1, -1).split(\"=\");\n parts.push({\n type: \"[\",\n name,\n value: value ? value.replace(/['\"]/g, \"\") : undefined,\n });\n } else {\n parts.push({ type: \"\", name: match });\n }\n }\n return parts;\n};\n\n/**\n * Checks if a node matches a single CSS selector.\n * @param node The `DOMNode` object to test against the selector.\n * @param selector The CSS selector string.\n * @returns `true` if the node matches the selector, `false` otherwise.\n */\nconst matchesSingleSelector = (node: DOMNode, selector: string): boolean => {\n const parts = parseSelector(selector);\n\n return parts.every((part) => {\n switch (part.type) {\n case \"#\": {\n return node.attributes.get(\"id\") === part.value;\n }\n case \".\": {\n const classes = node.attributes.get(\"class\")?.split(/\\s+/) || [];\n return classes.includes(part.value as string);\n }\n case \"[\": {\n const attrValue = node.attributes.get(part.name);\n return part.value ? attrValue === part.value : attrValue !== undefined;\n }\n default: {\n return toLowerCase(node.tagName) === toLowerCase(part.name);\n }\n }\n });\n};\n\n/**\n * Checks if a node matches one or mode CSS selectors.\n * @param node The `DOMNode` object to test against the selector.\n * @param selector The CSS selector string.\n * @returns `true` if the node matches the selector, `false` otherwise.\n */\nexport const matchesSelector = (node: DOMNode, selector: string): boolean => {\n const matcher = selectorCache.getMatchFunction(selector);\n return matcher(node);\n};\n","// prototype.ts\nimport { tokenize, trim } from \"./util.ts\";\nimport { matchesSelector } from \"./selectors.ts\";\nimport {\n defineProperties,\n DOM_ERROR,\n isNode,\n isObj,\n isPrimitive,\n isRoot,\n isTag,\n selfClosingTags,\n toUpperCase,\n} from \"./util.ts\";\n\nimport type {\n ChildElementList,\n ChildNode,\n ChildNodeList,\n CommentNode,\n DOMNode,\n MaybeChildNode,\n NodeLikeAttributes,\n RootNode,\n TagNames,\n TextNode,\n TextToken,\n} from \"./types.ts\";\n\n/**\n * Generates text string from node's children textContent.\n * @param node The node whose children to stringify\n * @returns textContent string\n */\nconst textContent = (node: ChildNode): string => {\n if (!isTag(node)) return node.nodeValue;\n const { childNodes, nodeName } = node;\n if (nodeName === \"BR\") return \"\\n\";\n if (!childNodes.length) return \"\";\n const hasTagChild = childNodes.some(isTag);\n\n return childNodes.map((n) => isTag(n) ? textContent(n) : n.nodeValue).join(\n hasTagChild ? \"\\n\" : \"\",\n );\n};\n\n/**\n * Generates HTML string for node's children\n * @param node The node whose children to stringify\n * @param depth Current indentation depth\n * @returns innerHTML string\n */\nconst innerHTML = (\n node: DOMNode,\n depth = 0,\n): string => {\n const { childNodes: childContents } = node;\n // Remove comments\n const childNodes = childContents.filter((c) => c.nodeName !== \"#comment\");\n if (!childNodes.length) return \"\";\n const childIsText = childNodes.length === 1 &&\n !isTag(childNodes[0]);\n const space = depth && !childIsText ? \" \".repeat(depth) : \"\";\n return childNodes\n .map((n) => isTag(n) ? outerHTML(n, depth) : space + n.nodeValue)\n .join(\"\\n\");\n};\n\n/**\n * Generates HTML string for a node including its opening/closing tags\n * @param node The node to stringify\n * @param depth Current indentation depth\n * @returns outerHTML string\n */\nconst outerHTML = (node: DOMNode, depth = 0): string => {\n const { attributes, tagName, childNodes: childContents } = node;\n const childNodes = childContents.filter((c) => c.nodeName !== \"#comment\");\n const space = depth ? \" \".repeat(depth) : \"\";\n const hasChildren = childNodes.length > 0;\n const childIsText = childNodes.length === 1 && !isTag(childNodes[0]);\n const hasAttributes = attributes.size > 0;\n const isSelfClosing = selfClosingTags.has(tagName);\n\n const attrStr = hasAttributes\n ? \" \" + Array.from(attributes)\n .map(([key, val]) => `${key}=\"${trim(val)}\"`)\n .join(\" \")\n : \"\";\n\n let output = `${space}<${tagName}${attrStr}${isSelfClosing ? \" /\" : \"\"}>`;\n output += !childIsText && hasChildren ? \"\\n\" : \"\";\n output += hasChildren ? innerHTML(node, depth + 1) : \"\";\n output += !childIsText && hasChildren ? `\\n${space}` : \"\";\n output += !isSelfClosing ? `</${tagName}>` : \"\";\n\n return output;\n};\n\n/**\n * Creates a basic text or comment node.\n * @param nodeName The node name (\"#text\" or \"#comment\").\n * @param text The text content of the node.\n * @returns A TextNode or CommentNode object.\n */\nexport function createBasicNode<T extends (\"#text\" | \"#comment\")>(\n nodeName: T,\n text: string,\n): TextNode | CommentNode {\n return {\n nodeName,\n // nodeValue: nodeName !== \"#text\" ? `<${text}>` : text,\n nodeValue: text,\n } as (TextNode | CommentNode);\n}\n\nfunction setupChildNode(\n child: ChildNode,\n parent: DOMNode | RootNode,\n ownerDocument?: RootNode,\n) {\n defineProperties(child, {\n textContent: {\n enumerable: false,\n get: () => textContent(child),\n set: (newContent: string) => {\n if (isTag(child)) {\n child.replaceChildren();\n child.appendChild(createBasicNode(\"#text\", newContent));\n } else {\n child.nodeValue = newContent;\n }\n },\n },\n parentNode: {\n enumerable: false,\n get: () => parent,\n },\n parentElement: {\n enumerable: false,\n get: () => parent,\n },\n ownerDocument: {\n enumerable: false,\n get: () => ownerDocument,\n },\n });\n\n child.remove = () => parent.removeChild(child);\n\n // Define recursive before and after methods\n child.before = (...nodes: ChildNodeList) => {\n const validNodes = nodes.map(convertToNode).filter(isNode);\n const index = parent.childNodes.indexOf(child);\n // istanbul ignore else @preserve\n if (index > -1) {\n parent.childNodes.splice(index, 0, ...validNodes);\n validNodes.forEach((n, i) => {\n // istanbul ignore else @preserve\n if (isTag(n)) {\n const childIndex = (parent as DOMNode).children.indexOf(\n child as DOMNode,\n );\n (parent as DOMNode).children.splice(childIndex + i, 0, n);\n ownerDocument?.register(n);\n // istanbul ignore else @preserve\n if (isTag(parent as DOMNode)) (parent as DOMNode).registerChild(n);\n }\n setupChildNode(n, parent, ownerDocument); // Setup new nodes\n });\n }\n };\n\n child.after = (...nodes: ChildNodeList) => {\n const validNodes = nodes.map(convertToNode).filter(isNode);\n const index = parent.childNodes.indexOf(child);\n // istanbul ignore else @preserve\n if (index > -1) {\n parent.childNodes.splice(index + 1, 0, ...validNodes);\n validNodes.forEach((n, i) => {\n // istanbul ignore else @preserve\n if (isTag(n)) {\n const childIndex = (parent as DOMNode).children.indexOf(\n child as DOMNode,\n );\n (parent as DOMNode).children.splice(childIndex + 1 + i, 0, n);\n ownerDocument?.register(n);\n // istanbul ignore else @preserve\n if (isTag(parent as DOMNode)) (parent as DOMNode).registerChild(n);\n }\n setupChildNode(n, parent, ownerDocument); // Setup new nodes\n });\n }\n };\n}\n\n/**\n * Creates a DOM-like Node (`DOMNode` or `RootNode`) with DOM API properties and methods.\n * This function extends the basic `NodeLike` from **Parser** by adding DOM-specific\n * properties and methods, as well as applying filters based on the provided configuration.\n *\n * @param this - The `RootNode` when creating a `DOMNode`, or `null` otherwise (in non-strict mode)\n * @param nodeName The tag name of the node to create (or '#document' for the root).\n * @param childNodes Optional child nodes to append to the created node.\n * @returns An extended `DOMNode` or `RootNode` object with DOM API.\n */\nexport function createNode(\n this: RootNode | null,\n nodeName: string,\n ...childNodes: ChildNodeList\n): Omit<DOMNode, \"tagName\" | \"attributes\"> | RootNode {\n const ALL: ChildElementList = [];\n const CHILDREN: ChildElementList = [];\n const CHILDNODES: ChildNodeList = [];\n const nodeIsRoot = nodeName === \"#document\";\n const ownerDocument = this ?? undefined;\n\n const node = {\n nodeName,\n appendChild(child: ChildNode) {\n if (!isNode(child)) {\n throw new Error(`${DOM_ERROR} Invalid node.`);\n }\n CHILDNODES.push(child);\n if (isTag(child)) {\n ALL.push(child);\n CHILDREN.push(child);\n ownerDocument?.register(child);\n }\n\n setupChildNode(child, node as unknown as DOMNode, ownerDocument);\n },\n append(...nodes: ChildNodeList) {\n for (const child of nodes) {\n node.appendChild(child);\n }\n },\n cleanup: () => {\n ALL.length = 0;\n CHILDREN.length = 0;\n CHILDNODES.length = 0;\n },\n\n // Root document methods\n ...(isRoot({ nodeName } as RootNode) && {\n createElement(\n tagName:\n & string\n & (keyof HTMLElementTagNameMap | keyof SVGElementTagNameMap),\n first?: NodeLikeAttributes | MaybeChildNode,\n ...rest: MaybeChildNode[]\n ) {\n return createElement.call(\n node as RootNode,\n tagName,\n first,\n ...rest,\n );\n },\n createElementNS(\n _ns: string,\n tagName:\n & string\n & (keyof SVGElementTagNameMap & keyof HTMLElementTagNameMap),\n first?: NodeLikeAttributes | MaybeChildNode,\n ...rest: MaybeChildNode[]\n ) {\n return createElement.call(node as RootNode, tagName, first, ...rest);\n },\n createComment(content: string) {\n return createBasicNode(\"#comment\", content);\n },\n createTextNode(content: string) {\n return createBasicNode(\"#text\", content);\n },\n getElementById(id: string) {\n return ALL.find((node) => node.attributes.get(\"id\") === id) ?? null;\n },\n }),\n\n // Element methods\n ...((!nodeIsRoot) && {\n matches(selector: string) {\n return matchesSelector(node as unknown as DOMNode, selector);\n },\n }),\n // Shared methods\n contains: (childNode: DOMNode) => {\n if (!childNode || !isTag(childNode)) {\n throw new Error(\n \"DomError: the childNode parameter must be a valid DOMNode\",\n );\n }\n if ((node as DOMNode | RootNode).children.includes(childNode)) {\n return true;\n }\n\n let currentParent = childNode.parentNode;\n while (currentParent) {\n if (currentParent === node) {\n return true;\n }\n currentParent = currentParent.parentNode;\n }\n return false;\n },\n removeChild(childNode: ChildNode) {\n if (!childNode || !isNode(childNode)) {\n throw new Error(\n \"DomError: the childNode parameter must be a valid ChildNode\",\n );\n }\n\n const indexOf = (arr: ChildNode[]) => arr.indexOf(childNode);\n /* istanbul ignore else @preserve */\n if (isTag(childNode)) {\n const idx1 = indexOf(ALL);\n const idx2 = indexOf(CHILDREN);\n /* istanbul ignore else @preserve */\n if (idx1 > -1) ALL.splice(idx1, 1);\n /* istanbul ignore else @preserve */\n if (idx2 > -1) CHILDREN.splice(idx2, 1);\n childNode.cleanup();\n\n ownerDocument?.deregister(childNode);\n }\n\n const idx3 = indexOf(CHILDNODES);\n /* istanbul ignore else @preserve */\n if (idx3 > -1) CHILDNODES.splice(idx3, 1);\n },\n replaceChildren: (...newChildren: DOMNode[]) => {\n // clone this array to work\n CHILDNODES.slice(0).forEach((child) => node.removeChild(child));\n node.append(...newChildren);\n },\n querySelector(selector: string) {\n return ALL.find((n) => n.matches(selector)) ?? null;\n },\n querySelectorAll(selector: string) {\n return ALL.filter((n) => n.matches(selector));\n },\n getElementsByTagName(tagName: string) {\n return tagName === \"*\"\n ? ALL\n : ALL.filter((n) => n.tagName.toLowerCase() === tagName.toLowerCase());\n },\n getElementsByClassName(className: string) {\n return ALL.filter((n) => {\n const classAttr = n.attributes.get(\"class\");\n return classAttr?.split(/\\s+/).includes(className) ?? false;\n });\n },\n };\n\n // Define enumerable getters\n defineProperties(node, {\n childNodes: {\n enumerable: true,\n get: () => CHILDNODES,\n },\n children: {\n enumerable: true,\n get: () => CHILDREN,\n },\n // Add tag-specific property\n ...(!nodeIsRoot\n ? {\n registerChild: {\n enumerable: false,\n value: (child: DOMNode) => {\n ALL.push(child);\n },\n },\n }\n : {}),\n });\n\n // Add root-specific properties\n if (nodeIsRoot) {\n defineProperties(node, {\n all: {\n enumerable: true,\n get: () => ALL,\n },\n documentElement: {\n enumerable: true,\n get: () => ALL.find((node) => toUpperCase(node.tagName) === \"HTML\"),\n },\n head: {\n enumerable: true,\n get: () => ALL.find((node) => toUpperCase(node.tagName) === \"HEAD\"),\n },\n body: {\n enumerable: true,\n get: () => ALL.find((node) => toUpperCase(node.tagName) === \"BODY\"),\n },\n register: {\n enumerable: false,\n value: (child: DOMNode) => {\n ALL.push(child);\n },\n },\n deregister: {\n enumerable: false,\n value: (child: DOMNode) => {\n const idx = ALL.indexOf(child);\n /* istanbul ignore else @preserve */\n if (idx > -1) ALL.splice(idx, 1);\n },\n },\n });\n } else {\n // Add HTML generation methods\n defineProperties(node, {\n innerHTML: {\n enumerable: false,\n get: () => innerHTML(node as unknown as DOMNode),\n },\n outerHTML: {\n enumerable: false,\n get: () => outerHTML(node as unknown as DOMNode),\n },\n });\n }\n\n // Add any initial children\n if (childNodes?.length) {\n node.append(...childNodes);\n }\n\n return node as unknown as RootNode | Omit<DOMNode, \"tagName\" | \"attributes\">;\n}\n\nconst convertToNode = (n: string | number | ChildNode) => {\n if (isPrimitive(n)) {\n const { tokenType, value } = tokenize(String(n))[0] as TextToken;\n return createBasicNode(`#${tokenType}`, value);\n }\n return n;\n};\n\n/**\n * Creates a new `Element` like node\n * @param this The RootNode instance\n * @param tagName Tag name for the element\n * @param first Optional attributes or first child\n * @param args Additional child nodes\n * @returns New element node\n */\nexport function createElement(\n this: RootNode,\n tagName: string & TagNames,\n first?: NodeLikeAttributes | MaybeChildNode,\n ...args: MaybeChildNode[]\n): DOMNode {\n const childNodes: ChildNodeList = [];\n let attributes = new Map<string, string>();\n\n // Handle first argument\n /* istanbul ignore else @preserve */\n if (first) {\n if (isObj(first) && !isNode(first)) {\n // Convert attributes object to Map\n attributes = new Map(Object.entries(first));\n } else {\n childNodes.push(convertToNode(first as string | number | ChildNode));\n }\n }\n\n // Add remaining children\n const nodes = args.map(convertToNode).filter(isNode);\n childNodes.push(...nodes);\n\n const node = createNode.call(\n this,\n toUpperCase(tagName),\n ...childNodes,\n ) as DOMNode;\n\n const charset = attributes.get(\"charset\");\n if (tagName === \"meta\" && charset) {\n this.charset = toUpperCase(charset);\n }\n\n defineProperties(node, {\n tagName: {\n enumerable: true,\n get: () => tagName,\n },\n attributes: {\n enumerable: true,\n get: () => attributes,\n },\n id: {\n enumerable: true,\n get: () => attributes.get(\"id\") ?? \"\",\n },\n className: {\n enumerable: true,\n get: () => attributes.get(\"class\") ?? \"\",\n },\n });\n // define Element attributes methods\n node.hasAttribute = (attrName) => attributes.has(attrName);\n node.getAttribute = (attrName) => attributes.get(attrName) ?? null;\n node.setAttribute = (attrName, attrValue) => {\n attributes.set(attrName, attrValue);\n };\n node.removeAttribute = (attrName) => {\n attributes.delete(attrName);\n };\n node.hasAttributeNS = (_namespace, attrName) => attributes.has(attrName);\n node.getAttributeNS = (_namespace, attrName) =>\n attributes.get(attrName) ?? null;\n node.setAttributeNS = (_namespace, attrName, attrValue) => {\n attributes.set(attrName, attrValue);\n };\n node.removeAttributeNS = (_namespace, attrName) => {\n attributes.delete(attrName);\n };\n // define Element parent selector\n node.closest = (selector: string) => {\n if (!selector) throw new Error(\"DomError: selector must be a string\");\n if (node.matches(selector)) return node;\n let currentParent = node.parentNode;\n while (!isRoot(currentParent)) {\n if (currentParent.matches(selector)) {\n return currentParent;\n }\n currentParent = currentParent.parentNode;\n }\n return null;\n };\n\n return node;\n}\n\n/**\n * Creates a new `Document` like root node.\n *\n * @returns a new root node\n */\nexport const createDocument = () =>\n createNode.call(null, \"#document\") as RootNode;\n"],"mappings":"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"}