|
- // 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) => `<!-- ${h.textContent} -->`,
- 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) => `<html>${d.head.hasChildNodes() ? d.head.outerHTML : ""}${d.body.outerHTML}</html>`,
- 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("<placeholder></placeholder>");
- 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(`</${el.tagName.toLowerCase()}>$`);
- const newTag = toHtml(el).replace(open, `<${tagName2}`).replace(close, `</${tagName2}>`);
- 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(
- `<style lang="${vueLang}"${isScoped ? " scoped" : ""}>
- ${text}
- </style>`
- ) : createElement(`<style type="${type}">
- ${text}
- </style>`);
- }
- };
- 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
|