// src/attributes.ts import { pipe as pipe4 } from "fp-ts/lib/function.js"; // src/create.ts import { identity } from "fp-ts/lib/function.js"; import { Comment, Text, Window } from "happy-dom"; import { dasherize } from "native-dash"; // src/errors.ts import { relative } from "path"; // node_modules/.pnpm/callsites@4.0.0/node_modules/callsites/index.js function callsites() { const _prepareStackTrace = Error.prepareStackTrace; Error.prepareStackTrace = (_, stack2) => stack2; const stack = new Error().stack.slice(1); Error.prepareStackTrace = _prepareStackTrace; return stack; } // src/diagnostics.ts import { flow as flow2, pipe as pipe3 } from "fp-ts/lib/function.js"; // src/nodes.ts import { pipe as pipe2 } from "fp-ts/lib/function.js"; // src/type-guards.ts function isHappyWrapperError(err) { return typeof err === "object" && err.kind === "HappyWrapper"; } var isInspectionTuple = (thing) => { return Array.isArray(thing) && thing.length === 2 && typeof thing[0] === "string" && !Array.isArray(thing[1]); }; function isDocument(dom) { return typeof dom === "object" && dom !== null && !isElement(dom) && "body" in dom; } function isFragment(dom) { return typeof dom === "object" && dom !== null && !isElement(dom) && !isTextNode(dom) && !("body" in dom); } var nodeStartsWithElement = (node) => { return !!(node.firstChild === node.firstElementChild); }; var nodeEndsWithElement = (node) => { return "lastElementChild" in node && node.lastChild === node.lastElementChild; }; var nodeBoundedByElements = (node) => { return nodeStartsWithElement(node) && nodeEndsWithElement(node); }; var hasSingularElement = (node) => { return nodeBoundedByElements(node) && node.childNodes.length === 1; }; function isElement(el) { return typeof el === "object" && el !== null && "outerHTML" in el && el.nodeType === 1; } var isElementLike = (container) => { if (isDocument(container)) { return container.body.childNodes.length === 1 && container.body.firstChild === container.body.firstElementChild; } return isFragment(container) && container.childNodes.length === 1 && container.firstChild === container.firstElementChild; }; function isTextNodeLike(node) { var _a; return (isDocument(node) || isFragment(node)) && ((_a = node == null ? void 0 : node.childNodes) == null ? void 0 : _a.length) === 1 && isTextNode(node.firstChild); } var isUpdateSignature = (args) => { return Array.isArray(args) && args.length === 3 && typeof args[1] === "number" && typeof args[2] === "number"; }; function isTextNode(node) { if (typeof node === "string") { const test = createFragment(node); return isTextNodeLike(test); } else { return typeof node === "object" && node !== null && !("firstElementChild" in node); } } var isContainer = (thing) => { return isDocument(thing) || isFragment(thing) || isElement(thing) || isTextNode(thing); }; var nodeChildrenAllElements = (node) => { return node.childNodes.every((n) => isElement(n)); }; // src/utils.ts import { flow, pipe } from "fp-ts/lib/function.js"; var nodeTypeLookup = (type) => { switch (type) { case 1: { return "element"; } case 3: { return "text"; } case 8: { return "comment"; } case 11: { return "fragment"; } } }; var getNodeType = (node) => { if (typeof node === "string") { return "html"; } const byType = nodeTypeLookup(node.nodeType); if (byType) { return byType; } return isTextNode(node) ? "text" : isElement(node) ? "element" : isDocument(node) ? "document" : isFragment(node) ? "fragment" : "node"; }; var solveForNodeType = (_ = void 0) => { const solver = () => ({ solver: (s) => (node, parent) => { if (node === null) { throw new Error("Value passed into solver was NULL!"); } if (node === void 0) { throw new Error("Value passed into solver was UNDEFINED!"); } const type = getNodeType(node); if (type in s) { const fn = s[type]; return fn(node, parent); } else { if (type === "node" && "element" in s && isElement(node)) { const fn = s.element; return fn(node, parent); } else if (type === "node" && "text" in s && isTextNode(node)) { const fn = s.text; return fn(node); } throw new HappyMishap(`Problem finding "${type}" in solver.`, { name: `solveForNodeType(${type})` }); } } }); return { outputType: () => solver(), mirror: () => solver() }; }; function toHtml(node) { if (node === null) { return ""; } const n = Array.isArray(node) ? node : [node]; try { const results = n.map((i) => { const convert = solveForNodeType().outputType().solver({ html: (h) => h, text: (t) => t.textContent, comment: (h) => ``, element: (e) => e.outerHTML, node: (ne) => { if (isElement(ne)) { convert(ne); } if (isTextNode(ne)) { convert(ne); } throw new Error( `Unknown node type detected while converting to HTML: [ name: ${ne.nodeName}, type: ${ne.nodeType}, value: ${ne.nodeValue} ]` ); }, document: (d) => `${d.head.hasChildNodes() ? d.head.outerHTML : ""}${d.body.outerHTML}`, fragment: (f) => { return isElementLike(f) ? f.firstElementChild.outerHTML : f.childNodes.map((c) => convert(c, f)).join(""); } }); return convert(i); }); return results.join(""); } catch (error_) { const error = Array.isArray(node) ? new HappyMishap( `Problem converting an array of ${n.length} nodes [${n.map((i) => getNodeType(i)).join(", ")}] to HTML`, { name: "toHTML([...])", inspect: ["first node", node[0]], error: error_ } ) : new HappyMishap(`Problem converting "${getNodeType(node)}" to HTML!`, { name: "toHTML(getNodeType(node))", inspect: node, error: error_ }); throw error; } } function clone(container) { const clone2 = solveForNodeType().mirror().solver({ html: (h) => `${h}`, fragment: flow(toHtml, createFragment), document: (d) => { return createDocument(d.body.innerHTML, d.head.innerHTML); }, element: (e) => pipe(e, toHtml, createElement), node: (n) => { throw new HappyMishap("Can't clone an unknown node!", { inspect: n }); }, text: flow(toHtml, createTextNode), comment: flow(toHtml, createCommentNode) }); return clone2(container); } function safeString(str) { const node = createFragment(str); return node.textContent; } // src/nodes.ts var getChildren = (el) => { if (!el.hasChildNodes()) { return []; } const output = []; let child = el.firstChild; for (let idx = 0; idx < el.childNodes.length; idx++) { if (isElement(child) || isTextNode(child)) { output.push(child); } else if (isFragment(child) || isDocument(child)) { for (const fragChild of getChildren(child)) { output.push(fragChild); } } else { throw new HappyMishap( `unknown node type [${getNodeType( child )}] found while trying to convert children to an array`, { name: "getChildrenAsArray", inspect: child } ); } child = child.nextSibling; } return output; }; var getChildElements = (el) => { return getChildren(el).filter((c) => isElement(c)); }; var extract = (memory) => (node) => { if (memory) { memory.push(clone(node)); } return false; }; var placeholder = (memory, placeholder2) => (node) => { if (memory) { memory.push(clone(node)); } const el = placeholder2 ? placeholder2 : createElement(""); addClass(...getClassList(node))(el); node.replaceWith(el); return node; }; var replaceElement = (newElement) => (oldElement) => { const parent = oldElement.parentElement; if (isElement(parent) || isTextNode(parent)) { parent.replaceChild(createElement(newElement), oldElement); } const newEl = typeof newElement === "string" ? createElement(newElement) : newElement; if (parent) { const children = getChildElements(parent); const childIdx = children.findIndex( (c) => toHtml(c) === toHtml(oldElement) ); const updated = (children || []).map( (c, i) => i === childIdx ? newEl : c ); parent.replaceChildren(...updated); } return newEl; }; var append = (...nodes) => { const n = nodes.flat(); return (parent) => { const result = solveForNodeType("text", "node", "comment").mirror().solver({ html: (h) => pipe2(h, createElement, append(...nodes), toHtml), element: (e) => { for (const i of n) { e.append(i); } return e; }, fragment: (f) => { for (const i of n) { f.append(i); } return f; }, document: (d) => { for (const i of n) { d.body.append(i); } return d; } })(isUpdateSignature(parent) ? parent[0] : parent); return result; }; }; var into = (parent) => (...content) => { const wrapped = !!(typeof parent === "string"); let normalizedParent = wrapped ? createFragment(parent) : isElement(parent) ? parent : parent ? parent : createFragment(); const flat = isUpdateSignature(content) ? [content[0]] : content.flatMap((c) => c); if (isTextNodeLike(normalizedParent)) { throw new HappyMishap( `The wrapper node -- when calling into() -- is wrapping a text node; this is not allowed. Parent HTML: "${toHtml( normalizedParent )}"`, { name: "into()", inspect: [["parent node", parent]] } ); } const contentHtml = flat.map((c) => toHtml(c)).join(""); const transient = createFragment(contentHtml); const parentHasChildElements = normalizedParent.childElementCount > 0; if (parentHasChildElements) { for (const c of getChildren(transient)) { normalizedParent.firstChild.appendChild(clone(c)); } } else { for (const c of getChildren(transient)) { normalizedParent.append(c); } } if (isUpdateSignature(content) && isElement(content[0])) { normalizedParent = isElementLike(normalizedParent) ? normalizedParent.firstElementChild : createElement(normalizedParent); content[0].replaceWith(normalizedParent); } return wrapped && !isUpdateSignature(content) ? toHtml(normalizedParent) : normalizedParent; }; var changeTagName = (tagName) => (...args) => { const node = args[0]; const replacer = (el, tagName2) => { const open = new RegExp(`^<${el.tagName.toLowerCase()}`); const close = new RegExp(`$`); const newTag = toHtml(el).replace(open, `<${tagName2}`).replace(close, ``); if (el.parentNode && el.parentNode !== null) { el.parentNode.replaceChild(createNode(newTag), el); } return newTag; }; const areTheSame = (before2, after2) => before2.toLocaleLowerCase() === after2.toLocaleLowerCase(); return solveForNodeType().mirror().solver({ html: (h) => { const before2 = createFragment(h).firstElementChild.tagName; return areTheSame(before2, tagName) ? h : toHtml(replacer(createFragment(h).firstElementChild, tagName)); }, text: (t) => { throw new HappyMishap( "Attempt to change a tag name for a IText node. This is not allowed.", { inspect: t, name: "changeTagName(IText)" } ); }, comment: (t) => { throw new HappyMishap( "Attempt to change a tag name for a IComment node. This is not allowed.", { inspect: t, name: "changeTagName(IComment)" } ); }, node: (n) => { throw new HappyMishap( "Attempt to change a generic INode node's tag name. This is not allowed.", { inspect: n, name: "changeTagName(INode)" } ); }, element: (el) => areTheSame(el.tagName, tagName) ? el : replaceElement(replacer(el, tagName))(el), fragment: (f) => { if (f.firstElementChild) { if (f.firstElementChild.parentElement) { f.firstElementChild.replaceWith( changeTagName(tagName)(f.firstElementChild) ); } else { throw new HappyMishap( "Fragment's first child node must have a parent node to change the tag name!", { name: "changeTagName(Fragment)", inspect: f } ); } } else { throw new HappyMishap( "Fragment passed into changeTagName() has no elements as children!", { name: "changeTagName(Fragment)", inspect: f } ); } return f; }, document: (d) => { d.body.firstElementChild.replaceWith( changeTagName(tagName)(d.body.firstElementChild) ); const body = toHtml(d.body); const head = d.head.innerHTML; return createDocument(body, head); } })(node); }; var prepend = (prepend2) => (el) => { const p = typeof prepend2 === "string" ? createFragment(prepend2).firstChild : prepend2; el.prepend(p); return el; }; var before = (beforeNode) => (...afterNode) => { const outputIsHtml = typeof afterNode[0] === "string"; const beforeNormalized = typeof beforeNode === "string" ? createFragment(beforeNode).firstElementChild || createFragment(beforeNode).firstChild : createNode(beforeNode); const afterNormalized = typeof afterNode[0] === "string" ? createFragment(afterNode[0]) : isUpdateSignature(afterNode[0]) ? afterNode[0][0] : afterNode[0]; const invalidType = (n) => { throw new HappyMishap( `The before() utility was passed an invalid container type for the "after" node: ${getNodeType( n )}`, { name: `before(${getNodeType(beforeNormalized)})(${getNodeType(n)})`, inspect: n } ); }; const noParent = (n) => new HappyMishap( `the before() utility for depends on having a parent element in the "afterNode" as the parent's value must be mutated. If you do genuinely want this behavior then use a Fragment (or just HTML strings)`, { name: `before(${getNodeType(beforeNode)})(${getNodeType(n)})` } ); const node = solveForNodeType().mirror().solver({ html: (h) => pipe2(h, createFragment, before(beforeNode), toHtml), text: (t) => { if (!t.parentElement) { throw noParent(t); } t.before(beforeNormalized); return t; }, comment: (t) => { if (!t.parentElement) { throw noParent(t); } t.before(beforeNormalized); return t; }, node: (n) => invalidType(n), document: (d) => { d.body.prepend(beforeNormalized); return d; }, fragment: (f) => { f.prepend(beforeNormalized); return f; }, element: (el) => { if (el.parentElement) { el.before(beforeNormalized); return el; } else { throw noParent(el); } } })(afterNormalized); return outputIsHtml && !isUpdateSignature(afterNode) ? toHtml(node) : node; }; var after = (afterNode) => (beforeNode) => { const afterNormalized = typeof afterNode === "string" ? createFragment(afterNode).firstElementChild : afterNode; const invalidType = (n) => { throw new HappyMishap( `The after function was passed an invalid container type: ${getNodeType( n )}`, { name: `after(${getNodeType(beforeNode)})(invalid)` } ); }; return solveForNodeType().mirror().solver({ html: (h) => pipe2(h, createFragment, after(afterNode), toHtml), text: (t) => invalidType(t), comment: (t) => invalidType(t), node: (n) => invalidType(n), document: (d) => { d.body.append(afterNormalized); return d; }, fragment: (f) => { f.append(afterNormalized); return f; }, element: (el) => { if (el.parentElement) { el.after(afterNormalized); return el; } else { throw new HappyMishap( `the after() utility for depends on having a parent element in the "afterNode" as the parent's value must be mutated. If you do genuinely want this behavior then use a Fragment (or just HTML strings)`, { name: `after(${getNodeType(afterNode)})(IElement)` } ); } } })(beforeNode); }; var wrap = (...children) => (parent) => { return into(parent)(...children); }; // src/diagnostics.ts function descClass(n) { const list = getClassList(n); return list.length > 0 ? `{ ${list.join(" ")} }` : ""; } function descFrag(n) { const children = getChildren(n).map((i) => describeNode(i)); return isElementLike(n) ? `[el: ${n.firstElementChild.tagName.toLowerCase()}]${descClass}` : isTextNodeLike(n) ? `[text: ${n.textContent.slice(0, 4).replace(/\n+/g, "")}...]` : `[children: ${children.length > 0 ? `${children.join(", ")}` : "none"}]`; } var describeNode = (node) => { if (!node) { return node === null ? "[null]" : "undefined"; } else if (isUpdateSignature(node)) { return `UpdateSignature(${describeNode(node[0])})`; } else if (Array.isArray(node)) { return node.map((i) => describeNode(i)).join("\n"); } return solveForNodeType().outputType().solver({ html: (h) => pipe3(h, createFragment, describeNode), node: (n) => `node${descClass(n)}`, text: (t) => `text[${t.textContent.slice(0, 5).replace("\n", "")}...]`, comment: (t) => `comment[${t.textContent.slice(0, 5).replace("\n", "")}...]`, element: (e) => `element[${e.tagName.toLowerCase()}]${descClass(e)}`, fragment: (f) => `fragment${descFrag(f)}`, document: (d) => `doc[head: ${!!d.head}, body: ${!!d.body}]: ${describeNode( createFragment(d.body) )}` })(node); }; var inspect = (item, toJSON = false) => { const solver = Array.isArray(item) ? () => item.map((i) => describeNode(i)) : solveForNodeType().outputType().solver({ html: (h) => pipe3(h, createFragment, (f) => inspect(f)), fragment: (x) => ({ kind: "Fragment", children: `${x.children.length} / ${x.childNodes.length}`, ...x.childNodes.length > 1 ? { leadsWith: isElement(x.firstChild) ? "element" : isTextNode(x.firstChild) ? "text" : "other", endsWith: isElement(x.lastChild) ? "element" : isTextNode(x.lastChild) ? "text" : "other" } : { childNode: inspect(x.firstChild) }, content: x.textContent.length > 128 ? `${x.textContent.slice(0, 128)} ...` : x.textContent, childDetails: x.childNodes.map((i) => { try { return { html: toHtml(i), nodeType: getNodeType(i), hasParentElement: !!i.parentElement, hasParentNode: i.parentNode ? `${getNodeType(i.parentNode)} [type:${i.parentNode.nodeType}]` : false, childNodes: i.childNodes.length }; } catch { return "N/A"; } }), html: toHtml(x) }), document: (x) => { var _a, _b, _c, _d; return { kind: "Document", headerChildren: (_a = x.head.childNodes) == null ? void 0 : _a.length, bodyChildren: (_b = x.body.childNodes) == null ? void 0 : _b.length, body: toHtml(x.body), children: `${(_c = x.body.children) == null ? void 0 : _c.length} / ${(_d = x.body.childNodes) == null ? void 0 : _d.length}`, childTextContent: x.body.childNodes.map((i) => i.textContent), childDetails: x.childNodes.map((i) => { try { return { html: toHtml(i), nodeType: getNodeType(i), hasParentElement: !!i.parentElement, hasParentNode: i.parentNode ? `${getNodeType(i.parentNode)} [type:${i.parentNode.nodeType}]` : false, childNodes: i.childNodes.length }; } catch { return "N/A"; } }) }; }, text: (x) => { var _a, _b; return { kind: "IText node", textContent: x.textContent.length > 128 ? `${x.textContent.slice(0, 128)} ...` : x.textContent, children: (_a = x.childNodes) == null ? void 0 : _a.length, childContent: (_b = x.childNodes) == null ? void 0 : _b.map((i) => i.textContent) }; }, comment: (c) => { var _a, _b; return { kind: "IComment node", textContent: c.textContent.length > 128 ? `${c.textContent.slice(0, 128)} ...` : c.textContent, children: (_a = c.childNodes) == null ? void 0 : _a.length, childContent: (_b = c.childNodes) == null ? void 0 : _b.map((i) => i.textContent) }; }, element: (x) => { var _a; return { kind: "IElement node", tagName: x.tagName, classes: getClassList(x), hasNaturalParent: !!x.parentElement, ...x.parentElement ? { parent: describeNode(x.parentElement) } : {}, textContent: x.textContent, children: `${x.children.length} / ${x.childNodes.length}`, childContent: (_a = x.childNodes) == null ? void 0 : _a.map((i) => i.textContent), childDetails: x.childNodes.map((i) => { try { return { html: toHtml(i), nodeType: getNodeType(i), hasParentElement: !!i.parentElement, hasParentNode: i.parentNode ? `${getNodeType(i.parentNode)} [type:${i.parentNode.nodeType}]` : false, childNodes: i.childNodes.length }; } catch { return "N/A"; } }), html: truncate(512)(toHtml(x)) }; }, node: (n) => { var _a, _b; return { kind: "INode (generic)", looksLike: isElement(n) ? "element" : isTextNode(n) ? "text" : "unknown", children: `${(_a = n.childNodes) == null ? void 0 : _a.length}`, childContent: (_b = n.childNodes) == null ? void 0 : _b.map((i) => truncate(128)(i.textContent)), html: truncate(512)(n.toString()) }; } }); const result = isContainer(item) || typeof item === "string" ? solver(item) : { result: "not found", type: typeof item, ...typeof item === "object" && item !== null ? { keys: Object.keys(item) } : { value: JSON.stringify(item) } }; return toJSON ? JSON.stringify(result, null, 2) : result; }; var removeSpecialChars = (input) => input.replace(/\\t/g, "").replace(/\\n/g, "").trim(); var truncate = (maxLength) => (input) => input.slice(0, maxLength); var tree = (node) => { const summarize = (tree2) => { const summary = (n) => { let ts; switch (n.type) { case "text": { ts = { node: `t(${pipe3( n.node.textContent, removeSpecialChars, truncate(10) )})`, children: n.children.map((c) => summary(c)) }; break; } case "comment": { ts = { node: `c(${pipe3( n.node.textContent, removeSpecialChars, truncate(10) )})`, children: n.children.map((c) => summary(c)) }; break; } case "element": { const el = n.node; ts = { node: `el(${el.tagName.toLowerCase()})`, children: n.children.map((c) => summary(c)) }; break; } case "node": { const node2 = n.node; ts = { node: `n(${pipe3(node2.nodeName, removeSpecialChars, truncate(10)) || pipe3(node2.textContent, removeSpecialChars, truncate(10))}`, children: n.children.map((c) => summary(c)) }; break; } case "fragment": { const f = n.node; ts = { node: `frag(${f.firstElementChild ? f.firstElementChild.tagName.toLowerCase() : removeSpecialChars(f.textContent).trim().slice(0, 10)})`, children: n.children.map((c) => summary(c)) }; break; } case "document": { const d = n.node; ts = { node: `doc(${isElementLike(d) ? d.body.firstElementChild.tagName.toLowerCase() : d.textContent.slice(0, 10)})`, children: n.children.map((c) => summary(c)) }; break; } default: { ts = { node: `u(${n.toString()})`, children: n.children.map((c) => summary(c)) }; break; } } return ts; }; const recurse = (level = 0) => (node2) => { const indent = `${"".padStart(level * 6, " ")}${level > 0 ? `${level}) ` : "ROOT: "}`; return `${indent}${node2.node} ${node2.children.length > 0 ? "\u2935" : "\u21A4"} ${node2.children.map((i) => recurse(level + 1)(i))}`; }; return { ...tree2, summary: () => summary(tree2), toString: () => { const describe = summary(tree2); return ` Tree Summary: ${describe.node} ${"".padStart( 40, "-" )} ${recurse(0)(describe)}`; } }; }; const convert = (level) => solveForNodeType().outputType().solver({ html: flow2(createFragment, tree), text: (t) => summarize({ type: "text", node: t, level, children: t.childNodes.map((c) => convert(level + 1)(c)) }), comment: (c) => summarize({ type: "comment", node: c, level, children: c.childNodes.map((i) => convert(level + 1)(i)) }), element: (e) => summarize({ type: "element", node: e, level, children: e.childNodes.map((c) => convert(level + 1)(c)) }), node: (n) => summarize({ type: "node", node: n, level, children: n.childNodes.map((c) => convert(level + 1)(c)) }), fragment: (f) => summarize({ type: "fragment", node: f, level, children: f.childNodes.map((c) => convert(level + 1)(c)) }), document: (d) => summarize({ type: "document", node: d, level, children: d.childNodes.map((c) => convert(level + 1)(c)) }) }); return convert(0)(node); }; var siblings = (...content) => { return into()(...content); }; // src/errors.ts var HappyMishap = class extends Error { constructor(message, options = {}) { var _a; super(); this.name = "HappyWrapper"; this.kind = "HappyWrapper"; this.trace = []; this.message = ` ${message}`; if (options.name) { this.name = `HappyWrapper::${options.name || "unknown"}`; } try { const sites = callsites(); this.structuredStack = (sites || []).slice(1).map((i) => { var _a2; return { fn: i.getFunctionName() || i.getMethodName() || ((_a2 = i.getFunction()) == null ? void 0 : _a2.name) || "", line: i.getLineNumber() || void 0, file: i.getFileName() ? relative(process.cwd(), i.getFileName()) : "" }; }) || []; } catch { this.structuredStack = []; } this.fn = this.structuredStack[0].fn || ""; this.file = this.structuredStack[0].file || ""; this.line = this.structuredStack[0].line || null; if (isHappyWrapperError(options.error)) { this.name = `[file: ${this.file}, line: ${this.line}] HappyWrapper::${options.name || options.error.name}`; } if (options.error) { const name = options.error instanceof Error ? options.error.name.replace("HappyWrapper::", "") : "unknown"; const underlying = ` The underlying error message [${name}] was: ${options.error instanceof Error ? options.error.message : String(options.error)}`; this.message = `${this.message}${underlying}`; this.trace = [...this.trace, name]; } else { if (options.inspect) { const inspections = isInspectionTuple(options.inspect) ? [options.inspect] : Array.isArray(options.inspect) ? options.inspect : [options.inspect]; for (const [idx, i] of inspections.entries()) { const intro = isInspectionTuple(i) ? `${i[0]} ` : `${[idx]}: `; const container = isInspectionTuple(i) ? i[1] : i; this.message = `${this.message} ${intro}${JSON.stringify( inspect(container), null, 2 )}`; } } if (this.trace.length > 1) { this.message = `${this.message} Trace:${this.trace.map( (i, idx) => `${idx}. ${i}` )}`; } } this.message = `${this.message} `; for (const l of this.structuredStack) { this.message = ((_a = l.file) == null ? void 0 : _a.includes(".pnpm")) ? this.message : `${this.message} - ${l.fn ? `${l.fn}() ` : ""}${l.file}:${l.line}`; } this.structuredStack = []; } toJSON() { return { name: this.name, message: this.message }; } toString() { return { name: this.name, message: this.message }; } }; // src/create.ts function createDocument(body, head) { const window = new Window(); const document = window.document; document.body.innerHTML = body; if (head) { document.head.innerHTML = head; } return document; } function createFragment(content) { const window = new Window(); const document = window.document; const fragment = document.createDocumentFragment(); if (content) { fragment.append(clone(content)); } return fragment; } var createNode = (node) => { const frag = createFragment(node); if (isElementLike(frag)) { return frag.firstElementChild; } else if (isTextNodeLike(frag)) { return frag.firstChild; } else { throw new HappyMishap( "call to createNode() couldn't be converted to IElement or IText node", { name: "createNode()", inspect: node } ); } }; function createTextNode(text) { if (!text) { return new Text(""); } const frag = createFragment(text); if (isTextNodeLike(frag)) { return frag.firstChild; } else { throw new HappyMishap( `The HTML passed in cannot be converted to a single text node: "${text}".`, { name: "createFragment(text)", inspect: frag } ); } } function createCommentNode(comment) { return new Comment(comment); } var createElement = (el, parent) => solveForNodeType().outputType().solver({ node: (n) => { if (isElement(n)) { return createElement(n); } else { throw new HappyMishap( "can't create an IElement from an INode node because it doesn't have a tagName property", { inspect: n } ); } }, html: (h) => { const frag = createFragment(h); if (isElementLike(frag)) { if (parent) { parent.append(frag.firstElementChild); return parent == null ? void 0 : parent.lastElementChild; } return frag.firstElementChild; } else { throw new HappyMishap( "The HTML passed into createElement() is not convertible to a IElement node!", { name: "createElement(html)", inspect: frag } ); } }, element: identity, text: (t) => { throw new HappyMishap( "An IElement can not be created from a IText node because element's require a wrapping tag name!", { name: "createElement(text)", inspect: t } ); }, comment: (t) => { throw new HappyMishap( "An IElement can not be created from a IComment node because element's require a wrapping tag name!", { name: "createElement(comment)", inspect: t } ); }, fragment: (f) => { if (isElement(f.firstElementChild)) { return f.firstElementChild; } else { throw new HappyMishap( `Unable to create a IElement node from: ${toHtml(f)}`, { name: "createElement()" } ); } }, document: (d) => { if (isElementLike(d)) { if (parent) { throw new HappyMishap( "A Document and a parent IElement were passed into createElement. This is not a valid combination!" ); } return d.firstElementChild; } else { throw new HappyMishap( "Can not create an Element from passed in Document", { name: "createElement(document)", inspect: d } ); } } })(el); var renderClasses = (klasses) => { return klasses.map( ([selector, defn]) => ` ${selector} { ${Object.keys(defn).map((p) => ` ${dasherize(p)}: ${defn[p]};`).join("\n")} }` ).join("\n"); }; var createInlineStyle = (type = "text/css") => { const cssVariables = {}; const cssClasses = []; let isVueBlock = false; let isScoped = true; let vueLang = "css"; const api = { addCssVariable(prop, value, scope = ":root") { if (!(scope in cssVariables)) { cssVariables[scope] = []; } cssVariables[scope].push({ prop: prop.replace(/^--/, ""), value }); return api; }, addClassDefinition(selector, cb) { const classApi = { addChild: (child, defn) => { const childSelector = `${selector} ${child}`; cssClasses.push([childSelector, defn]); return classApi; }, addProps: (defn) => { cssClasses.push([selector, defn]); return classApi; } }; cb(classApi); return api; }, addCssVariables(dictionary, scope = ":root") { for (const p of Object.keys(dictionary)) { api.addCssVariable(p, dictionary[p], scope); } return api; }, convertToVueStyleBlock(lang, scoped = true) { vueLang = lang; isVueBlock = true; isScoped = scoped; return api; }, finish() { const setVariable = (scope, defn) => `${scope} { ${Object.keys(defn).map( (prop) => ` --${defn[prop].prop}: ${defn[prop].value}${String(defn.prop).endsWith(";") ? "" : ";"}` ).join("\n")} }`; let text = ""; for (const v of Object.keys(cssVariables)) { text = `${text}${setVariable(v, cssVariables[v])} `; } text = `${text}${renderClasses(cssClasses)}`; return isVueBlock ? createElement( `` ) : createElement(``); } }; return api; }; // src/attributes.ts var setAttribute = (attr) => (value) => (node) => { const invalidNode = (n) => { throw new HappyMishap( `You can not use the setAttribute() utility on a node of type: "${getNodeType( n )}"`, { name: `setAttribute(${attr})(${value})(INVALID)` } ); }; const result = solveForNodeType().mirror().solver({ html: (h) => pipe4(h, createFragment, (f) => setAttribute(attr)(value)(f), toHtml), text: (t) => invalidNode(t), comment: (t) => invalidNode(t), node: (n) => invalidNode(n), fragment: (f) => { f.firstElementChild.setAttribute(attr, value); return f; }, document: (d) => { d.body.firstElementChild.setAttribute(attr, value); return d; }, element: (e) => { e.setAttribute(attr, value); return e; } })(node); return result; }; var getAttribute = (attr) => { return solveForNodeType("text", "node", "comment").outputType().solver({ html: (h) => pipe4(h, createFragment, getAttribute(attr)), fragment: (f) => f.firstElementChild.getAttribute(attr), document: (doc) => doc.body.firstElementChild.getAttribute(attr), element: (el) => el.getAttribute(attr) }); }; var getClass = getAttribute("class"); var setClass = setAttribute("class"); var getClassList = (container) => { if (!container) { return []; } return solveForNodeType().outputType().solver({ html: (h) => pipe4(h, createFragment, getClassList), document: (d) => { var _a; return ((_a = getClass(d.body.firstElementChild)) == null ? void 0 : _a.split(/\s+/)) || []; }, fragment: (f) => { var _a; return ((_a = getClass(f.firstElementChild)) == null ? void 0 : _a.split(/\s+/)) || []; }, element: (e) => { var _a; return ((_a = getClass(e)) == null ? void 0 : _a.split(/\s+/)) || []; }, text: (n) => { throw new HappyMishap("Passed in a text node to getClassList!", { name: "getClassList", inspect: n }); }, comment: (n) => { throw new HappyMishap("Passed in a comment node to getClassList!", { name: "getClassList", inspect: n }); }, node: (n) => { throw new HappyMishap( "Passed in an unknown node type to getClassList!", { name: "getClassList", inspect: n } ); } })(container).filter(Boolean); }; var removeClass = (remove) => (doc) => { var _a; const current = ((_a = getClass(doc)) == null ? void 0 : _a.split(/\s+/g)) || []; const toRemove = Array.isArray(remove) ? remove : [remove]; const resultantClassString = [ ...new Set(current.filter((c) => !toRemove.includes(c))) ].filter(Boolean).join(" "); return setClass(resultantClassString)(doc); }; var addClass = (...add) => (doc) => { var _a; const toAdd = Array.isArray(add) ? add.flat() : [add]; const currentClasses = ((_a = getClass(doc)) == null ? void 0 : _a.split(/\s+/g)) || []; const resultantClasses = [ .../* @__PURE__ */ new Set([...currentClasses, ...toAdd]) ]; return setClass(resultantClasses.join(" ").trim())(doc); }; var addVueEvent = (event, value) => { return (el) => { const isHtml = typeof el === "string"; const bound = getAttribute("v-bind")(isHtml ? createElement(el) : el); const bind = bound ? bound.replace("}", `, ${event}: '${value}' }`) : `{ ${event}: "${value}" }`; const e2 = setAttribute("v-bind")(bind)(el); return isHtml ? toHtml(e2) : el; }; }; function hasFilterCallback(filters) { return typeof filters[0] === "function"; } var filterClasses = (...args) => (doc) => { const el = isDocument(doc) || isFragment(doc) ? doc.firstElementChild : isElement(doc) ? doc : null; if (!el) { throw new HappyMishap( "An invalid container was passed into filterClasses()!", { name: "filterClasses", inspect: doc } ); } const filters = hasFilterCallback(args) ? args.slice(1) : args; const cb = hasFilterCallback(args) ? args[0] : void 0; const classes = getClassList(el); const removed = []; for (const klass of classes) { const matched = !filters.every( (f) => typeof f === "string" ? f.trim() !== klass.trim() : !f.test(klass) ); if (matched) { removed.push(klass); } } setClass(classes.filter((k) => !removed.includes(k)).join(" "))(doc); if (cb) { cb(removed); } return doc; }; var hasParentElement = (node) => { const n = typeof node === "string" ? createNode(node) : node; return solveForNodeType().outputType().solver({ html: () => false, text: (t) => !!t.parentElement, comment: (t) => !!t.parentElement, element: (e) => !!e.parentElement, fragment: (f) => !!f.parentElement, document: () => true, node: (n2) => !!n2.parentElement })(n); }; var getParent = (node) => { return hasParentElement(node) ? node.parentElement : null; }; // src/select.ts var select = (node) => { const originIsHtml = typeof node === "string"; let rootNode = originIsHtml ? createFragment(node) : isElement(node) ? node : isDocument(node) || isFragment(node) ? node : void 0; if (!rootNode) { throw new HappyMishap( `Attempt to select() an invalid node type: ${getNodeType(node)}`, { name: "select(INode)", inspect: node } ); } const api = { type: () => { return originIsHtml ? "html" : getNodeType(rootNode); }, findAll: (sel) => { return sel ? rootNode.querySelectorAll(sel) : getChildElements(rootNode); }, findFirst: (sel, errorMsg) => { const result = rootNode.querySelector(sel); if (!result && errorMsg) { throw new HappyMishap( `${errorMsg}. The HTML from the selected DOM node is: ${toHtml( rootNode )}`, { name: "select.findFirst()", inspect: rootNode } ); } return result; }, append: (content) => { if (!content) { return api; } const nodes = Array.isArray(content) ? content.filter(Boolean) : [content]; rootNode.append(...nodes); return api; }, update: (selection, errorIfNotFound = false) => (mutate) => { const el = selection ? rootNode == null ? void 0 : rootNode.querySelector(selection) : isElement(rootNode) ? rootNode : rootNode.firstElementChild ? rootNode.firstElementChild : null; if (el) { let elReplacement; try { elReplacement = mutate( el, 0, 1 ); } catch (error) { throw new HappyMishap( `update(): the passed in callback to select(container).update('${selection}')(): mutate(${describeNode( el )}, 0, 1) ${error instanceof Error ? error.message : String(error)}.`, { name: `select(${typeof rootNode}).updateAll(${selection})(mutation fn)`, inspect: el } ); } if (elReplacement === false) { el.remove(); } else if (!isElement(elReplacement)) { throw new HappyMishap( `The return value for a call to select(${getNodeType( rootNode )}).update(${selection}) return an invalid value! Value return values are an IElement or false.`, { name: "select.update", inspect: el } ); } } else { if (errorIfNotFound) { throw new HappyMishap( errorIfNotFound === true ? `The selection "${selection}" was not found so the update() operation wasn't able to be run` : errorIfNotFound, { name: `select(${selection}).update(sel)`, inspect: ["parent node", rootNode] } ); } if (!selection) { throw new HappyMishap( `Call to select(container).update() was intended to target the root node of the selection but nothing was selected! This shouldn't really happen ... the rootNode's type is ${typeof rootNode}${typeof rootNode === "object" ? `, ${getNodeType(rootNode)} [element-like: ${isElementLike( rootNode )}, element: ${isElement(rootNode)}, children: ${rootNode.childNodes.length}]` : ""}` ); } } return api; }, updateAll: (selection) => (mutate) => { const elements = selection ? rootNode.querySelectorAll(selection) : getChildElements(rootNode); for (const [idx, el] of elements.entries()) { if (isElement(el)) { let elReplacement; try { elReplacement = mutate( el, idx, elements.length ); } catch (error) { throw new HappyMishap( `updateAll(): the passed in callback to select(container).updateAll('${selection}')(): mutate(${describeNode( el )}, ${idx} idx, ${elements.length} elements) ${error instanceof Error ? error.message : String(error)}.`, { name: `select(${typeof rootNode}).updateAll(${selection})(mutation fn)`, inspect: el } ); } if (elReplacement === false) { el.remove(); } else if (!isElement(elReplacement)) { throw new HappyMishap( `The return value from the "select(container).updateAll('${selection}')(${describeNode( el )}, ${idx} idx, ${elements.length} elements)" call was invalid! Valid return values are FALSE or an IElement but instead got: ${typeof elReplacement}.`, { name: "select().updateAll -> invalid return value" } ); } } else { throw new Error( `Ran into an unknown node type while running updateAll(): ${JSON.stringify( inspect(el), null, 2 )}` ); } } return api; }, mapAll: (selection) => (mutate) => { const collection = []; const elements = selection ? rootNode.querySelectorAll(selection) : getChildElements(rootNode); for (const el of elements) { collection.push(mutate(clone(el))); } return collection; }, filterAll: (selection, cb) => { for (const el of rootNode == null ? void 0 : rootNode.querySelectorAll(selection)) { if (cb) { cb(el); } el.remove(); } return api; }, wrap: (wrapper, errMsg) => { try { const safeWrap = typeof wrapper === "string" ? createElement(wrapper) : wrapper; rootNode = wrap(rootNode)(safeWrap); return api; } catch (error) { if (isHappyWrapperError(error) || error instanceof Error) { error.message = errMsg ? `Error calling select.wrap(): ${errMsg} ${error.message}` : `Error calling select.wrap(): ${error.message}`; throw error; } throw error; } }, toContainer: () => { return originIsHtml ? toHtml(rootNode) : rootNode; } }; return api; }; export { HappyMishap, addClass, addVueEvent, after, append, before, changeTagName, clone, createCommentNode, createDocument, createElement, createFragment, createInlineStyle, createNode, createTextNode, describeNode, extract, filterClasses, getAttribute, getChildElements, getChildren, getClassList, getNodeType, getParent, hasParentElement, hasSingularElement, inspect, into, isContainer, isDocument, isElement, isElementLike, isFragment, isHappyWrapperError, isInspectionTuple, isTextNode, isTextNodeLike, isUpdateSignature, nodeBoundedByElements, nodeChildrenAllElements, nodeEndsWithElement, nodeStartsWithElement, nodeTypeLookup, placeholder, prepend, removeClass, replaceElement, safeString, select, setAttribute, siblings, solveForNodeType, toHtml, tree, wrap }; //# sourceMappingURL=index.js.map