@tir.jp/hob 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ zlib License
2
+
3
+ (C) 2026 ayamada
4
+
5
+ This software is provided 'as-is', without any express or implied
6
+ warranty. In no event will the authors be held liable for any damages
7
+ arising from the use of this software.
8
+
9
+ Permission is granted to anyone to use this software for any purpose,
10
+ including commercial applications, and to alter it and redistribute it
11
+ freely, subject to the following restrictions:
12
+
13
+ 1. The origin of this software must not be misrepresented; you must not
14
+ claim that you wrote the original software. If you use this software
15
+ in a product, an acknowledgment in the product documentation would be
16
+ appreciated but is not required.
17
+ 2. Altered source versions must be plainly marked as such, and must not be
18
+ misrepresented as being the original software.
19
+ 3. This notice may not be removed or altered from any source distribution.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # @tir.jp/hob (HTML Object Builder)
2
+
3
+ A minimal, property-centric DOM builder inspired by Clojure's Hiccup.
4
+
5
+ ## Features
6
+
7
+ - **Lightweight:** Tiny footprint (less than 1KB).
8
+ - **Property-centric:** Directly sets DOM properties (like `onclick`, `style.width`) instead of attributes.
9
+ - **Hiccup-like syntax:** Uses standard JavaScript arrays to define DOM structures.
10
+ - **Smart Attributes:** Automatically maps `class` to `className`, supports `style` strings, and correctly handles `data-*` and `aria-*` attributes.
11
+ - **Functional Components:** Supports React-like functional components for easy UI reuse.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @tir.jp/hob
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Basic Usage
22
+ ```javascript
23
+ import * as Hob from '@tir.jp/hob';
24
+
25
+ const myUI = Hob.build([
26
+ "DIV", { class: "container", style: "padding: 10px;" },
27
+ ["H1", "Hello World"],
28
+ ["BUTTON", { onclick: () => alert('Clicked!') }, "Click me"]
29
+ ]);
30
+
31
+ document.body.appendChild(myUI);
32
+ ```
33
+
34
+ ### Functional Components
35
+ You can pass a function instead of a tag name to create reusable components.
36
+
37
+ ```javascript
38
+ import * as Hob from '@tir.jp/hob';
39
+
40
+ // Define a component
41
+ const Card = (attrs, title, content) => [
42
+ "DIV", { class: "card", ...attrs },
43
+ ["H2", title],
44
+ ["P", content]
45
+ ];
46
+
47
+ // Use the component
48
+ const app = Hob.build([
49
+ "DIV",
50
+ [Card, { id: "card-1" }, "Title 1", "This is the first card."],
51
+ [Card, { style: { color: "blue" } }, "Title 2", "This is the second card."]
52
+ ]);
53
+
54
+ document.body.appendChild(app);
55
+ ```
56
+
57
+ ## API
58
+
59
+ ### `build(treeArray)`
60
+ Takes a Hiccup-style array and returns an `HTMLElement`.
61
+
62
+ - `treeArray[0]`: Tag name (e.g., `"DIV"`) or a Function.
63
+ - `treeArray[1]` (optional): Attribute/Property object.
64
+ - `...treeArray[2:]`: Children (strings, numbers, arrays, or existing `HTMLElement`s).
65
+
66
+ ### `setAttr(htmlObj, attrObj)`
67
+ Recursively assigns properties from `attrObj` to `htmlObj`.
68
+
69
+ ## License
70
+
71
+ Zlib
package/index.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ // Tag can be a string (HTML tag) or a functional component
2
+ export type HiccupTag = string | ((attrs: Record<string, any>, ...children: any[]) => HiccupTree);
3
+
4
+ export type HiccupTree =
5
+ | [HiccupTag, Record<string, any>?, ...(HiccupTree | HTMLElement | string | number | null | undefined)[]]
6
+ | string | number | HTMLElement | null | undefined;
7
+
8
+ /**
9
+ * Recursively sets attributes/properties on an HTMLElement.
10
+ */
11
+ export function setAttr(htmlObj: any, attrObj: Record<string, any>): void;
12
+
13
+ /**
14
+ * Builds an HTMLElement tree from a nested array (Hiccup format).
15
+ */
16
+ export function build(treeArray: HiccupTree): HTMLElement;
package/index.mjs ADDED
@@ -0,0 +1,71 @@
1
+ // html-object-builder (HOB)
2
+ // A minimal, property-centric DOM builder inspired by Clojure's Hiccup.
3
+
4
+ /**
5
+ * Recursively sets attributes/properties on an HTMLElement.
6
+ * Unlike standard setAttribute, this assigns directly to the object properties,
7
+ * with some quality-of-life mappings for common DOM quirks.
8
+ *
9
+ * @param {HTMLElement} htmlObj The target DOM element.
10
+ * @param {Object} attrObj The object containing attributes/properties to set.
11
+ */
12
+ export const setAttr = (htmlObj, attrObj) => {
13
+ Object.entries(attrObj).forEach(([k, v]) => {
14
+ // QoL: Map 'class' to 'className' for direct property access
15
+ if (k === 'class') k = 'className';
16
+
17
+ if (k === 'style' && typeof v === 'string') {
18
+ // QoL: Support string assignment to style (e.g., style: "color: red;")
19
+ htmlObj.style.cssText = v;
20
+ } else if (k.includes('-')) {
21
+ // QoL: Support data-* and aria-* attributes which must use setAttribute
22
+ htmlObj.setAttribute(k, v);
23
+ } else if (v?.constructor === Object) {
24
+ setAttr(htmlObj[k], v);
25
+ } else {
26
+ htmlObj[k] = v;
27
+ }
28
+ });
29
+ };
30
+
31
+ /**
32
+ * Builds an HTMLElement tree from a nested array (Hiccup format).
33
+ * Supports functional components for UI composition.
34
+ *
35
+ * @param {Array} treeArray [tag|Function, attrs?, ...children]
36
+ * @returns {HTMLElement}
37
+ */
38
+ export const build = (treeArray) => {
39
+ if (!Array.isArray(treeArray)) {
40
+ throw new Error('HOB: build(treeArray) requires an array.');
41
+ }
42
+
43
+ const tag = treeArray[0];
44
+
45
+ // Functional Component Support
46
+ if (typeof tag === 'function') {
47
+ const hasAttrs = treeArray[1]?.constructor === Object;
48
+ const attrs = hasAttrs ? treeArray[1] : {};
49
+ const children = treeArray.slice(hasAttrs ? 2 : 1);
50
+ // Recursively build the result of the functional component
51
+ return build(tag(attrs, ...children));
52
+ }
53
+
54
+ const htmlObj = document.createElement(tag);
55
+
56
+ for (let i = 1; i < treeArray.length; i++) {
57
+ const one = treeArray[i];
58
+ if (one == null) {
59
+ continue; // Skip null/undefined
60
+ } else if (one?.constructor === Object) {
61
+ setAttr(htmlObj, one);
62
+ } else if (Array.isArray(one)) {
63
+ htmlObj.appendChild(build(one));
64
+ } else if (one instanceof HTMLElement) {
65
+ htmlObj.appendChild(one);
66
+ } else {
67
+ htmlObj.appendChild(document.createTextNode((one ?? '').toString()));
68
+ }
69
+ }
70
+ return htmlObj;
71
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@tir.jp/hob",
3
+ "version": "1.0.0",
4
+ "description": "A minimal, property-centric DOM builder inspired by Clojure's Hiccup.",
5
+ "type": "module",
6
+ "main": "index.mjs",
7
+ "module": "index.mjs",
8
+ "types": "index.d.ts",
9
+ "exports": {
10
+ ".": "./index.mjs"
11
+ },
12
+ "scripts": {
13
+ "test": "echo \"Error: no test specified\" && exit 1"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/ayamada/hob.git"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/ayamada/hob/issues"
21
+ },
22
+ "homepage": "https://github.com/ayamada/hob#readme",
23
+ "keywords": [
24
+ "hiccup",
25
+ "dom",
26
+ "minimal",
27
+ "property-centric"
28
+ ],
29
+ "author": "ayamada",
30
+ "contributors": [
31
+ "mac"
32
+ ],
33
+ "license": "Zlib",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }