ajo 0.1.26 → 0.1.28
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/dist/html.cjs +1 -1
- package/dist/html.js +47 -48
- package/dist/index.cjs +1 -1
- package/dist/index.js +73 -76
- package/package.json +5 -5
- package/readme.md +83 -93
- package/types.ts +4 -3
package/dist/html.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./context.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("./context.cjs"),g=new Set(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),m=Symbol.for("ajo.args"),y=e=>e.replace(/[&<>"']/g,r=>`&#${r.charCodeAt(0)};`),o=()=>{},b=e=>[...f(e)].join(""),f=function*(e,{alloc:r=o,push:t=o,placeholder:n=o}={}){for(e of d(e,{alloc:r,push:t,placeholder:n}))typeof e=="string"?yield y(e):yield*$(e,{alloc:r,push:t,placeholder:n})},$=function*({nodeName:e,children:r,...t},n){let l="";for(const i in t)i.startsWith("set:")||t[i]==null||t[i]===!1||(t[i]===!0?l+=` ${i}`:l+=` ${i}="${y(String(t[i]))}"`);g.has(e)?yield`<${e}${l}>`:(yield`<${e}${l}>`,r!=null&&(yield*f(r,n)),yield`</${e}>`)},d=function*(e,r){if(e==null)return;const t=typeof e;if(t!="boolean")if(t=="string")yield e;else if(t=="number"||t=="bigint")yield String(e);else if(Symbol.iterator in e)for(e of e)yield*d(e,r);else"nodeName"in e?typeof e.nodeName=="function"?yield*v(e,r):yield u(e,r):yield String(e)},v=function*({nodeName:e,fallback:r=e.fallback,...t},n){const l=e.constructor.name;e.src?yield w(e.src,t,n):l=="GeneratorFunction"?yield S(e,t,n):l=="AsyncGeneratorFunction"?yield x(e,r,t,n):(t=e(t),typeof t?.then=="function"?yield A(r,t,n):yield*d(t,n))},w=(e,r,t)=>{const n=t.alloc();return t.push({id:n,src:e,h:u(r,t),done:!0}),t.placeholder(n)},S=(e,r,t)=>{const n={...e.attrs},l={...e.args};for(const c in r)c.startsWith("attr:")?n[c.slice(5)]=r[c]:c=="key"||c=="skip"||c=="memo"||c=="ref"||c.startsWith("set:")?n[c]=r[c]:l[c]=r[c];const i={[a.Context]:Object.create(a.current()?.[a.Context]??null),[m]:l,next:o,return:o,throw:c=>{throw c}},s=e.call(i,l),p=a.current();a.current(i);try{const c=[...d(s.next().value,t)];return{...n,nodeName:e.is??"div",children:c.length==1?c[0]:c}}finally{s.return?.(),a.current(p)}},x=(e,r,t,n)=>{const l=n.alloc();return Promise.resolve().then(async()=>{const i=e(t);n={...n,alloc:(s=l)=>n.alloc(s)};try{for(t=await i.next();!t.done;)n.push({id:l,h:u(t.value,n),done:!1}),t=await i.next();n.push({id:l,h:u(t.value,n),done:!0})}catch(s){n.push({id:l,h:u(s,n),done:!0})}finally{i.return?.()}}),n.placeholder(l,r)},A=(e,r,t)=>{const n=t.alloc();return r.then(l=>t.push({id:n,h:u(l,{...t,alloc:(i=n)=>t.alloc(i)}),done:!0})),t.placeholder(n,e)},u=({key:e,skip:r,memo:t,ref:n,...l},i)=>{if("children"in l){const s=[...d(l.children,i)];s.length?l.children=s.length==1?s[0]:s:delete l.children}return l};exports.html=f;exports.render=b;
|
package/dist/html.js
CHANGED
|
@@ -1,74 +1,73 @@
|
|
|
1
|
-
import { Context as
|
|
2
|
-
const
|
|
3
|
-
},
|
|
4
|
-
for (e of
|
|
5
|
-
typeof e == "string" ? yield
|
|
6
|
-
}, $ = function* (e, r) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}, u = function* (e, r) {
|
|
1
|
+
import { Context as y, current as f } from "./context.js";
|
|
2
|
+
const m = /* @__PURE__ */ new Set(["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]), b = Symbol.for("ajo.args"), d = (e) => e.replace(/[&<>"']/g, (r) => `&#${r.charCodeAt(0)};`), u = () => {
|
|
3
|
+
}, j = (e) => [...p(e)].join(""), p = function* (e, { alloc: r = u, push: t = u, placeholder: n = u } = {}) {
|
|
4
|
+
for (e of o(e, { alloc: r, push: t, placeholder: n }))
|
|
5
|
+
typeof e == "string" ? yield d(e) : yield* $(e, { alloc: r, push: t, placeholder: n });
|
|
6
|
+
}, $ = function* ({ nodeName: e, children: r, ...t }, n) {
|
|
7
|
+
let l = "";
|
|
8
|
+
for (const i in t)
|
|
9
|
+
i.startsWith("set:") || t[i] == null || t[i] === !1 || (t[i] === !0 ? l += ` ${i}` : l += ` ${i}="${d(String(t[i]))}"`);
|
|
10
|
+
m.has(e) ? yield `<${e}${l}>` : (yield `<${e}${l}>`, r != null && (yield* p(r, n)), yield `</${e}>`);
|
|
11
|
+
}, o = function* (e, r) {
|
|
13
12
|
if (e == null) return;
|
|
14
13
|
const t = typeof e;
|
|
15
14
|
if (t != "boolean")
|
|
16
15
|
if (t == "string") yield e;
|
|
17
16
|
else if (t == "number" || t == "bigint") yield String(e);
|
|
18
|
-
else if (Symbol.iterator in e) for (e of e) yield*
|
|
19
|
-
else "nodeName" in e ? typeof e.nodeName == "function" ? yield*
|
|
20
|
-
},
|
|
21
|
-
const
|
|
22
|
-
e.src ? yield
|
|
23
|
-
},
|
|
17
|
+
else if (Symbol.iterator in e) for (e of e) yield* o(e, r);
|
|
18
|
+
else "nodeName" in e ? typeof e.nodeName == "function" ? yield* w(e, r) : yield a(e, r) : yield String(e);
|
|
19
|
+
}, w = function* ({ nodeName: e, fallback: r = e.fallback, ...t }, n) {
|
|
20
|
+
const l = e.constructor.name;
|
|
21
|
+
e.src ? yield v(e.src, t, n) : l == "GeneratorFunction" ? yield x(e, t, n) : l == "AsyncGeneratorFunction" ? yield S(e, r, t, n) : (t = e(t), typeof t?.then == "function" ? yield A(r, t, n) : yield* o(t, n));
|
|
22
|
+
}, v = (e, r, t) => {
|
|
24
23
|
const n = t.alloc();
|
|
25
24
|
return t.push({ id: n, src: e, h: a(r, t), done: !0 }), t.placeholder(n);
|
|
26
|
-
},
|
|
27
|
-
const n = { ...e.attrs },
|
|
25
|
+
}, x = (e, r, t) => {
|
|
26
|
+
const n = { ...e.attrs }, l = { ...e.args };
|
|
28
27
|
for (const c in r)
|
|
29
|
-
c.startsWith("attr:") ? n[c.slice(5)] = r[c] :
|
|
30
|
-
const
|
|
31
|
-
[
|
|
32
|
-
[
|
|
33
|
-
next:
|
|
34
|
-
return:
|
|
28
|
+
c.startsWith("attr:") ? n[c.slice(5)] = r[c] : c == "key" || c == "skip" || c == "memo" || c == "ref" || c.startsWith("set:") ? n[c] = r[c] : l[c] = r[c];
|
|
29
|
+
const i = {
|
|
30
|
+
[y]: Object.create(f()?.[y] ?? null),
|
|
31
|
+
[b]: l,
|
|
32
|
+
next: u,
|
|
33
|
+
return: u,
|
|
35
34
|
throw: (c) => {
|
|
36
35
|
throw c;
|
|
37
36
|
}
|
|
38
|
-
}, s = e.call(
|
|
39
|
-
|
|
37
|
+
}, s = e.call(i, l), g = f();
|
|
38
|
+
f(i);
|
|
40
39
|
try {
|
|
41
|
-
const c = [...
|
|
40
|
+
const c = [...o(s.next().value, t)];
|
|
42
41
|
return { ...n, nodeName: e.is ?? "div", children: c.length == 1 ? c[0] : c };
|
|
43
42
|
} finally {
|
|
44
|
-
s.return?.(),
|
|
43
|
+
s.return?.(), f(g);
|
|
45
44
|
}
|
|
46
|
-
},
|
|
47
|
-
const
|
|
45
|
+
}, S = (e, r, t, n) => {
|
|
46
|
+
const l = n.alloc();
|
|
48
47
|
return Promise.resolve().then(async () => {
|
|
49
|
-
const
|
|
50
|
-
n = { ...n, alloc: (s =
|
|
48
|
+
const i = e(t);
|
|
49
|
+
n = { ...n, alloc: (s = l) => n.alloc(s) };
|
|
51
50
|
try {
|
|
52
|
-
for (t = await
|
|
53
|
-
n.push({ id:
|
|
54
|
-
n.push({ id:
|
|
51
|
+
for (t = await i.next(); !t.done; )
|
|
52
|
+
n.push({ id: l, h: a(t.value, n), done: !1 }), t = await i.next();
|
|
53
|
+
n.push({ id: l, h: a(t.value, n), done: !0 });
|
|
55
54
|
} catch (s) {
|
|
56
|
-
n.push({ id:
|
|
55
|
+
n.push({ id: l, h: a(s, n), done: !0 });
|
|
57
56
|
} finally {
|
|
58
|
-
|
|
57
|
+
i.return?.();
|
|
59
58
|
}
|
|
60
|
-
}), n.placeholder(
|
|
61
|
-
},
|
|
59
|
+
}), n.placeholder(l, r);
|
|
60
|
+
}, A = (e, r, t) => {
|
|
62
61
|
const n = t.alloc();
|
|
63
|
-
return r.then((
|
|
64
|
-
}, a = ({ key: e, skip: r, memo: t, ref: n, ...
|
|
65
|
-
if ("children" in
|
|
66
|
-
const s = [...
|
|
67
|
-
s.length ?
|
|
62
|
+
return r.then((l) => t.push({ id: n, h: a(l, { ...t, alloc: (i = n) => t.alloc(i) }), done: !0 })), t.placeholder(n, e);
|
|
63
|
+
}, a = ({ key: e, skip: r, memo: t, ref: n, ...l }, i) => {
|
|
64
|
+
if ("children" in l) {
|
|
65
|
+
const s = [...o(l.children, i)];
|
|
66
|
+
s.length ? l.children = s.length == 1 ? s[0] : s : delete l.children;
|
|
68
67
|
}
|
|
69
|
-
return
|
|
68
|
+
return l;
|
|
70
69
|
};
|
|
71
70
|
export {
|
|
72
71
|
p as html,
|
|
73
|
-
|
|
72
|
+
j as render
|
|
74
73
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./context.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./context.cjs"),y=Symbol.for("ajo.key"),j=Symbol.for("ajo.memo"),g=Symbol.for("ajo.ref"),p=Symbol.for("ajo.cache"),c=Symbol.for("ajo.generator"),a=Symbol.for("ajo.iterator"),b=Symbol.for("ajo.render"),f=Symbol.for("ajo.args"),N=t=>t.children,k=(t,e,...r)=>((e??={}).nodeName=t,!("children"in e)&&r.length&&(e.children=r.length==1?r[0]:r),e),l=(t,e,r=e.firstChild,i=null)=>{for(t of S(t)){const n=T(t,e,r);r==null?m(e,n,i):n==r?r=n.nextSibling:n==r.nextSibling?(m(e,r,i),r=n.nextSibling):m(e,n,r)}for(;r!=i;){const n=r.nextSibling;r.nodeType==1&&A(r),e.removeChild(r),r=n}},S=function*(t){if(t==null)return;const e=typeof t;if(e!="boolean")if(e=="string")yield t;else if(e=="number"||e=="bigint")yield String(t);else if(Symbol.iterator in t)for(t of t)yield*S(t);else"nodeName"in t?typeof t.nodeName=="function"?yield*E(t):yield t:yield String(t)},E=function*({nodeName:t,...e}){t.constructor.name=="GeneratorFunction"?yield O(t,e):yield*S(t(e))},O=function(t,e){const r={...t.attrs},i={...t.args};for(const n in e)n.startsWith("attr:")?r[n.slice(5)]=e[n]:n=="key"||n=="skip"||n=="memo"||n=="ref"||n.startsWith("set:")?r[n]=e[n]:i[n]=e[n];return{...r,nodeName:t.is??"div",[c]:t,[f]:i}},T=(t,e,r)=>typeof t=="string"?F(t,r):G(t,e,r),F=(t,e)=>{for(;e&&e.nodeType!=3;)e=e.nextSibling;return e?e.data!=t&&(e.data=t):e=document.createTextNode(t),e},G=({nodeName:t,children:e,key:r,skip:i,memo:n,ref:x,[c]:u,[f]:v,...w},C,s)=>{for(;s&&(s.localName!=t||s[y]!=null&&s[y]!=r||s[c]&&s[c]!=u);)s=s.nextSibling;return s??=document.createElementNS(w.xmlns??C.namespaceURI,t),r!=null&&(s[y]=r),(n==null||W(s[j],s[j]=n))&&(R(s[p]??B(s),s[p]=w,s),i||(u?I(u,v,s):l(e,s)),typeof x=="function"&&(s[g]=x)(s)),s},R=(t,e,r)=>{for(const i in{...t,...e})t[i]!==e[i]&&(i.startsWith("set:")?r[i.slice(4)]=e[i]:e[i]==null||e[i]===!1?r.removeAttribute(i):r.setAttribute(i,e[i]===!0?"":e[i]))},W=(t,e)=>Array.isArray(t)&&Array.isArray(e)?t.some((r,i)=>r!==e[i]):t!==e,B=t=>Array.from(t.attributes).reduce((e,r)=>(e[r.name]=r.value,e),{}),m=(t,e,r)=>{if(e.contains(document.activeElement)){const i=e.nextSibling;for(;r&&r!=e;){const n=r.nextSibling;t.insertBefore(r,i),r=n}}else t.insertBefore(e,r)},A=t=>{for(const e of t.children)A(e);typeof t.return=="function"&&t.return(),t[g]?.(null)},I=(t,e,r)=>{r[c]??=(M(r),t),Object.assign(r[f]??={},e),r[b]()},M=t=>{Object.assign(t,h),t[o.Context]=Object.create(o.current()?.[o.Context]??null)},h={[b](){const t=o.current();o.current(this);try{const{value:e,done:r}=(this[a]??=this[c].call(this,this[f])).next();l(e,this),this[g]?.(this),r&&this.return()}catch(e){this.throw(e)}finally{o.current(t)}},next(t){if(typeof t=="function")try{t.call(this,this[f])}catch(e){this.throw(e)}o.current()?.contains(this)||this[b]()},throw(t){for(let e=this;e;e=e.parentNode)if(typeof e[a]?.throw=="function")try{return l(e[a].throw(t).value,e)}catch(r){t=new Error(r instanceof Error?r.message:r,{cause:t})}throw t},return(){try{this[a]?.return()}catch(t){this.throw(t)}finally{this[a]=null}}};exports.Fragment=N;exports.h=k;exports.render=l;
|
package/dist/index.js
CHANGED
|
@@ -1,96 +1,93 @@
|
|
|
1
|
-
import { Context as
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
r == null ? t.appendChild(i) : i == r ? r = i.nextSibling : i == r.nextSibling ? (t.appendChild(r), r = i.nextSibling) : T(t, i, r);
|
|
1
|
+
import { Context as j, current as f } from "./context.js";
|
|
2
|
+
const u = Symbol.for("ajo.key"), p = Symbol.for("ajo.memo"), g = Symbol.for("ajo.ref"), A = Symbol.for("ajo.cache"), o = Symbol.for("ajo.generator"), a = Symbol.for("ajo.iterator"), m = Symbol.for("ajo.render"), c = Symbol.for("ajo.args"), U = (t) => t.children, h = (t, r, ...e) => ((r ??= {}).nodeName = t, !("children" in r) && e.length && (r.children = e.length == 1 ? e[0] : e), r), b = (t, r, e = r.firstChild, i = null) => {
|
|
3
|
+
for (t of S(t)) {
|
|
4
|
+
const n = G(t, r, e);
|
|
5
|
+
e == null ? y(r, n, i) : n == e ? e = n.nextSibling : n == e.nextSibling ? (y(r, e, i), e = n.nextSibling) : y(r, n, e);
|
|
7
6
|
}
|
|
8
|
-
for (;
|
|
9
|
-
const
|
|
10
|
-
|
|
7
|
+
for (; e != i; ) {
|
|
8
|
+
const n = e.nextSibling;
|
|
9
|
+
e.nodeType == 1 && v(e), r.removeChild(e), e = n;
|
|
11
10
|
}
|
|
12
|
-
}, S = function* (
|
|
13
|
-
if (
|
|
14
|
-
const
|
|
15
|
-
if (
|
|
16
|
-
if (
|
|
17
|
-
else if (
|
|
18
|
-
else if (Symbol.iterator in
|
|
19
|
-
else "nodeName" in
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
},
|
|
23
|
-
const
|
|
24
|
-
for (const n in
|
|
25
|
-
n.startsWith("attr:") ?
|
|
26
|
-
return { ...
|
|
27
|
-
},
|
|
28
|
-
for (;
|
|
29
|
-
return
|
|
30
|
-
},
|
|
31
|
-
for (
|
|
32
|
-
return s ??= document.createElementNS(
|
|
33
|
-
},
|
|
34
|
-
for (const i in { ...
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
if (
|
|
38
|
-
const i =
|
|
39
|
-
for (;
|
|
40
|
-
const n =
|
|
41
|
-
|
|
11
|
+
}, S = function* (t) {
|
|
12
|
+
if (t == null) return;
|
|
13
|
+
const r = typeof t;
|
|
14
|
+
if (r != "boolean")
|
|
15
|
+
if (r == "string") yield t;
|
|
16
|
+
else if (r == "number" || r == "bigint") yield String(t);
|
|
17
|
+
else if (Symbol.iterator in t) for (t of t) yield* S(t);
|
|
18
|
+
else "nodeName" in t ? typeof t.nodeName == "function" ? yield* C(t) : yield t : yield String(t);
|
|
19
|
+
}, C = function* ({ nodeName: t, ...r }) {
|
|
20
|
+
t.constructor.name == "GeneratorFunction" ? yield E(t, r) : yield* S(t(r));
|
|
21
|
+
}, E = function(t, r) {
|
|
22
|
+
const e = { ...t.attrs }, i = { ...t.args };
|
|
23
|
+
for (const n in r)
|
|
24
|
+
n.startsWith("attr:") ? e[n.slice(5)] = r[n] : n == "key" || n == "skip" || n == "memo" || n == "ref" || n.startsWith("set:") ? e[n] = r[n] : i[n] = r[n];
|
|
25
|
+
return { ...e, nodeName: t.is ?? "div", [o]: t, [c]: i };
|
|
26
|
+
}, G = (t, r, e) => typeof t == "string" ? O(t, e) : R(t, r, e), O = (t, r) => {
|
|
27
|
+
for (; r && r.nodeType != 3; ) r = r.nextSibling;
|
|
28
|
+
return r ? r.data != t && (r.data = t) : r = document.createTextNode(t), r;
|
|
29
|
+
}, R = ({ nodeName: t, children: r, key: e, skip: i, memo: n, ref: x, [o]: l, [c]: N, ...w }, k, s) => {
|
|
30
|
+
for (; s && (s.localName != t || s[u] != null && s[u] != e || s[o] && s[o] != l); ) s = s.nextSibling;
|
|
31
|
+
return s ??= document.createElementNS(w.xmlns ?? k.namespaceURI, t), e != null && (s[u] = e), (n == null || W(s[p], s[p] = n)) && (T(s[A] ?? B(s), s[A] = w, s), i || (l ? F(l, N, s) : b(r, s)), typeof x == "function" && (s[g] = x)(s)), s;
|
|
32
|
+
}, T = (t, r, e) => {
|
|
33
|
+
for (const i in { ...t, ...r })
|
|
34
|
+
t[i] !== r[i] && (i.startsWith("set:") ? e[i.slice(4)] = r[i] : r[i] == null || r[i] === !1 ? e.removeAttribute(i) : e.setAttribute(i, r[i] === !0 ? "" : r[i]));
|
|
35
|
+
}, W = (t, r) => Array.isArray(t) && Array.isArray(r) ? t.some((e, i) => e !== r[i]) : t !== r, B = (t) => Array.from(t.attributes).reduce((r, e) => (r[e.name] = e.value, r), {}), y = (t, r, e) => {
|
|
36
|
+
if (r.contains(document.activeElement)) {
|
|
37
|
+
const i = r.nextSibling;
|
|
38
|
+
for (; e && e != r; ) {
|
|
39
|
+
const n = e.nextSibling;
|
|
40
|
+
t.insertBefore(e, i), e = n;
|
|
42
41
|
}
|
|
43
|
-
} else
|
|
44
|
-
},
|
|
45
|
-
for (const r of t.children)
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
Object.assign(
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const e = c();
|
|
56
|
-
c(this);
|
|
42
|
+
} else t.insertBefore(r, e);
|
|
43
|
+
}, v = (t) => {
|
|
44
|
+
for (const r of t.children) v(r);
|
|
45
|
+
typeof t.return == "function" && t.return(), t[g]?.(null);
|
|
46
|
+
}, F = (t, r, e) => {
|
|
47
|
+
e[o] ??= (I(e), t), Object.assign(e[c] ??= {}, r), e[m]();
|
|
48
|
+
}, I = (t) => {
|
|
49
|
+
Object.assign(t, K), t[j] = Object.create(f()?.[j] ?? null);
|
|
50
|
+
}, K = {
|
|
51
|
+
[m]() {
|
|
52
|
+
const t = f();
|
|
53
|
+
f(this);
|
|
57
54
|
try {
|
|
58
|
-
const { value:
|
|
59
|
-
b(
|
|
60
|
-
} catch (
|
|
61
|
-
this.throw(
|
|
55
|
+
const { value: r, done: e } = (this[a] ??= this[o].call(this, this[c])).next();
|
|
56
|
+
b(r, this), this[g]?.(this), e && this.return();
|
|
57
|
+
} catch (r) {
|
|
58
|
+
this.throw(r);
|
|
62
59
|
} finally {
|
|
63
|
-
|
|
60
|
+
f(t);
|
|
64
61
|
}
|
|
65
62
|
},
|
|
66
|
-
next(
|
|
67
|
-
if (typeof
|
|
68
|
-
|
|
69
|
-
} catch (
|
|
70
|
-
this.throw(
|
|
63
|
+
next(t) {
|
|
64
|
+
if (typeof t == "function") try {
|
|
65
|
+
t.call(this, this[c]);
|
|
66
|
+
} catch (r) {
|
|
67
|
+
this.throw(r);
|
|
71
68
|
}
|
|
72
|
-
|
|
69
|
+
f()?.contains(this) || this[m]();
|
|
73
70
|
},
|
|
74
|
-
throw(
|
|
75
|
-
for (let
|
|
76
|
-
return b(
|
|
77
|
-
} catch (
|
|
78
|
-
|
|
71
|
+
throw(t) {
|
|
72
|
+
for (let r = this; r; r = r.parentNode) if (typeof r[a]?.throw == "function") try {
|
|
73
|
+
return b(r[a].throw(t).value, r);
|
|
74
|
+
} catch (e) {
|
|
75
|
+
t = new Error(e instanceof Error ? e.message : e, { cause: t });
|
|
79
76
|
}
|
|
80
|
-
throw
|
|
77
|
+
throw t;
|
|
81
78
|
},
|
|
82
79
|
return() {
|
|
83
80
|
try {
|
|
84
|
-
this[
|
|
85
|
-
} catch (
|
|
86
|
-
this.throw(
|
|
81
|
+
this[a]?.return();
|
|
82
|
+
} catch (t) {
|
|
83
|
+
this.throw(t);
|
|
87
84
|
} finally {
|
|
88
|
-
this[
|
|
85
|
+
this[a] = null;
|
|
89
86
|
}
|
|
90
87
|
}
|
|
91
88
|
};
|
|
92
89
|
export {
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
U as Fragment,
|
|
91
|
+
h,
|
|
95
92
|
b as render
|
|
96
93
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ajo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"description": "ajo is a JavaScript view library for building user interfaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./types.ts",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"types.ts"
|
|
34
34
|
],
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@types/node": "24.
|
|
37
|
-
"happy-dom": "
|
|
38
|
-
"vite": "7.
|
|
36
|
+
"@types/node": "24.10.1",
|
|
37
|
+
"happy-dom": "20.0.11",
|
|
38
|
+
"vite": "7.2.4",
|
|
39
39
|
"vite-tsconfig-paths": "5.1.4",
|
|
40
|
-
"vitest": "
|
|
40
|
+
"vitest": "4.0.14"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|
|
43
43
|
"ui",
|
package/readme.md
CHANGED
|
@@ -36,24 +36,23 @@ npm install ajo
|
|
|
36
36
|
Create your first component:
|
|
37
37
|
|
|
38
38
|
```javascript
|
|
39
|
-
import { render } from 'ajo'
|
|
39
|
+
import { render } from 'ajo'
|
|
40
40
|
|
|
41
41
|
// Stateless component
|
|
42
42
|
const Greeting = ({ name }) => <p>Hello, {name}!</p>
|
|
43
43
|
|
|
44
44
|
// Stateful component
|
|
45
45
|
function* Counter() {
|
|
46
|
+
|
|
46
47
|
let count = 0
|
|
47
48
|
|
|
48
49
|
const increment = () => this.next(() => count++)
|
|
49
50
|
|
|
50
|
-
while (true)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
);
|
|
56
|
-
}
|
|
51
|
+
while (true) yield (
|
|
52
|
+
<button set:onclick={increment}>
|
|
53
|
+
Count: {count}
|
|
54
|
+
</button>
|
|
55
|
+
)
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
// Render to DOM
|
|
@@ -77,26 +76,19 @@ const UserCard = ({ user }) => (
|
|
|
77
76
|
**Stateful Components** use generator functions with automatic wrapper elements:
|
|
78
77
|
```javascript
|
|
79
78
|
function* TodoList() {
|
|
79
|
+
|
|
80
80
|
let todos = []
|
|
81
81
|
|
|
82
|
-
const addTodo = (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
<ul>
|
|
93
|
-
{todos.map(todo => (
|
|
94
|
-
<li key={todo.id}>{todo.text}</li>
|
|
95
|
-
))}
|
|
96
|
-
</ul>
|
|
97
|
-
</>
|
|
98
|
-
);
|
|
99
|
-
}
|
|
82
|
+
const addTodo = text => this.next(() => todos.push({ id: Date.now(), text }))
|
|
83
|
+
|
|
84
|
+
while (true) yield (
|
|
85
|
+
<>
|
|
86
|
+
<input set:onkeydown={e => e.key === 'Enter' && addTodo(e.target.value)} />
|
|
87
|
+
<ul>
|
|
88
|
+
{todos.map(todo => <li key={todo.id}>{todo.text}</li>)}
|
|
89
|
+
</ul>
|
|
90
|
+
</>
|
|
91
|
+
)
|
|
100
92
|
}
|
|
101
93
|
```
|
|
102
94
|
|
|
@@ -108,27 +100,27 @@ The generator structure provides a natural mental model:
|
|
|
108
100
|
|
|
109
101
|
```javascript
|
|
110
102
|
function* ShoppingCart(args) {
|
|
103
|
+
|
|
111
104
|
// Persistent state (like useState)
|
|
112
105
|
let items = []
|
|
113
|
-
|
|
106
|
+
|
|
114
107
|
// Persistent handlers (like useCallback)
|
|
115
|
-
const addItem = (
|
|
116
|
-
this.next(() => items.push(product))
|
|
117
|
-
};
|
|
108
|
+
const addItem = product => this.next(() => items.push(product))
|
|
118
109
|
|
|
119
110
|
// Main render loop
|
|
120
111
|
while (true) {
|
|
112
|
+
|
|
121
113
|
// Derived values computed fresh each render
|
|
122
114
|
const total = items.reduce((sum, item) => sum + item.price, 0)
|
|
123
115
|
const itemCount = items.length
|
|
124
|
-
|
|
116
|
+
|
|
125
117
|
yield (
|
|
126
118
|
<>
|
|
127
119
|
<h2>Cart ({itemCount} items)</h2>
|
|
128
120
|
<p>Total: ${total}</p>
|
|
129
121
|
{/* ... */}
|
|
130
122
|
</>
|
|
131
|
-
)
|
|
123
|
+
)
|
|
132
124
|
}
|
|
133
125
|
}
|
|
134
126
|
```
|
|
@@ -144,26 +136,23 @@ function* ShoppingCart(args) {
|
|
|
144
136
|
|
|
145
137
|
```javascript
|
|
146
138
|
function* MapComponent(args) {
|
|
139
|
+
|
|
147
140
|
let mapRef = null
|
|
148
|
-
|
|
149
|
-
while (true)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
<div class="map-markers"></div>
|
|
164
|
-
</div>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
141
|
+
|
|
142
|
+
while (true) yield (
|
|
143
|
+
<div
|
|
144
|
+
ref={el => {
|
|
145
|
+
if (el && !mapRef) {
|
|
146
|
+
mapRef = el
|
|
147
|
+
// Third-party map library controls this DOM
|
|
148
|
+
new GoogleMap(el, args.config)
|
|
149
|
+
}
|
|
150
|
+
}}
|
|
151
|
+
skip
|
|
152
|
+
>
|
|
153
|
+
{/* Google Maps API manages children elements */}
|
|
154
|
+
</div>
|
|
155
|
+
)
|
|
167
156
|
}
|
|
168
157
|
```
|
|
169
158
|
|
|
@@ -178,11 +167,9 @@ const html = render(<App />)
|
|
|
178
167
|
|
|
179
168
|
### Streaming SSR
|
|
180
169
|
```javascript
|
|
181
|
-
import { stream } from 'ajo/stream'
|
|
170
|
+
import { stream } from 'ajo/stream'
|
|
182
171
|
|
|
183
|
-
for await (const chunk of stream(<App />))
|
|
184
|
-
response.write(chunk);
|
|
185
|
-
}
|
|
172
|
+
for await (const chunk of stream(<App />)) response.write(chunk)
|
|
186
173
|
```
|
|
187
174
|
|
|
188
175
|
## Best Practices
|
|
@@ -196,13 +183,17 @@ for await (const chunk of stream(<App />)) {
|
|
|
196
183
|
|
|
197
184
|
### Core Module (`ajo`)
|
|
198
185
|
|
|
199
|
-
#### `render(children: Children, container: Element): void`
|
|
200
|
-
Renders JSX into a DOM container element.
|
|
186
|
+
#### `render(children: Children, container: Element, child?: ChildNode, ref?: ChildNode): void`
|
|
187
|
+
Renders JSX into a DOM container element. When `child` and `ref` are provided, only nodes between them (inclusive of `child`, exclusive of `ref`) are reconciled, leaving the rest of the container untouched.
|
|
201
188
|
|
|
202
189
|
```javascript
|
|
203
|
-
import { render } from 'ajo'
|
|
190
|
+
import { render } from 'ajo'
|
|
204
191
|
|
|
205
|
-
render(<App />, document.getElementById('root'))
|
|
192
|
+
render(<App />, document.getElementById('root'))
|
|
193
|
+
|
|
194
|
+
// Update only the <main> region without touching header/footer
|
|
195
|
+
const container = document.body
|
|
196
|
+
render(<main>Updated</main>, container, container.querySelector('main'), container.querySelector('footer'))
|
|
206
197
|
```
|
|
207
198
|
|
|
208
199
|
#### `h(type: Type, props?: Props, ...children: Children[]): VNode`
|
|
@@ -217,7 +208,7 @@ const List = () => (
|
|
|
217
208
|
<li>Item 1</li>
|
|
218
209
|
<li>Item 2</li>
|
|
219
210
|
</>
|
|
220
|
-
)
|
|
211
|
+
)
|
|
221
212
|
```
|
|
222
213
|
|
|
223
214
|
### Stateful Component Instance Methods
|
|
@@ -229,17 +220,18 @@ Triggers a re-render of the component by advancing to the next yield point. Opti
|
|
|
229
220
|
|
|
230
221
|
```javascript
|
|
231
222
|
function* Counter(args) {
|
|
232
|
-
|
|
223
|
+
|
|
224
|
+
let count = 0
|
|
233
225
|
|
|
234
226
|
const increment = () => {
|
|
235
227
|
// Simple re-render
|
|
236
|
-
this.next(() => count++)
|
|
237
|
-
}
|
|
228
|
+
this.next(() => count++)
|
|
229
|
+
}
|
|
238
230
|
|
|
239
231
|
const incrementByStep = () => {
|
|
240
232
|
// Access current props in callback
|
|
241
|
-
this.next(({ step }) => count += step)
|
|
242
|
-
}
|
|
233
|
+
this.next(({ step }) => count += step)
|
|
234
|
+
}
|
|
243
235
|
|
|
244
236
|
// ... rest of component
|
|
245
237
|
}
|
|
@@ -257,15 +249,15 @@ Terminates the generator and triggers cleanup (rarely used directly).
|
|
|
257
249
|
Creates a context for sharing data across component trees.
|
|
258
250
|
|
|
259
251
|
```javascript
|
|
260
|
-
import { context } from 'ajo/context'
|
|
252
|
+
import { context } from 'ajo/context'
|
|
261
253
|
|
|
262
|
-
const ThemeContext = context('light')
|
|
254
|
+
const ThemeContext = context('light')
|
|
263
255
|
|
|
264
256
|
// Set value
|
|
265
|
-
ThemeContext('dark')
|
|
257
|
+
ThemeContext('dark')
|
|
266
258
|
|
|
267
259
|
// Get value
|
|
268
|
-
const theme = ThemeContext()
|
|
260
|
+
const theme = ThemeContext() // 'dark'
|
|
269
261
|
```
|
|
270
262
|
|
|
271
263
|
### HTML Module (`ajo/html`)
|
|
@@ -274,9 +266,9 @@ const theme = ThemeContext(); // 'dark'
|
|
|
274
266
|
Renders JSX to an HTML string for static site generation.
|
|
275
267
|
|
|
276
268
|
```javascript
|
|
277
|
-
import { render } from 'ajo/html'
|
|
269
|
+
import { render } from 'ajo/html'
|
|
278
270
|
|
|
279
|
-
const html = render(<HomePage title="Welcome" />)
|
|
271
|
+
const html = render(<HomePage title="Welcome" />)
|
|
280
272
|
```
|
|
281
273
|
|
|
282
274
|
#### `html(children: Children, hooks?: Hooks): IterableIterator<string>`
|
|
@@ -288,54 +280,52 @@ Low-level HTML streaming function with custom hooks.
|
|
|
288
280
|
Renders components to an async stream for progressive SSR.
|
|
289
281
|
|
|
290
282
|
```javascript
|
|
291
|
-
import { stream } from 'ajo/stream'
|
|
283
|
+
import { stream } from 'ajo/stream'
|
|
292
284
|
|
|
293
|
-
for await (const chunk of stream(<App />))
|
|
294
|
-
response.write(chunk);
|
|
295
|
-
}
|
|
285
|
+
for await (const chunk of stream(<App />)) response.write(chunk)
|
|
296
286
|
```
|
|
297
287
|
|
|
298
288
|
#### `hydrate(patch: Patch): Promise<void>`
|
|
299
289
|
Client-side function for applying streamed patches during hydration.
|
|
300
290
|
|
|
301
291
|
```javascript
|
|
302
|
-
import { hydrate } from 'ajo/stream'
|
|
292
|
+
import { hydrate } from 'ajo/stream'
|
|
303
293
|
|
|
304
|
-
window.$stream = { push: hydrate }
|
|
294
|
+
window.$stream = { push: hydrate }
|
|
305
295
|
```
|
|
306
296
|
|
|
307
297
|
### TypeScript Support
|
|
308
298
|
|
|
309
299
|
```typescript
|
|
310
300
|
// Component types
|
|
311
|
-
type Stateless<Props = {}> = (props: Props) => Children
|
|
301
|
+
type Stateless<Props = {}> = (props: Props) => Children
|
|
312
302
|
type Stateful<Props = {}, Tag = 'div'> = {
|
|
313
|
-
(this: StatefulElement<Tag>, props: Props): Iterator<Children
|
|
314
|
-
is?: Tag
|
|
315
|
-
attrs?: Record<string, unknown
|
|
316
|
-
args?: Partial<Props
|
|
317
|
-
}
|
|
303
|
+
(this: StatefulElement<Tag>, props: Props): Iterator<Children>
|
|
304
|
+
is?: Tag
|
|
305
|
+
attrs?: Record<string, unknown>
|
|
306
|
+
args?: Partial<Props>
|
|
307
|
+
}
|
|
318
308
|
|
|
319
309
|
// Stateful component instance
|
|
320
310
|
type StatefulElement<Tag> = HTMLElement & {
|
|
321
|
-
next: (callback?: (args: ComponentArgs) => void) => void
|
|
322
|
-
throw: (error: unknown) => void
|
|
323
|
-
return: () => void
|
|
311
|
+
next: (callback?: (args: ComponentArgs) => void) => void
|
|
312
|
+
throw: (error: unknown) => void
|
|
313
|
+
return: () => void
|
|
324
314
|
};
|
|
325
315
|
|
|
326
316
|
// Element types
|
|
327
|
-
type Children = unknown
|
|
317
|
+
type Children = unknown
|
|
328
318
|
type VNode<Type, Props> = Props & {
|
|
329
|
-
nodeName: Type
|
|
330
|
-
children?: Children
|
|
319
|
+
nodeName: Type
|
|
320
|
+
children?: Children
|
|
331
321
|
};
|
|
332
322
|
|
|
333
323
|
// Special attributes
|
|
334
324
|
type SpecialAttributes = {
|
|
335
|
-
key?: unknown
|
|
336
|
-
ref?: (element: Element | null) => void
|
|
337
|
-
memo?: unknown[]
|
|
338
|
-
skip?: boolean
|
|
325
|
+
key?: unknown
|
|
326
|
+
ref?: (element: Element | null) => void
|
|
327
|
+
memo?: unknown[]
|
|
328
|
+
skip?: boolean
|
|
339
329
|
};
|
|
340
330
|
```
|
|
341
331
|
|
package/types.ts
CHANGED
|
@@ -2,9 +2,9 @@ declare module 'ajo' {
|
|
|
2
2
|
|
|
3
3
|
type Tag = keyof (HTMLElementTagNameMap & SVGElementTagNameMap)
|
|
4
4
|
|
|
5
|
-
type Type = Tag | Stateless | Stateful
|
|
5
|
+
type Type<TArguments extends Props = {}, TTag extends Tag = 'div'> = Tag | Stateless<TArguments> | Stateful<TArguments, TTag>
|
|
6
6
|
|
|
7
|
-
type Component<
|
|
7
|
+
type Component<TArguments extends Props = {}> = Stateless<TArguments> | Stateful<TArguments>
|
|
8
8
|
|
|
9
9
|
type Props = Record<string, unknown>
|
|
10
10
|
|
|
@@ -61,11 +61,12 @@ declare module 'ajo' {
|
|
|
61
61
|
|
|
62
62
|
function Fragment({ children }: ElementChildrenAttribute): typeof children
|
|
63
63
|
function h(tag: Type, props?: Props | null, ...children: Children[]): VNode<Type, Props>
|
|
64
|
-
function render(h: Children, el:
|
|
64
|
+
function render(h: Children, el: ParentNode, child?: ChildNode, ref?: ChildNode): void
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
declare module 'ajo/context' {
|
|
68
68
|
function context<T>(fallback?: T): (value?: T) => T
|
|
69
|
+
function current(): import('ajo').Stateful | null
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
declare module 'ajo/html' {
|