@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 +19 -0
- package/README.md +71 -0
- package/index.d.ts +16 -0
- package/index.mjs +71 -0
- package/package.json +37 -0
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
|
+
}
|