mono-jsx 0.6.0 → 0.6.2
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/README.md +5 -5
- package/jsx-runtime.mjs +21 -59
- package/package.json +1 -1
- package/types/html.d.ts +6 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ mono-jsx is a JSX runtime that renders `<html>` element to `Response` object in
|
|
|
7
7
|
- 🚀 No build step needed
|
|
8
8
|
- 🦋 Lightweight (10KB gzipped), zero dependencies
|
|
9
9
|
- 🚦 Signals as reactive primitives
|
|
10
|
-
- ⚡️ Use web
|
|
10
|
+
- ⚡️ Use web components, no virtual DOM
|
|
11
11
|
- 💡 Complete Web API TypeScript definitions
|
|
12
12
|
- ⏳ Streaming rendering
|
|
13
13
|
- 🗂️ Built-in router
|
|
@@ -816,9 +816,9 @@ async function Dash(this: FC<{ page: "Profile" | "Projects" | "Settings" }>) {
|
|
|
816
816
|
return (
|
|
817
817
|
<>
|
|
818
818
|
<div class="tab">
|
|
819
|
-
<button onClick={e => this.page = "Profile"}>Profile</
|
|
820
|
-
<button onClick={e => this.page = "Projects"}>Projects</
|
|
821
|
-
<button onClick={e => this.page = "Settings"}>Settings</
|
|
819
|
+
<button onClick={e => this.page = "Profile"}>Profile</button>
|
|
820
|
+
<button onClick={e => this.page = "Projects"}>Projects</button>
|
|
821
|
+
<button onClick={e => this.page = "Settings"}>Settings</button>
|
|
822
822
|
</div>
|
|
823
823
|
<div class="page">
|
|
824
824
|
<component name={this.page} placeholder={<p>Loading...</p>} />
|
|
@@ -946,7 +946,7 @@ export default {
|
|
|
946
946
|
}
|
|
947
947
|
```
|
|
948
948
|
|
|
949
|
-
###
|
|
949
|
+
### Fallback(404)
|
|
950
950
|
|
|
951
951
|
You can add fallback(404) content to the `<router>` element as children, which will be displayed when no route matches the current URL:
|
|
952
952
|
|
package/jsx-runtime.mjs
CHANGED
|
@@ -1,60 +1,18 @@
|
|
|
1
1
|
// runtime/index.ts
|
|
2
|
-
var VERSION = "0.6.
|
|
3
|
-
var CX_JS = `{var r=e=>typeof e=="string",o=e=>typeof e=="object"&&e!==null;var n=e=>r(e)?e:o(e)?Array.isArray(e)?e.map(n).filter(Boolean).join(" "):Object.entries(e).filter(([,t])=>!!t).map(([t])=>t).join(" "):"";window.$cx=n;}`;
|
|
4
|
-
var
|
|
2
|
+
var VERSION = "0.6.2";
|
|
3
|
+
var CX_JS = `{var i=new Set("animation-iteration-count,aspect-ratio,border-image-outset,border-image-slice,border-image-width,box-flex-group,box-flex,box-ordinal-group,column-count,columns,fill-opacity,flex-grow,flex-negative,flex-order,flex-positive,flex-shrink,flex,flood-opacity,font-weight,grid-area,grid-column-end,grid-column-span,grid-column-start,grid-column,grid-row-end,grid-row-span,grid-row-start,grid-row,line-clamp,line-height,opacity,order,orphans,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-miterlimit,stroke-opacity,stroke-width,tab-size,widows,z-index,zoom".split(",")),r=e=>typeof e=="string",o=e=>typeof e=="object"&&e!==null;var n=e=>r(e)?e:o(e)?Array.isArray(e)?e.map(n).filter(Boolean).join(" "):Object.entries(e).filter(([,t])=>!!t).map(([t])=>t).join(" "):"";window.$cx=n;}`;
|
|
4
|
+
var STYLE_JS = `{var c=new Set("animation-iteration-count,aspect-ratio,border-image-outset,border-image-slice,border-image-width,box-flex-group,box-flex,box-ordinal-group,column-count,columns,fill-opacity,flex-grow,flex-negative,flex-order,flex-positive,flex-shrink,flex,flood-opacity,font-weight,grid-area,grid-column-end,grid-column-span,grid-column-start,grid-column,grid-row-end,grid-row-span,grid-row-start,grid-row,line-clamp,line-height,opacity,order,orphans,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-miterlimit,stroke-opacity,stroke-width,tab-size,widows,z-index,zoom".split(",")),a=e=>typeof e=="string",l=e=>typeof e=="object"&&e!==null,u=e=>e.replace(/[a-z][A-Z]/g,o=>o.charAt(0)+"-"+o.charAt(1).toLowerCase());var p=e=>{let o=[],i=[],t=new g;for(let[n,r]of Object.entries(e))switch(n.charCodeAt(0)){case 58:i.push(null,n+"{"+s(r)+"}");break;case 64:i.push(n+"{",null,"{"+s(r)+"}}");break;case 38:i.push(null,n.slice(1)+"{"+s(r)+"}");break;default:o.push([n,r])}return o.length>0&&(t.inline=s(o)),i.length>0&&(t.css=i),t},f=(e,o)=>{let{inline:i,css:t}=p(o);if(t){let n="[data-css-"+Date.now().toString(36)+"]";document.head.appendChild(document.createElement("style")).textContent=(i?n+"{"+i+"}":"")+t.map(r=>r===null?n:r).join(""),e.getAttributeNames().forEach(r=>r.startsWith("data-css-")&&e.removeAttribute(r)),e.setAttribute(n.slice(1,-1),"")}else i&&e.setAttribute("style",i)},s=e=>{if(l(e)){let o="";for(let[i,t]of Array.isArray(e)?e:Object.entries(e))if(a(t)||typeof t=="number"){let n=u(i),r=typeof t=="number"?c.has(n)?""+t:t+"px":""+t;o+=(o?";":"")+n+":"+(n==="content"?JSON.stringify(r):r)}return o}return""},g=(()=>{function e(){}return e.prototype=Object.freeze(Object.create(null)),e})();window.$applyStyle=f;}`;
|
|
5
5
|
var EVENT_JS = `{var w=window;w.$emit=(e,f,s)=>f.call(w.$signals?.(s)??e.target,e.type==="mount"?e.target:e);w.$onsubmit=(e,f,s)=>{e.preventDefault();f.call(w.$signals?.(s)??e.target,new FormData(e.target),e)};}`;
|
|
6
|
-
var SIGNALS_JS = `{let p;const
|
|
6
|
+
var SIGNALS_JS = `{let p;const m=window,E=new Map,b=new Map,d=e=>b.get(e)??b.set(e,S(e)).get(e),u=(e,t)=>e.getAttribute(t),y=(e,t,r)=>e.setAttribute(t,r),M=(e,t)=>e.replaceChildren(...t),v=()=>Object.create(null),S=e=>{const t=v(),r=(c,l)=>{t[c]=l},n=new Map,i=(c,l)=>{let o=n.get(c);return o||(o=new Set,n.set(c,o)),o.add(l),()=>{o.delete(l),o.size===0&&n.delete(c)}},s=new Proxy(v(),{get:(c,l)=>document.querySelector("[data-ref='"+e+":"+l+"']")});return new Proxy(t,{get:(c,l,o)=>{switch(l){case"$init":return r;case"$watch":return i;case"app":return d(0);case"refs":return s;default:return p?.(e,l),Reflect.get(c,l,o)}},set:(c,l,o,a)=>{if(o!==Reflect.get(c,l,a)){const f=n.get(l);return f&&queueMicrotask(()=>f.forEach(g=>g())),Reflect.set(c,l,o,a)}return!1}})},k=(e,t,r)=>{if(t==="toggle"){let n;return()=>{if(!n){const i=e.firstElementChild;i&&i.tagName==="TEMPLATE"&&i.hasAttribute("m-slot")?n=[...i.content.childNodes]:n=[...e.childNodes]}M(e,r()?n:[])}}if(t==="switch"){let n,i=u(e,"match"),s,c,l=o=>s.get(o)??s.set(o,[]).get(o);return()=>{if(!s){s=new Map,c=[];for(const o of e.childNodes)if(o.nodeType===1&&o.tagName==="TEMPLATE"&&o.hasAttribute("m-slot")){for(const a of o.content.childNodes)a.nodeType===1&&a.hasAttribute("slot")?l(u(a,"slot")).push(a):c.push(a);o.remove()}else i?l(i).push(o):c.push(o)}n=""+r(),M(e,s.has(n)?s.get(n):c)}}if(t&&t.length>2&&t.startsWith("[")&&t.endsWith("]")){let n=t.slice(1,-1),i=e.parentElement;return i.tagName==="M-GROUP"&&(i=i.previousElementSibling),()=>{const s=r();s===!1||s===null||s===void 0?i.removeAttribute(n):typeof s=="object"&&s!==null&&(n==="class"||n==="style"||n==="props")?n==="class"?y(i,n,$cx(s)):n==="style"?$applyStyle(i,s):y(i,n,JSON.stringify(s)):y(i,n,s===!0?"":s)}}return()=>e.textContent=""+r()},N=e=>{const t=e.indexOf(":");return t>0?[Number(e.slice(0,t)),e.slice(t+1)]:null},w=async e=>{const t=e();return t!==void 0?t:(await new Promise(r=>setTimeout(r,0)),w(e))},T=(e,t)=>customElements.define(e,class extends HTMLElement{disposes=[];connectedCallback(){t(this)}disconnectedCallback(){this.disposes.forEach(r=>r()),this.disposes.length=0}});T("m-signal",e=>{const t=d(Number(u(e,"scope"))),r=u(e,"key");if(r)e.disposes.push(t.$watch(r,k(e,u(e,"mode"),()=>t[r])));else{const n=Number(u(e,"computed"));w(()=>E.get(n)).then(([i,s])=>{const c=k(e,u(e,"mode"),i.bind(t));s.forEach(l=>{const[o,a]=N(l);e.disposes.push(d(o).$watch(a,c))})})}}),T("m-effect",e=>{const{disposes:t}=e,r=Number(u(e,"scope")),n=Number(u(e,"n")),i=new Array(n);t.push(()=>{i.forEach(s=>typeof s=="function"&&s()),i.length=0});for(let s=0;s<n;s++){const c="$ME_"+r+"_"+s;w(()=>m[c]).then(l=>{const o=[],a=d(r),f=()=>{i[s]=l.call(a)};p=(g,h)=>o.push([g,h]),f(),p=void 0;for(const[g,h]of o)t.push(d(g).$watch(h,f))},()=>{})}}),m.$signals=e=>e!==void 0?d(e):void 0,m.$MS=(e,t)=>{const[r,n]=N(e);d(r).$init(n,t)},m.$MC=(e,t,r)=>{E.set(e,[t,r])},m.$merge=(e,...t)=>{for(const[r,...n]of t){let i=e;const s=n.pop();for(const c of n)i=i[c];i[s]=r}return e};}`;
|
|
7
7
|
var SUSPENSE_JS = `{const s=new Map,i=e=>e.getAttribute("chunk-id"),l=(e,t)=>customElements.define(e,class extends HTMLElement{connectedCallback(){t(this)}});l("m-portal",e=>{s.set(i(e),e)}),l("m-chunk",e=>{setTimeout(()=>{const t=e.firstChild?.content.childNodes,o=i(e),n=s.get(o);n&&(e.hasAttribute("next")?n.before(...t):(s.delete(o),e.hasAttribute("done")?n.remove():n.replaceWith(...t)),e.remove())})});}`;
|
|
8
|
-
var LAZY_JS = `{const
|
|
9
|
-
var ROUTER_JS = `{const n=document,a=t=>t.split("#",1)[0];customElements.define("m-router",class extends HTMLElement{#t;#e;#s;async#
|
|
8
|
+
var LAZY_JS = `{const r=document,o=(t,e)=>t.getAttribute(e),i=(t,e=[])=>t.replaceChildren(...e);customElements.define("m-component",class extends HTMLElement{static observedAttributes=["name","props"];#e;#i;#n;#t;#s;async#r(){const t={"x-component":this.#e,"x-props":this.#i??"{}","x-runtime-flag":""+$runtimeFlag,"x-scope-seq":""+$scopeSeq},e=new AbortController;this.#s?.abort(),this.#s=e,i(this,this.#n);const s=await fetch(location.href,{headers:t,signal:e.signal});if(!s.ok)throw i(this),new Error("Failed to fetch component '"+name+"'");const[l,n]=await s.json();this.innerHTML=l,n&&(r.body.appendChild(r.createElement("script")).textContent=n)}connectedCallback(){setTimeout(()=>{if(!this.#e){const t=o(this,"name"),e=o(this,"props");if(!t)throw new Error("Component name is required");this.#e=t,this.#i=e?.startsWith("base64,")?atob(e.slice(7)):null,this.#n=[...this.childNodes]}this.#r()})}disconnectedCallback(){i(this,this.#n),this.#s?.abort(),this.#t&&clearTimeout(this.#t),this.#s=void 0,this.#t=void 0}attributeChangedCallback(t,e,s){this.#e&&s&&e!==s&&(t==="name"?this.#e=s:t==="props"&&(this.#i=s),this.#t&&clearTimeout(this.#t),this.#t=setTimeout(()=>{this.#t=void 0,this.#r()},20))}});}`;
|
|
9
|
+
var ROUTER_JS = `{const n=document,a=t=>t.split("#",1)[0];customElements.define("m-router",class extends HTMLElement{#t;#e;#s;#i;async#o(t){const i={"x-route":"true","x-runtime-flag":""+$runtimeFlag,"x-scope-seq":""+$scopeSeq},e=new AbortController;this.#i?.abort(),this.#i=e;const s=await fetch(t,{headers:i,signal:e.signal});if(s.status===404){this.replaceChildren(...this.#t);return}if(!s.ok)throw this.replaceChildren(),new Error("Failed to fetch route: "+s.status+" "+s.statusText);const[o,r]=await s.json();this.innerHTML=o,r&&(n.body.appendChild(n.createElement("script")).textContent=r)}#n(){n.querySelectorAll("nav a").forEach(t=>{const{href:i,classList:e}=t,s=t.closest("nav").getAttribute("data-active-class")??"active";a(i)===a(location.href)?e.add(s):e.remove(s)})}#a(t){this.#o(t),this.#n()}connectedCallback(){setTimeout(()=>{if(!this.#t)if(this.getAttribute("status")==="404")this.#t=[...this.childNodes];else{this.#t=[];for(const t of this.childNodes)if(t.nodeType===1&&t.tagName==="TEMPLATE"&&t.hasAttribute("m-slot")){this.#t.push(...t.content.childNodes),t.remove();break}}}),this.#e=t=>{if(t.defaultPrevented||t.altKey||t.ctrlKey||t.metaKey||t.shiftKey||!(t.target instanceof HTMLAnchorElement))return;const{download:i,href:e,rel:s,target:o}=t.target;i||s==="external"||o==="_blank"||!e||!e.startsWith(location.origin)||a(e)===a(location.href)||(t.preventDefault(),history.pushState({},"",e),this.#a(e))},this.#s=()=>this.#a(location.href),addEventListener("popstate",this.#s),n.addEventListener("click",this.#e),setTimeout(()=>this.#n())}disconnectedCallback(){removeEventListener("popstate",this.#s),n.removeEventListener("click",this.#e),this.#i?.abort(),this.#s=void 0,this.#e=void 0,this.#i=void 0}});}`;
|
|
10
10
|
|
|
11
11
|
// runtime/utils.ts
|
|
12
12
|
var regexpHtmlSafe = /["'&<>]/;
|
|
13
|
-
var cssBareUnitProps =
|
|
14
|
-
"animation-iteration-count",
|
|
15
|
-
|
|
16
|
-
"border-image-outset",
|
|
17
|
-
"border-image-slice",
|
|
18
|
-
"border-image-width",
|
|
19
|
-
"box-flex-group",
|
|
20
|
-
"box-flex",
|
|
21
|
-
"box-ordinal-group",
|
|
22
|
-
"column-count",
|
|
23
|
-
"columns",
|
|
24
|
-
"fill-opacity",
|
|
25
|
-
"flex-grow",
|
|
26
|
-
"flex-negative",
|
|
27
|
-
"flex-order",
|
|
28
|
-
"flex-positive",
|
|
29
|
-
"flex-shrink",
|
|
30
|
-
"flex",
|
|
31
|
-
"flood-opacity",
|
|
32
|
-
"font-weight",
|
|
33
|
-
"grid-area",
|
|
34
|
-
"grid-column-end",
|
|
35
|
-
"grid-column-span",
|
|
36
|
-
"grid-column-start",
|
|
37
|
-
"grid-column",
|
|
38
|
-
"grid-row-end",
|
|
39
|
-
"grid-row-span",
|
|
40
|
-
"grid-row-start",
|
|
41
|
-
"grid-row",
|
|
42
|
-
"line-clamp",
|
|
43
|
-
"line-height",
|
|
44
|
-
"opacity",
|
|
45
|
-
"order",
|
|
46
|
-
"orphans",
|
|
47
|
-
"stop-opacity",
|
|
48
|
-
"stroke-dasharray",
|
|
49
|
-
"stroke-dashoffset",
|
|
50
|
-
"stroke-miterlimit",
|
|
51
|
-
"stroke-opacity",
|
|
52
|
-
"stroke-width",
|
|
53
|
-
"tab-size",
|
|
54
|
-
"widows",
|
|
55
|
-
"z-index",
|
|
56
|
-
"zoom"
|
|
57
|
-
]);
|
|
13
|
+
var cssBareUnitProps = new Set(
|
|
14
|
+
"animation-iteration-count,aspect-ratio,border-image-outset,border-image-slice,border-image-width,box-flex-group,box-flex,box-ordinal-group,column-count,columns,fill-opacity,flex-grow,flex-negative,flex-order,flex-positive,flex-shrink,flex,flood-opacity,font-weight,grid-area,grid-column-end,grid-column-span,grid-column-start,grid-column,grid-row-end,grid-row-span,grid-row-start,grid-row,line-clamp,line-height,opacity,order,orphans,stop-opacity,stroke-dasharray,stroke-dashoffset,stroke-miterlimit,stroke-opacity,stroke-width,tab-size,widows,z-index,zoom".split(",")
|
|
15
|
+
);
|
|
58
16
|
var isString = (v) => typeof v === "string";
|
|
59
17
|
var isObject = (v) => typeof v === "object" && v !== null;
|
|
60
18
|
var toHyphenCase = (k) => k.replace(/[a-z][A-Z]/g, (m) => m.charAt(0) + "-" + m.charAt(1).toLowerCase());
|
|
@@ -167,7 +125,7 @@ var $signal = Symbol.for("mono.signal");
|
|
|
167
125
|
|
|
168
126
|
// render.ts
|
|
169
127
|
var RUNTIME_CX = 1;
|
|
170
|
-
var
|
|
128
|
+
var RUNTIME_STYLE = 2;
|
|
171
129
|
var RUNTIME_EVENT = 4;
|
|
172
130
|
var RUNTIME_SIGNALS = 8;
|
|
173
131
|
var RUNTIME_SUSPENSE = 16;
|
|
@@ -239,6 +197,9 @@ function renderHtml(node, options) {
|
|
|
239
197
|
status = 404;
|
|
240
198
|
}
|
|
241
199
|
}
|
|
200
|
+
if (components && !request) {
|
|
201
|
+
console.warn("The `components` prop in the `<html>` element is ignored when `request` is not provided.");
|
|
202
|
+
}
|
|
242
203
|
if (headersInit) {
|
|
243
204
|
for (const [key, value] of Object.entries(headersInit)) {
|
|
244
205
|
if (value) {
|
|
@@ -337,9 +298,9 @@ async function render(node, options, write, writeJS, componentMode) {
|
|
|
337
298
|
runtimeFlag |= RUNTIME_CX;
|
|
338
299
|
js += CX_JS;
|
|
339
300
|
}
|
|
340
|
-
if (rc.flags.runtime &
|
|
341
|
-
runtimeFlag |=
|
|
342
|
-
js +=
|
|
301
|
+
if (rc.flags.runtime & RUNTIME_STYLE && !(runtimeFlag & RUNTIME_STYLE)) {
|
|
302
|
+
runtimeFlag |= RUNTIME_STYLE;
|
|
303
|
+
js += STYLE_JS;
|
|
343
304
|
}
|
|
344
305
|
if (rc.mfs.size > 0 && !(runtimeFlag & RUNTIME_EVENT)) {
|
|
345
306
|
runtimeFlag |= RUNTIME_EVENT;
|
|
@@ -686,7 +647,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
686
647
|
if (attrName === "class") {
|
|
687
648
|
rc.flags.runtime |= RUNTIME_CX;
|
|
688
649
|
} else if (attrName === "style") {
|
|
689
|
-
rc.flags.runtime |=
|
|
650
|
+
rc.flags.runtime |= RUNTIME_STYLE;
|
|
690
651
|
}
|
|
691
652
|
signalValue = signal;
|
|
692
653
|
attrValue = signal[$signal].value;
|
|
@@ -703,7 +664,7 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
703
664
|
const { inline, css } = styleToCSS(attrValue);
|
|
704
665
|
if (css) {
|
|
705
666
|
const id = hashCode((inline ?? "") + css.join("")).toString(36);
|
|
706
|
-
addonHtml += '<style
|
|
667
|
+
addonHtml += '<style data-mono-jsx-css="' + id + '">' + (inline ? "[data-css-" + id + "]{" + escapeCSSText(inline) + "}" : "") + escapeCSSText(css.map((v) => v === null ? "[data-css-" + id + "]" : v).join("")) + "</style>";
|
|
707
668
|
attr = " data-css-" + id;
|
|
708
669
|
} else if (inline) {
|
|
709
670
|
attr = " style=" + toAttrStringLit(inline);
|
|
@@ -745,9 +706,10 @@ function renderAttr(rc, attrName, attrValue, stripSlotProp) {
|
|
|
745
706
|
default:
|
|
746
707
|
if (attrName.startsWith("on") && typeof attrValue === "function") {
|
|
747
708
|
attr = " " + escapeHTML(attrName.toLowerCase()) + '="$emit(event,$MF_' + rc.mfs.gen(attrValue) + toStr(rc.fcCtx?.scopeId, (i) => "," + i) + ')"';
|
|
748
|
-
} else if (
|
|
709
|
+
} else if (attrValue === false || attrValue === null || attrValue === void 0) {
|
|
710
|
+
} else {
|
|
749
711
|
attr = " " + escapeHTML(attrName);
|
|
750
|
-
if (attrValue !==
|
|
712
|
+
if (attrValue !== true) {
|
|
751
713
|
attr += "=" + toAttrStringLit(String(attrValue));
|
|
752
714
|
}
|
|
753
715
|
}
|
package/package.json
CHANGED
package/types/html.d.ts
CHANGED
|
@@ -119,6 +119,11 @@ export namespace HTML {
|
|
|
119
119
|
type?: string;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
interface NavAttributes<T extends EventTarget> extends GlobalAttributes<T> {
|
|
123
|
+
/** @mono-jsx: This attribute is used to specify the class name for the active link. */
|
|
124
|
+
"data-active-class"?: string;
|
|
125
|
+
}
|
|
126
|
+
|
|
122
127
|
interface ImgAttributes<T extends EventTarget> extends GlobalAttributes<T>, LoaderElementAttributes<T> {
|
|
123
128
|
alt?: string;
|
|
124
129
|
crossOrigin?: CrossOrigin;
|
|
@@ -984,7 +989,7 @@ export namespace HTML {
|
|
|
984
989
|
menu: MenuAttributes<HTMLElement>;
|
|
985
990
|
meta: MetaAttributes<HTMLMetaElement>;
|
|
986
991
|
meter: MeterAttributes<HTMLMeterElement>;
|
|
987
|
-
nav:
|
|
992
|
+
nav: NavAttributes<HTMLElement>;
|
|
988
993
|
noindex: GlobalAttributes<HTMLElement>;
|
|
989
994
|
noscript: GlobalAttributes<HTMLElement>;
|
|
990
995
|
object: ObjectAttributes<HTMLObjectElement>;
|