update to v2.3.0
add `.rep()` & `.replaceChildren()` function update `.app()` & `.append()` to support rest params update build target to ES6 fix comment color on demo page add (more) tests
This commit is contained in:
4
dist/demo.html
vendored
4
dist/demo.html
vendored
@@ -148,6 +148,10 @@
|
|||||||
/\`[^`]+\`/g,
|
/\`[^`]+\`/g,
|
||||||
(val) => `<span class="code-str">${val}</span>`,
|
(val) => `<span class="code-str">${val}</span>`,
|
||||||
)
|
)
|
||||||
|
.replace(
|
||||||
|
/\/\/.*/g,
|
||||||
|
(val) => `<span class="code-cmnt">${val}</span>`,
|
||||||
|
)
|
||||||
.replace(/\.\w+/g, (val) =>
|
.replace(/\.\w+/g, (val) =>
|
||||||
val !== ".js"
|
val !== ".js"
|
||||||
? `<span class="code-func">${val}</span>`
|
? `<span class="code-func">${val}</span>`
|
||||||
|
77
dist/fluent-dom-esm.js
vendored
77
dist/fluent-dom-esm.js
vendored
@@ -4,22 +4,22 @@ const isHTMLElement = (value) => !!value.nodeType;
|
|||||||
const isNumber = (value) => typeof value === "number";
|
const isNumber = (value) => typeof value === "number";
|
||||||
const isString = (value) => typeof value === "string";
|
const isString = (value) => typeof value === "string";
|
||||||
/**
|
/**
|
||||||
* fluent-dom-esm v2.2.1
|
* fluent-dom-esm v2.3.0
|
||||||
*
|
*
|
||||||
* Fluent DOM Manipulation, adapted to ESM and cranked up to v2.2(.1).
|
* Fluent DOM Manipulation, adapted to ESM and cranked up to v2.3(.0).
|
||||||
*
|
*
|
||||||
* https://git.itsericwoodward.com/eric/fluent-dom-esm
|
* https://git.itsericwoodward.com/eric/fluent-dom-esm
|
||||||
*
|
*
|
||||||
* v2.2.1 Copyright (c) 2025 Eric Woodward
|
* v2.3.0 Copyright (c) 2025 Eric Woodward
|
||||||
* Original copyright (c) 2009 Tommy Montgomery (https://glacius.tmont.com/articles/fluent-dom-manipulation-in-javascript)
|
* Original copyright (c) 2009 Tommy Montgomery (https://glacius.tmont.com/articles/fluent-dom-manipulation-in-javascript)
|
||||||
*
|
*
|
||||||
* Released under the WTFPL (Do What the Fuck You Want to Public License)
|
* Released under the WTFPL (Do What the Fuck You Want to Public License)
|
||||||
*
|
*
|
||||||
* @author Eric Woodward (v2 update)
|
* @author Eric Woodward (v2+)
|
||||||
* @author Tommy Montgomery (original)
|
* @author Tommy Montgomery (original)
|
||||||
* @license http://sam.zoy.org/wtfpl/
|
* @license http://sam.zoy.org/wtfpl/
|
||||||
*/
|
*/
|
||||||
const APP_VERSION = "2.2.1";
|
const APP_VERSION = "2.3.0";
|
||||||
const fluentDomEsm = (function() {
|
const fluentDomEsm = (function() {
|
||||||
const FluentDom = function(nodeOrQuerySelector) {
|
const FluentDom = function(nodeOrQuerySelector) {
|
||||||
if (typeof nodeOrQuerySelector !== "string")
|
if (typeof nodeOrQuerySelector !== "string")
|
||||||
@@ -40,35 +40,43 @@ const fluentDomEsm = (function() {
|
|||||||
let root = node || null;
|
let root = node || null;
|
||||||
this.fluentDom = APP_VERSION;
|
this.fluentDom = APP_VERSION;
|
||||||
this.a = this.attr = function(name, value) {
|
this.a = this.attr = function(name, value) {
|
||||||
if (!root || typeof name === "undefined" || typeof value === "undefined") {
|
if (!root) {
|
||||||
throw new Error("Cannot set an attribute on a non-element");
|
throw new Error("Cannot set an attribute on a non-element");
|
||||||
}
|
}
|
||||||
|
if (typeof name === "undefined") {
|
||||||
|
throw new Error("Cannot set an attribute without a name");
|
||||||
|
}
|
||||||
root.setAttribute(name, value);
|
root.setAttribute(name, value);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
this.app = this.append = function(value) {
|
this.app = this.append = function(...content) {
|
||||||
if (!root || !root?.appendChild) {
|
if (!root || !root?.appendChild) {
|
||||||
throw new Error("Cannot append to a non-element");
|
throw new Error("Cannot append to a non-element");
|
||||||
}
|
}
|
||||||
const type = typeof value;
|
if (!content || content.length < 1) {
|
||||||
if (type === "object") {
|
throw new Error("Cannot append without a value");
|
||||||
if (isFluentDomObject(value)) {
|
}
|
||||||
const domVal = value.toDom();
|
content.forEach((value) => {
|
||||||
if (domVal !== null) root.appendChild(domVal);
|
const type = typeof value;
|
||||||
} else if (isHTMLElement(value)) {
|
if (type === "object") {
|
||||||
root.appendChild(value);
|
if (isFluentDomObject(value)) {
|
||||||
|
const domVal = value.toDom();
|
||||||
|
if (domVal !== null) root?.appendChild(domVal);
|
||||||
|
} else if (isHTMLElement(value)) {
|
||||||
|
root?.appendChild(value);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Invalid argument: not an HTMLElement or FluentDom object"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (isNumber(value) || isString(value)) {
|
||||||
|
root?.appendChild(document.createTextNode(`${value}`));
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Invalid argument: not an HTMLElement or FluentDom object"
|
`Invalid argument: not a valid type (${typeof value})`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (isNumber(value) || isString(value)) {
|
});
|
||||||
root.appendChild(document.createTextNode(`${value}`));
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid argument: not a valid type (${typeof value})`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
this.c = this.create = function(tagName) {
|
this.c = this.create = function(tagName) {
|
||||||
@@ -87,9 +95,7 @@ const fluentDomEsm = (function() {
|
|||||||
};
|
};
|
||||||
this.html = function(content) {
|
this.html = function(content) {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
throw new Error(
|
throw new Error("Cannot set innerHTML for a non-element");
|
||||||
"Cannot get or set innerHTML for a non-element"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
root.innerHTML = content;
|
root.innerHTML = content;
|
||||||
return this;
|
return this;
|
||||||
@@ -108,6 +114,25 @@ const fluentDomEsm = (function() {
|
|||||||
root = document.querySelector(selector);
|
root = document.querySelector(selector);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
this.rep = this.replaceChildren = function(...content) {
|
||||||
|
if (!root) {
|
||||||
|
throw new Error("Cannot replaceChildren on a non-element");
|
||||||
|
}
|
||||||
|
if (!root.replaceChildren) {
|
||||||
|
if (!content) return this.html("");
|
||||||
|
return this.html("").append(...content);
|
||||||
|
}
|
||||||
|
if (content.length && content[0] && isFluentDomObject(content[0])) {
|
||||||
|
const domValues = content.map(
|
||||||
|
(val) => val.toDom()
|
||||||
|
);
|
||||||
|
root.replaceChildren(
|
||||||
|
...domValues.filter((val) => val !== null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
root.replaceChildren(...content);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
function styleFunction(prop, value) {
|
function styleFunction(prop, value) {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
throw new Error("Cannot get or set style for a non-element");
|
throw new Error("Cannot get or set style for a non-element");
|
||||||
@@ -150,7 +175,7 @@ const fluentDomEsm = (function() {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
this.v = this.version = function() {
|
this.v = this.version = function() {
|
||||||
return APP_VERSION;
|
return this.fluentDom;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return FluentDom;
|
return FluentDom;
|
||||||
|
8
dist/fluent-dom-esm.types.d.ts
vendored
8
dist/fluent-dom-esm.types.d.ts
vendored
@@ -1,9 +1,9 @@
|
|||||||
export interface FluentDomObject {
|
export interface FluentDomObject {
|
||||||
(nodeOrQuerySelector: string | HTMLElement): FluentDomObject;
|
(nodeOrQuerySelector: HTMLElement | string): FluentDomObject;
|
||||||
fluentDom: string;
|
fluentDom: string;
|
||||||
a: (name: string, value: string) => FluentDomObject;
|
a: (name: string, value: string) => FluentDomObject;
|
||||||
app: (obj: FluentDomObject | HTMLElement | string) => FluentDomObject;
|
app: (...content: (FluentDomObject | HTMLElement | string)[]) => FluentDomObject;
|
||||||
append: (obj: FluentDomObject | HTMLElement | string) => FluentDomObject;
|
append: (...content: (FluentDomObject | HTMLElement | string)[]) => FluentDomObject;
|
||||||
attr: (name: string, value: string) => FluentDomObject;
|
attr: (name: string, value: string) => FluentDomObject;
|
||||||
c: (tagName: string) => FluentDomObject;
|
c: (tagName: string) => FluentDomObject;
|
||||||
className: (className: string) => FluentDomObject;
|
className: (className: string) => FluentDomObject;
|
||||||
@@ -19,6 +19,8 @@ export interface FluentDomObject {
|
|||||||
listen: (type: keyof HTMLElementEventMap, listener: () => {}, optionsOrUseCapture?: boolean | object) => FluentDomObject;
|
listen: (type: keyof HTMLElementEventMap, listener: () => {}, optionsOrUseCapture?: boolean | object) => FluentDomObject;
|
||||||
q: (selector: string) => FluentDomObject;
|
q: (selector: string) => FluentDomObject;
|
||||||
querySelector: (selector: string) => FluentDomObject;
|
querySelector: (selector: string) => FluentDomObject;
|
||||||
|
rep: (...content: (FluentDomObject | HTMLElement | string)[]) => FluentDomObject;
|
||||||
|
replaceChildren: (...content: (FluentDomObject | HTMLElement | string)[]) => FluentDomObject;
|
||||||
s: ((prop: CSSStyleDeclaration) => FluentDomObject) | ((prop: string, value: string) => FluentDomObject);
|
s: ((prop: CSSStyleDeclaration) => FluentDomObject) | ((prop: string, value: string) => FluentDomObject);
|
||||||
style: ((prop: CSSStyleDeclaration) => FluentDomObject) | ((prop: string, value: string) => FluentDomObject);
|
style: ((prop: CSSStyleDeclaration) => FluentDomObject) | ((prop: string, value: string) => FluentDomObject);
|
||||||
t: (text: string) => FluentDomObject;
|
t: (text: string) => FluentDomObject;
|
||||||
|
2
jsr.json
2
jsr.json
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@itsericwoodward/fluent-dom-esm",
|
"name": "@itsericwoodward/fluent-dom-esm",
|
||||||
"version": "2.2.1",
|
"version": "2.3.0",
|
||||||
"exports": "./src/fluent-dom-esm.ts"
|
"exports": "./src/fluent-dom-esm.ts"
|
||||||
}
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "fluent-dom-esm",
|
"name": "fluent-dom-esm",
|
||||||
"version": "2.2.1",
|
"version": "2.3.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "WTFPL",
|
"license": "WTFPL",
|
||||||
"exports": {
|
"exports": {
|
||||||
|
@@ -148,6 +148,10 @@
|
|||||||
/\`[^`]+\`/g,
|
/\`[^`]+\`/g,
|
||||||
(val) => `<span class="code-str">${val}</span>`,
|
(val) => `<span class="code-str">${val}</span>`,
|
||||||
)
|
)
|
||||||
|
.replace(
|
||||||
|
/\/\/.*/g,
|
||||||
|
(val) => `<span class="code-cmnt">${val}</span>`,
|
||||||
|
)
|
||||||
.replace(/\.\w+/g, (val) =>
|
.replace(/\.\w+/g, (val) =>
|
||||||
val !== ".js"
|
val !== ".js"
|
||||||
? `<span class="code-func">${val}</span>`
|
? `<span class="code-func">${val}</span>`
|
||||||
|
219
src/__tests__/fluent-dom-esm.append.test.ts
Normal file
219
src/__tests__/fluent-dom-esm.append.test.ts
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
|
describe(".app() and .append()", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body.replaceChildren();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support single FluentDomObject argument", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app($d.c("div").id("item2").t("Item 2"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append($d.c("div").id("item2").t("Item 2"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support multiple FluentDomObject arguments for `.app()` and `.append()`", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add children
|
||||||
|
$d(document.body).app(
|
||||||
|
$d.c("div").id("item1").t("Item 1"),
|
||||||
|
$d.c("div").id("item2").t("Item 2"),
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add children
|
||||||
|
$d(document.body).append(
|
||||||
|
$d.c("div").id("item1").t("Item 1"),
|
||||||
|
$d.c("div").id("item2").t("Item 2"),
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support single HTMLElement argument for `.app()` and `.append()`", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app(
|
||||||
|
$d.c("div").id("item1").t("Item 1").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app(
|
||||||
|
$d.c("div").id("item2").t("Item 2").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append(
|
||||||
|
$d.c("div").id("item1").t("Item 1").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append(
|
||||||
|
$d.c("div").id("item2").t("Item 2").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support multiple HTMLElement arguments for `.app()` and `.append()`", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add children
|
||||||
|
$d(document.body).app(
|
||||||
|
$d.c("div").id("item1").t("Item 1").toDom() ?? "",
|
||||||
|
$d.c("div").id("item2").t("Item 2").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append(
|
||||||
|
$d.c("div").id("item1").t("Item 1").toDom() ?? "",
|
||||||
|
$d.c("div").id("item2").t("Item 2").toDom() ?? "",
|
||||||
|
);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
expect(body?.children[1]).toHaveAttribute("id", "item2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support single string argument for `.app()` and `.append()`", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append("Item 1");
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app("Item 2");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append("Item 1");
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app("Item 2");
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support multiple string arguments for `.app()` and `.append()`", () => {
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add children
|
||||||
|
$d(document.body).append("Item 1", "Item 2");
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// reset
|
||||||
|
body?.replaceChildren();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).append("Item 1", "Item 2");
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("Item 2");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
});
|
||||||
|
});
|
67
src/__tests__/fluent-dom-esm.attr.test.ts
Normal file
67
src/__tests__/fluent-dom-esm.attr.test.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
|
describe(".a() and .attr()", () => {
|
||||||
|
it("adds an attribute to the wrapped HTMLElement", () => {
|
||||||
|
// create base anchor
|
||||||
|
const $a1 = $d.c("a");
|
||||||
|
expect($a1.toDom()).not.toBeNull();
|
||||||
|
expect($a1.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($a1.toDom()?.outerHTML).toEqual("<a></a>");
|
||||||
|
expect($a1.toDom()?.getAttribute("href")).toBeNull();
|
||||||
|
|
||||||
|
// add href attribute
|
||||||
|
$a1.a("href", "http://example.com");
|
||||||
|
expect($a1.toDom()?.getAttribute("href")).not.toBeNull();
|
||||||
|
expect($a1.toDom()?.getAttribute("href")).toEqual("http://example.com");
|
||||||
|
|
||||||
|
// create base anchor
|
||||||
|
const $a2 = $d.c("a");
|
||||||
|
expect($a2.toDom()).not.toBeNull();
|
||||||
|
expect($a2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($a2.toDom()?.outerHTML).toEqual("<a></a>");
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).toBeNull();
|
||||||
|
|
||||||
|
// add href attribute
|
||||||
|
$a2.attr("href", "mailto:someone@somewhere.com");
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).not.toBeNull();
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).toEqual(
|
||||||
|
"mailto:someone@somewhere.com",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("disables a form element when the 'disabled' attribute is set", () => {
|
||||||
|
const $button1 = $d.c("button").t("click me");
|
||||||
|
expect($button1.toDom()).not.toBeNull();
|
||||||
|
expect($button1.toDom()).not.toBeDisabled();
|
||||||
|
$button1.a("disabled", "");
|
||||||
|
expect($button1.toDom()).toBeDisabled();
|
||||||
|
$button1.a("name", "button1");
|
||||||
|
expect($button1.toDom()?.getAttribute("name")).toEqual("button1");
|
||||||
|
|
||||||
|
const $button2 = $d.c("button").t("click me");
|
||||||
|
expect($button2.toDom()).not.toBeNull();
|
||||||
|
expect($button2.toDom()).not.toBeDisabled();
|
||||||
|
$button2.attr("disabled", "");
|
||||||
|
expect($button2.toDom()).toBeDisabled();
|
||||||
|
$button1.attr("name", "button2");
|
||||||
|
expect($button1.toDom()?.getAttribute("name")).toEqual("button2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("updates the HTMLElements dataset when a data attribute is set", () => {
|
||||||
|
const $div1 = $d.c("div");
|
||||||
|
expect($div1.toDom()).not.toBeNull();
|
||||||
|
expect($div1.toDom()?.dataset).toEqual({});
|
||||||
|
$div1.a("data-test", "some data");
|
||||||
|
expect($div1.toDom()?.dataset).toEqual({ test: "some data" });
|
||||||
|
|
||||||
|
const $div2 = $d.c("div");
|
||||||
|
expect($div2.toDom()).not.toBeNull();
|
||||||
|
expect($div2.toDom()?.dataset).toEqual({});
|
||||||
|
$div2.a("data-test", "some more data");
|
||||||
|
expect($div2.toDom()?.dataset).toEqual({ test: "some more data" });
|
||||||
|
});
|
||||||
|
});
|
50
src/__tests__/fluent-dom-esm.create.test.ts
Normal file
50
src/__tests__/fluent-dom-esm.create.test.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
|
describe(".c() and .create()", () => {
|
||||||
|
it("should create an FluentDomObject-wrapped HTMLElement", () => {
|
||||||
|
const $div1 = $d(document.body).c("div");
|
||||||
|
expect($div1.toDom()).not.toBeNull();
|
||||||
|
expect($div1.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($div1.toDom()?.outerHTML).toEqual("<div></div>");
|
||||||
|
expect($div1.fluentDom).toBeDefined();
|
||||||
|
expect($div1.fluentDom).toEqual($div1.version());
|
||||||
|
|
||||||
|
const $span1 = $d(document.body).c("span");
|
||||||
|
expect($span1.toDom()).not.toBeNull();
|
||||||
|
expect($span1.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($span1.toDom()?.outerHTML).toEqual("<span></span>");
|
||||||
|
expect($span1.fluentDom).toBeDefined();
|
||||||
|
expect($span1.fluentDom).toEqual($span1.version());
|
||||||
|
|
||||||
|
const $div2 = $d(document.body).create("div");
|
||||||
|
expect($div2.toDom()).not.toBeNull();
|
||||||
|
expect($div2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($div2.toDom()?.outerHTML).toEqual("<div></div>");
|
||||||
|
expect($div2.fluentDom).toBeDefined();
|
||||||
|
expect($div2.fluentDom).toEqual($div2.version());
|
||||||
|
|
||||||
|
const $span2 = $d(document.body).create("span");
|
||||||
|
expect($span2.toDom()).not.toBeNull();
|
||||||
|
expect($span2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($span2.toDom()?.outerHTML).toEqual("<span></span>");
|
||||||
|
expect($span2.fluentDom).toBeDefined();
|
||||||
|
expect($span2.fluentDom).toEqual($span2.version());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should replace the current object with a new object", () => {
|
||||||
|
// default state
|
||||||
|
let $el = $d(document.body);
|
||||||
|
expect($el.toDom()).not.toBeNull();
|
||||||
|
expect($el.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($el.toDom()?.outerHTML).toEqual("<body></body>");
|
||||||
|
|
||||||
|
$el = $el.c("ul");
|
||||||
|
expect($el.toDom()).not.toBeNull();
|
||||||
|
expect($el.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($el.toDom()?.outerHTML).toEqual("<ul></ul>");
|
||||||
|
});
|
||||||
|
});
|
67
src/__tests__/fluent-dom-esm.object.test.ts
Normal file
67
src/__tests__/fluent-dom-esm.object.test.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
|
describe("base object", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body.replaceChildren();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow for wrapping an existing node", () => {
|
||||||
|
const $body = $d(document.body);
|
||||||
|
$d(document.body).app($d.c("div").cls("test-class").t("text content"));
|
||||||
|
expect($body.toDom()?.innerHTML).toEqual(
|
||||||
|
'<div class="test-class">text content</div>',
|
||||||
|
);
|
||||||
|
expect(document.body?.innerHTML).toEqual(
|
||||||
|
'<div class="test-class">text content</div>',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should allow for wrapping an existing node via a querySelector for an ID", () => {
|
||||||
|
$d(document.body)
|
||||||
|
.app($d.c("div").id("item1").t("Item 1"))
|
||||||
|
.app($d.c("div").id("item2").t("Item 2"))
|
||||||
|
.app($d.c("div").id("item3").cls("item-num3").t("Item 3"));
|
||||||
|
expect($d("#item2").toDom()).toHaveTextContent("Item 2");
|
||||||
|
expect($d("#item3").toDom()).toHaveClass("item-num3");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should create an FluentDomObject-wrapped HTMLElement via .c() and .create()", () => {
|
||||||
|
const $div1 = $d.c("div");
|
||||||
|
expect($div1.toDom()).not.toBeNull();
|
||||||
|
expect($div1.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($div1.toDom()?.outerHTML).toEqual("<div></div>");
|
||||||
|
expect($div1.fluentDom).toBeDefined();
|
||||||
|
expect($div1.fluentDom).toEqual($div1.version());
|
||||||
|
|
||||||
|
const $span1 = $d.c("span");
|
||||||
|
expect($span1.toDom()).not.toBeNull();
|
||||||
|
expect($span1.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($span1.toDom()?.outerHTML).toEqual("<span></span>");
|
||||||
|
expect($span1.fluentDom).toBeDefined();
|
||||||
|
expect($span1.fluentDom).toEqual($span1.version());
|
||||||
|
|
||||||
|
const $div2 = $d.create("div");
|
||||||
|
expect($div2.toDom()).not.toBeNull();
|
||||||
|
expect($div2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($div2.toDom()?.outerHTML).toEqual("<div></div>");
|
||||||
|
expect($div2.fluentDom).toBeDefined();
|
||||||
|
expect($div2.fluentDom).toEqual($div2.version());
|
||||||
|
|
||||||
|
const $span2 = $d.create("span");
|
||||||
|
expect($span2.toDom()).not.toBeNull();
|
||||||
|
expect($span2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($span2.toDom()?.outerHTML).toEqual("<span></span>");
|
||||||
|
expect($span2.fluentDom).toBeDefined();
|
||||||
|
expect($span2.fluentDom).toEqual($span2.version());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the FluentDomObject version via .v() and .version()", () => {
|
||||||
|
const $div = $d.c("div");
|
||||||
|
expect($d.v()).toEqual($div.fluentDom);
|
||||||
|
expect($d.version()).toEqual($div.fluentDom);
|
||||||
|
});
|
||||||
|
});
|
135
src/__tests__/fluent-dom-esm.replaceChildren.test.ts
Normal file
135
src/__tests__/fluent-dom-esm.replaceChildren.test.ts
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
// @vitest-environment happy-dom
|
||||||
|
|
||||||
|
import { beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
|
describe("fluent-dom-esm tests", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body.replaceChildren();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support no arguments for `.rep()` and `.replaceChildren()`", () => {
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect($d(document.body).rep().toDom()).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(
|
||||||
|
$d(document.body).replaceChildren().toDom(),
|
||||||
|
).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support an empty array for `.rep()` and `.replaceChildren()`", () => {
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(
|
||||||
|
$d(document.body)
|
||||||
|
.rep(...[])
|
||||||
|
.toDom(),
|
||||||
|
).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(
|
||||||
|
$d(document.body)
|
||||||
|
.replaceChildren(...[])
|
||||||
|
.toDom(),
|
||||||
|
).toBeEmptyDOMElement();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support HTMLElement arguments for `.rep()` and `.replaceChildren()`", () => {
|
||||||
|
const newChild1 =
|
||||||
|
$d.c("div").id("new-child1").t("New Child 1").toDom() ?? "";
|
||||||
|
const newChild2 =
|
||||||
|
$d.c("div").id("new-child2").t("New Child 2").toDom() ?? "";
|
||||||
|
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// replace with one child
|
||||||
|
$d(document.body).rep(newChild1);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).not.toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
|
||||||
|
// replace with two children
|
||||||
|
$d(document.body).rep(newChild1, newChild2);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 2");
|
||||||
|
|
||||||
|
// replace with one child
|
||||||
|
$d(document.body).replaceChildren(newChild1);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).not.toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
|
||||||
|
// replace with two children
|
||||||
|
$d(document.body).replaceChildren(newChild1, newChild2);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body?.children.length).toEqual(2);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "new-child1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 2");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should support string arguments for `.rep()` and `.replaceChildren()`", () => {
|
||||||
|
const newChild1 = "New Child 1";
|
||||||
|
const newChild2 = "New Child 2";
|
||||||
|
|
||||||
|
// default state
|
||||||
|
const body = $d(document.body).toDom();
|
||||||
|
expect(body).not.toBeNull();
|
||||||
|
expect(body).toBeEmptyDOMElement();
|
||||||
|
|
||||||
|
// add child
|
||||||
|
$d(document.body).app($d.c("div").id("item1").t("Item 1"));
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).toHaveTextContent("Item 1");
|
||||||
|
expect(body?.children.length).toEqual(1);
|
||||||
|
expect(body?.children[0]).toHaveAttribute("id", "item1");
|
||||||
|
|
||||||
|
// replace with one child
|
||||||
|
$d(document.body).rep(newChild1);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).not.toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// replace with two children
|
||||||
|
$d(document.body).rep(newChild1, newChild2);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 2");
|
||||||
|
|
||||||
|
// replace with one child
|
||||||
|
$d(document.body).replaceChildren(newChild1);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body).not.toHaveTextContent("Item 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
|
||||||
|
// replace with two children
|
||||||
|
$d(document.body).replaceChildren(newChild1, newChild2);
|
||||||
|
expect(body).not.toBeEmptyDOMElement();
|
||||||
|
expect(body?.children.length).toEqual(0);
|
||||||
|
expect(body).toHaveTextContent("New Child 1");
|
||||||
|
expect(body).toHaveTextContent("New Child 2");
|
||||||
|
});
|
||||||
|
});
|
@@ -5,28 +5,43 @@ import { describe, expect, it } from "vitest";
|
|||||||
import $d from "../fluent-dom-esm";
|
import $d from "../fluent-dom-esm";
|
||||||
|
|
||||||
describe("fluent-dom-esm tests", () => {
|
describe("fluent-dom-esm tests", () => {
|
||||||
it("should allow for wrapping an existing node", () => {
|
it("should update an anchor's href via .h() and .href()", () => {
|
||||||
const $body = $d(document.body);
|
// create base anchor
|
||||||
$d(document.body).app($d.c("div").cls("test-class").t("text content"));
|
const $a1 = $d.c("a");
|
||||||
expect($body.toDom()?.innerHTML).toEqual(
|
expect($a1.toDom()).not.toBeNull();
|
||||||
'<div class="test-class">text content</div>',
|
expect($a1.toDom()).toBeEmptyDOMElement();
|
||||||
);
|
expect($a1.toDom()?.outerHTML).toEqual("<a></a>");
|
||||||
expect(document.body?.innerHTML).toEqual(
|
expect($a1.toDom()?.getAttribute("href")).toBeNull();
|
||||||
'<div class="test-class">text content</div>',
|
|
||||||
|
// add href attribute
|
||||||
|
$a1.h("http://example.com");
|
||||||
|
expect($a1.toDom()?.getAttribute("href")).not.toBeNull();
|
||||||
|
expect($a1.toDom()?.getAttribute("href")).toEqual("http://example.com");
|
||||||
|
|
||||||
|
// create base anchor
|
||||||
|
const $a2 = $d.c("a");
|
||||||
|
expect($a2.toDom()).not.toBeNull();
|
||||||
|
expect($a2.toDom()).toBeEmptyDOMElement();
|
||||||
|
expect($a2.toDom()?.outerHTML).toEqual("<a></a>");
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).toBeNull();
|
||||||
|
|
||||||
|
// add href attribute
|
||||||
|
$a2.href("mailto:someone@somewhere.com");
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).not.toBeNull();
|
||||||
|
expect($a2.toDom()?.getAttribute("href")).toEqual(
|
||||||
|
"mailto:someone@somewhere.com",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should allow for wrapping an existing node via a querySelector for an ID", () => {
|
it("should append text provided via `.t()` and `.text()`", () => {
|
||||||
$d(document.body)
|
|
||||||
.app($d.c("div").id("item1").t("Item 1"))
|
|
||||||
.app($d.c("div").id("item2").t("Item 2"))
|
|
||||||
.app($d.c("div").id("item3").cls("item-num3").t("Item 3"));
|
|
||||||
expect($d("#item2").toDom()).toHaveTextContent("Item 2");
|
|
||||||
expect($d("#item3").toDom()).toHaveClass("item-num3");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should append text provided via `.text()`", () => {
|
|
||||||
const testVal = "testing 123";
|
const testVal = "testing 123";
|
||||||
expect($d.c("div").t(testVal).toDom()).toHaveTextContent(testVal);
|
expect($d.c("div").t(testVal).toDom()).toHaveTextContent(testVal);
|
||||||
|
expect($d.c("div").text(testVal).toDom()).toHaveTextContent(testVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the FluentDomObject version via .v() and .version()", () => {
|
||||||
|
const $div = $d.c("div");
|
||||||
|
expect($div.v()).toEqual($div.fluentDom);
|
||||||
|
expect($div.version()).toEqual($div.fluentDom);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* fluent-dom-esm v2.2.1
|
* fluent-dom-esm v2.3.0
|
||||||
*
|
*
|
||||||
* Fluent DOM Manipulation, adapted to ESM and cranked up to v2.2(.1).
|
* Fluent DOM Manipulation, adapted to ESM and cranked up to v2.3(.0).
|
||||||
*
|
*
|
||||||
* https://git.itsericwoodward.com/eric/fluent-dom-esm
|
* https://git.itsericwoodward.com/eric/fluent-dom-esm
|
||||||
*
|
*
|
||||||
* v2.2.1 Copyright (c) 2025 Eric Woodward
|
* v2.3.0 Copyright (c) 2025 Eric Woodward
|
||||||
* Original copyright (c) 2009 Tommy Montgomery (https://glacius.tmont.com/articles/fluent-dom-manipulation-in-javascript)
|
* Original copyright (c) 2009 Tommy Montgomery (https://glacius.tmont.com/articles/fluent-dom-manipulation-in-javascript)
|
||||||
*
|
*
|
||||||
* Released under the WTFPL (Do What the Fuck You Want to Public License)
|
* Released under the WTFPL (Do What the Fuck You Want to Public License)
|
||||||
*
|
*
|
||||||
* @author Eric Woodward (v2 update)
|
* @author Eric Woodward (v2+)
|
||||||
* @author Tommy Montgomery (original)
|
* @author Tommy Montgomery (original)
|
||||||
* @license http://sam.zoy.org/wtfpl/
|
* @license http://sam.zoy.org/wtfpl/
|
||||||
*/
|
*/
|
||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
isString,
|
isString,
|
||||||
} from "./fluent-dom-esm.type-guards";
|
} from "./fluent-dom-esm.type-guards";
|
||||||
|
|
||||||
const APP_VERSION = "2.2.1";
|
const APP_VERSION = "2.3.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IIFE that creates the FluentDomObject as default export
|
* IIFE that creates the FluentDomObject as default export
|
||||||
@@ -33,7 +33,7 @@ export default (function () {
|
|||||||
/**
|
/**
|
||||||
* Wraps provided element in a FluentDomObject which is then returned
|
* Wraps provided element in a FluentDomObject which is then returned
|
||||||
*/
|
*/
|
||||||
const FluentDom = function (nodeOrQuerySelector: string | HTMLElement) {
|
const FluentDom = function (nodeOrQuerySelector: HTMLElement | string) {
|
||||||
if (typeof nodeOrQuerySelector !== "string")
|
if (typeof nodeOrQuerySelector !== "string")
|
||||||
return new (FluentDomInternal as any)(nodeOrQuerySelector);
|
return new (FluentDomInternal as any)(nodeOrQuerySelector);
|
||||||
|
|
||||||
@@ -74,13 +74,12 @@ export default (function () {
|
|||||||
* Sets the named attribute on the wrapped HTMLElement
|
* Sets the named attribute on the wrapped HTMLElement
|
||||||
*/
|
*/
|
||||||
this.a = this.attr = function (name, value) {
|
this.a = this.attr = function (name, value) {
|
||||||
if (
|
if (!root) {
|
||||||
!root ||
|
|
||||||
typeof name === "undefined" ||
|
|
||||||
typeof value === "undefined"
|
|
||||||
) {
|
|
||||||
throw new Error("Cannot set an attribute on a non-element");
|
throw new Error("Cannot set an attribute on a non-element");
|
||||||
}
|
}
|
||||||
|
if (typeof name === "undefined") {
|
||||||
|
throw new Error("Cannot set an attribute without a name");
|
||||||
|
}
|
||||||
|
|
||||||
root.setAttribute(name, value);
|
root.setAttribute(name, value);
|
||||||
return this;
|
return this;
|
||||||
@@ -89,30 +88,36 @@ export default (function () {
|
|||||||
/**
|
/**
|
||||||
* Appends value to wrapped HTMLElement
|
* Appends value to wrapped HTMLElement
|
||||||
*/
|
*/
|
||||||
this.app = this.append = function (value) {
|
this.app = this.append = function (...content) {
|
||||||
if (!root || !root?.appendChild) {
|
if (!root || !root?.appendChild) {
|
||||||
throw new Error("Cannot append to a non-element");
|
throw new Error("Cannot append to a non-element");
|
||||||
}
|
}
|
||||||
|
|
||||||
const type = typeof value;
|
if (!content || content.length < 1) {
|
||||||
if (type === "object") {
|
throw new Error("Cannot append without a value");
|
||||||
if (isFluentDomObject(value)) {
|
}
|
||||||
const domVal = value.toDom();
|
|
||||||
if (domVal !== null) root.appendChild(domVal);
|
content.forEach((value) => {
|
||||||
} else if (isHTMLElement(value)) {
|
const type = typeof value;
|
||||||
root.appendChild(value);
|
if (type === "object") {
|
||||||
|
if (isFluentDomObject(value)) {
|
||||||
|
const domVal = value.toDom();
|
||||||
|
if (domVal !== null) root?.appendChild(domVal);
|
||||||
|
} else if (isHTMLElement(value)) {
|
||||||
|
root?.appendChild(value);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"Invalid argument: not an HTMLElement or FluentDom object",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (isNumber(value) || isString(value)) {
|
||||||
|
root?.appendChild(document.createTextNode(`${value}`));
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Invalid argument: not an HTMLElement or FluentDom object",
|
`Invalid argument: not a valid type (${typeof value})`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (isNumber(value) || isString(value)) {
|
});
|
||||||
root.appendChild(document.createTextNode(`${value}`));
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
`Invalid argument: not a valid type (${typeof value})`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@@ -150,11 +155,9 @@ export default (function () {
|
|||||||
/**
|
/**
|
||||||
* Sets the wrapped HTMLElement's "innerHTML" property
|
* Sets the wrapped HTMLElement's "innerHTML" property
|
||||||
*/
|
*/
|
||||||
this.html = function (content: string) {
|
this.html = function (content) {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
throw new Error(
|
throw new Error("Cannot set innerHTML for a non-element");
|
||||||
"Cannot get or set innerHTML for a non-element",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.innerHTML = content;
|
root.innerHTML = content;
|
||||||
@@ -180,11 +183,43 @@ export default (function () {
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.q = this.querySelector = function (selector: string) {
|
/**
|
||||||
|
* Sets wrapped HTMLElement to matching querySelector
|
||||||
|
*/
|
||||||
|
this.q = this.querySelector = function (selector) {
|
||||||
root = document.querySelector(selector);
|
root = document.querySelector(selector);
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the children of the wrapped HTMLElement
|
||||||
|
*/
|
||||||
|
this.rep = this.replaceChildren = function (...content) {
|
||||||
|
if (!root) {
|
||||||
|
throw new Error("Cannot replaceChildren on a non-element");
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to using `this.html()` and `this.append()`
|
||||||
|
if (!root.replaceChildren) {
|
||||||
|
if (!content) return this.html("");
|
||||||
|
|
||||||
|
return this.html("").append(...content);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content.length && content[0] && isFluentDomObject(content[0])) {
|
||||||
|
const domValues = content.map((val) =>
|
||||||
|
(val as FluentDomObject).toDom(),
|
||||||
|
);
|
||||||
|
|
||||||
|
root.replaceChildren(
|
||||||
|
...domValues.filter((val) => val !== null),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
root.replaceChildren(...(content as (HTMLElement | string)[]));
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets one or more style attributes on the wrapped HTMLElement
|
* Sets one or more style attributes on the wrapped HTMLElement
|
||||||
*/
|
*/
|
||||||
@@ -272,7 +307,7 @@ export default (function () {
|
|||||||
* Returns library version
|
* Returns library version
|
||||||
*/
|
*/
|
||||||
this.v = this.version = function () {
|
this.v = this.version = function () {
|
||||||
return APP_VERSION;
|
return this.fluentDom;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,10 +1,14 @@
|
|||||||
export interface FluentDomObject {
|
export interface FluentDomObject {
|
||||||
(nodeOrQuerySelector: string | HTMLElement): FluentDomObject;
|
(nodeOrQuerySelector: HTMLElement | string): FluentDomObject;
|
||||||
fluentDom: string;
|
fluentDom: string;
|
||||||
|
|
||||||
a: (name: string, value: string) => FluentDomObject;
|
a: (name: string, value: string) => FluentDomObject;
|
||||||
app: (obj: FluentDomObject | HTMLElement | string) => FluentDomObject;
|
app: (
|
||||||
append: (obj: FluentDomObject | HTMLElement | string) => FluentDomObject;
|
...content: (FluentDomObject | HTMLElement | string)[]
|
||||||
|
) => FluentDomObject;
|
||||||
|
append: (
|
||||||
|
...content: (FluentDomObject | HTMLElement | string)[]
|
||||||
|
) => FluentDomObject;
|
||||||
attr: (name: string, value: string) => FluentDomObject;
|
attr: (name: string, value: string) => FluentDomObject;
|
||||||
|
|
||||||
c: (tagName: string) => FluentDomObject;
|
c: (tagName: string) => FluentDomObject;
|
||||||
@@ -34,6 +38,13 @@ export interface FluentDomObject {
|
|||||||
q: (selector: string) => FluentDomObject;
|
q: (selector: string) => FluentDomObject;
|
||||||
querySelector: (selector: string) => FluentDomObject;
|
querySelector: (selector: string) => FluentDomObject;
|
||||||
|
|
||||||
|
rep: (
|
||||||
|
...content: (FluentDomObject | HTMLElement | string)[]
|
||||||
|
) => FluentDomObject;
|
||||||
|
replaceChildren: (
|
||||||
|
...content: (FluentDomObject | HTMLElement | string)[]
|
||||||
|
) => FluentDomObject;
|
||||||
|
|
||||||
s:
|
s:
|
||||||
| ((prop: CSSStyleDeclaration) => FluentDomObject)
|
| ((prop: CSSStyleDeclaration) => FluentDomObject)
|
||||||
| ((prop: string, value: string) => FluentDomObject);
|
| ((prop: string, value: string) => FluentDomObject);
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2022",
|
"target": "es6",
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "es6",
|
||||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
"lib": ["es6", "DOM", "DOM.Iterable"],
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
||||||
/* Bundler mode */
|
/* Bundler mode */
|
||||||
|
@@ -6,14 +6,18 @@ import { defineConfig } from 'vite';
|
|||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [dts({exclude: ["./setupTests.ts", "**/*.test.ts"]})],
|
plugins: [dts({exclude: ["./vitest.setup.ts", "**/*.test.ts"]})],
|
||||||
build: {
|
build: {
|
||||||
lib: {
|
lib: {
|
||||||
entry: resolve(__dirname, 'src/fluent-dom-esm.ts'),
|
entry: resolve(__dirname, 'src/fluent-dom-esm.ts'),
|
||||||
name: 'fluent-dom-esm',
|
name: 'fluent-dom-esm',
|
||||||
fileName: 'fluent-dom-esm',
|
fileName: 'fluent-dom-esm',
|
||||||
formats: ['es']
|
formats: ['es'],
|
||||||
|
outDir: './dist'
|
||||||
},
|
},
|
||||||
minify: false
|
minify: false
|
||||||
}
|
},
|
||||||
|
test: {
|
||||||
|
setupFiles: ["./vitest.setup.ts"]
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@@ -1,7 +0,0 @@
|
|||||||
import { defineConfig } from 'vite';
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
test: {
|
|
||||||
setupFiles: ["./setupTests.ts"],
|
|
||||||
},
|
|
||||||
})
|
|
@@ -809,14 +809,14 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1":
|
"debug@npm:4, debug@npm:^4.3.4, debug@npm:^4.4.0, debug@npm:^4.4.1":
|
||||||
version: 4.4.1
|
version: 4.4.3
|
||||||
resolution: "debug@npm:4.4.1"
|
resolution: "debug@npm:4.4.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: "npm:^2.1.3"
|
ms: "npm:^2.1.3"
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
supports-color:
|
supports-color:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55
|
checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user