mono-jsx 0.1.2 → 0.1.3

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 CHANGED
@@ -65,7 +65,7 @@ mono-jsx allows you to return an `<html>` JSX element as a `Response` object in
65
65
  export default {
66
66
  fetch: (req) => (
67
67
  <html>
68
- <h1>Hello World!</h1>
68
+ <h1>Welcome to mono-jsx!</h1>
69
69
  </html>
70
70
  ),
71
71
  };
@@ -95,7 +95,7 @@ serve({
95
95
  port: 3000,
96
96
  fetch: (req) => (
97
97
  <html>
98
- <h1>Hello World!</h1>
98
+ <h1>Welcome to mono-jsx!</h1>
99
99
  </html>
100
100
  ),
101
101
  });
@@ -238,12 +238,30 @@ Plus, mono-jsx supports the `mount` event that will be triggered when the elemen
238
238
  function App() {
239
239
  return (
240
240
  <div onMount={(evt) => console.log(evt.target, "Mounted!")}>
241
- <h1>Hello World!</h1>
241
+ <h1>Welcome to mono-jsx!</h1>
242
242
  </div>
243
243
  );
244
244
  }
245
245
  ```
246
246
 
247
+ mono-jsx also accepts a function as the `action` property for `form` elements, which will be called when the form is submitted.
248
+
249
+ ```tsx
250
+ function App() {
251
+ return (
252
+ <form
253
+ action={(data: FormData, evt) => {
254
+ evt.defaultPrevented // true
255
+ console.log(data.get("name"));
256
+ }}
257
+ >
258
+ <input type="text" name="name" />
259
+ <button type="submit">Submit</button>
260
+ </form>
261
+ );
262
+ }
263
+ ```
264
+
247
265
  ## Using State
248
266
 
249
267
  mono-jsx provides a minimal state runtime that allows you to update view based on state changes in client-side.
@@ -298,7 +316,7 @@ function App(this: FC<{ show: boolean }>) {
298
316
  return (
299
317
  <div>
300
318
  <toggle value={this.show}>
301
- <h1>Hello World!</h1>
319
+ <h1>Welcome to mono-jsx!</h1>
302
320
  </toggle>
303
321
  <button onClick={toggle}>{this.computed(() => this.show ? "Hide" : "Show")}</button>
304
322
  </div>
@@ -344,7 +362,7 @@ async function Sleep(ms) {
344
362
  export default {
345
363
  fetch: (req) => (
346
364
  <html>
347
- <h1>Hello World!</h1>
365
+ <h1>Welcome to mono-jsx!</h1>
348
366
  <Sleep ms={1000} placeholder={<p>Sleeping...</p>}>
349
367
  <p>After 1 second</p>
350
368
  </Sleep>
@@ -364,7 +382,7 @@ async function Sleep(ms) {
364
382
  export default {
365
383
  fetch: (req) => (
366
384
  <html>
367
- <h1>Hello World!</h1>
385
+ <h1>Welcome to mono-jsx!</h1>
368
386
  <Sleep ms={1000} rendering="eager">
369
387
  <p>After 1 second</p>
370
388
  </Sleep>
package/jsx-runtime.mjs CHANGED
@@ -46,9 +46,16 @@ function createState(request) {
46
46
  }
47
47
 
48
48
  // runtime/index.ts
49
- var RUNTIME_STATE_JS = "const p=(e,i)=>e.getAttribute(i),m=(e,i)=>e.hasAttribute(i),M=new Map,T=e=>M.get(e)??M.set(e,L()).get(e);function L(){const e=Object.create(null),i=new Map;function f(n,o){let a=o;Object.defineProperty(e,n,{get:()=>a,set:u=>{if(u!==a){const r=i.get(n);r&&queueMicrotask(()=>r.forEach(s=>s())),a=u}}})}function d(n,o,a,u){let r;if(o==='toggle'){let s;r=()=>{if(!s){const t=n.firstElementChild;t&&t.tagName==='TEMPLATE'&&m(t,'m-slot')?(s=t.content.childNodes,n.innerHTML=''):s=n.childNodes}a()?n.append(...s):n.innerHTML=''}}else if(o==='switch'){let s=p(n,'match'),t,l,E=c=>t.get(c)??t.set(c,[]).get(c),h;r=()=>{if(!t){t=new Map,l=[];for(const c of n.childNodes)if(c.nodeType===1&&c.tagName==='TEMPLATE'&&m(c,'m-slot')){for(const g of c.content.childNodes)g.nodeType===1&&m(g,'slot')?E(p(g,'slot')).push(g):l.push(g);c.remove()}else s?E(s).push(c):l.push(c)}h=a(),n.innerHTML='',n.append(...t.has(h)?t.get(h):l)}}else if(o&&o.length>2&&o.startsWith('[')&&o.endsWith(']')){let s=o.slice(1,-1),t=n.parentElement;t.tagName==='M-GROUP'&&(t=t.previousElementSibling),r=()=>{const l=a();l===!1?t.removeAttribute(s):(s==='class'||s==='style')&&l&&typeof l=='object'?t.setAttribute(s,s==='class'?cx(l):styleToCSS(l)):t.setAttribute(s,l===!0?'':''+l)}}else r=()=>n.textContent=''+a();if(r)for(const s of u){let t=i.get(s);t||(t=[],i.set(s,t)),t.push(r)}}return{store:e,define:f,createEffect:d}}customElements.define('m-state',class extends HTMLElement{connectedCallback(){const e=this,i=p(e,'mode'),f=p(e,'key'),d=T(p(e,'fc'));f?d.createEffect(e,i,()=>d.store[f],[f]):m(e,'computed')&&setTimeout(()=>{const n=e.firstChild;if(n&&n.nodeType===1&&n.type==='computed'){const o=n.textContent;o&&new Function('$',o).call(d.store,(a,u)=>d.createEffect(e,i,a,u))}})}}),Object.assign(globalThis,{$state:e=>T(e).store,$defineState:(e,i)=>{const f=e.indexOf(':');f>0&&T(e.slice(0,f)).define(e.slice(f+1),i)}});";
50
- var RUNTIME_SUSPENSE_JS = "const n={},o=e=>e.getAttribute('chunk-id');c('m-portal',e=>{n[o(e)]=e}),c('m-chunk',e=>{const t=o(e),s=n[t];s&&setTimeout(()=>{s.replaceWith(...e.firstChild.content.childNodes),delete n[t],e.remove()})});function c(e,t){customElements.define(e,class extends HTMLElement{connectedCallback(){t(this)}})}";
51
- var RUNTIME_COMPONENTS_JS = { "cx": "var cx=(()=>{var e=r=>typeof r=='string',n=r=>typeof r=='object'&&r!==null;function t(r){return e(r)?r:n(r)?Array.isArray(r)?r.map(t).filter(Boolean).join(' '):Object.entries(r).filter(([,o])=>!!o).map(([o])=>o).join(' '):''}return t;})();", "styleToCSS": "var styleToCSS=(()=>{var a=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']),s=r=>typeof r=='string',c=r=>typeof r=='object'&&r!==null,f=r=>r.replace(/[a-z][A-Z]/g,t=>t.charAt(0)+'-'+t.charAt(1).toLowerCase());function u(r){if(s(r))return r;if(!c(r))return'';let t='';for(let[n,o]of Array.isArray(r)?r:Object.entries(r)){if(o==null||o===!1||Number.isNaN(o)||!s(n))return'';let e=f(n),i=typeof o=='number'?a.has(e)?''+o:o+'px':''+o;t+=(t!==''?';':'')+e+':'+(e==='content'?JSON.stringify(i):i)}return t}return u;})();", "event": "window.$emit=(evt,el,fn,fc)=>fn.call(window.$state?.(fc)??el,evt);window.$onsubmit=(evt,el,fn,fc)=>{evt.preventDefault();fn.call(window.$state?.(fc)??el,new FormData(el),evt)};" };
49
+ var RUNTIME_STATE_JS = `const p=(e,i)=>e.getAttribute(i),m=(e,i)=>e.hasAttribute(i),M=new Map,T=e=>M.get(e)??M.set(e,L()).get(e);function L(){const e=Object.create(null),i=new Map;function f(n,o){let a=o;Object.defineProperty(e,n,{get:()=>a,set:u=>{if(u!==a){const r=i.get(n);r&&queueMicrotask(()=>r.forEach(s=>s())),a=u}}})}function d(n,o,a,u){let r;if(o==="toggle"){let s;r=()=>{if(!s){const t=n.firstElementChild;t&&t.tagName==="TEMPLATE"&&m(t,"m-slot")?(s=t.content.childNodes,n.innerHTML=""):s=n.childNodes}a()?n.append(...s):n.innerHTML=""}}else if(o==="switch"){let s=p(n,"match"),t,l,E=c=>t.get(c)??t.set(c,[]).get(c),h;r=()=>{if(!t){t=new Map,l=[];for(const c of n.childNodes)if(c.nodeType===1&&c.tagName==="TEMPLATE"&&m(c,"m-slot")){for(const g of c.content.childNodes)g.nodeType===1&&m(g,"slot")?E(p(g,"slot")).push(g):l.push(g);c.remove()}else s?E(s).push(c):l.push(c)}h=a(),n.innerHTML="",n.append(...t.has(h)?t.get(h):l)}}else if(o&&o.length>2&&o.startsWith("[")&&o.endsWith("]")){let s=o.slice(1,-1),t=n.parentElement;t.tagName==="M-GROUP"&&(t=t.previousElementSibling),r=()=>{const l=a();l===!1?t.removeAttribute(s):(s==="class"||s==="style")&&l&&typeof l=="object"?t.setAttribute(s,s==="class"?cx(l):styleToCSS(l)):t.setAttribute(s,l===!0?"":""+l)}}else r=()=>n.textContent=""+a();if(r)for(const s of u){let t=i.get(s);t||(t=[],i.set(s,t)),t.push(r)}}return{store:e,define:f,createEffect:d}}customElements.define("m-state",class extends HTMLElement{connectedCallback(){const e=this,i=p(e,"mode"),f=p(e,"key"),d=T(p(e,"fc"));f?d.createEffect(e,i,()=>d.store[f],[f]):m(e,"computed")&&setTimeout(()=>{const n=e.firstChild;if(n&&n.nodeType===1&&n.type==="computed"){const o=n.textContent;o&&new Function("$",o).call(d.store,(a,u)=>d.createEffect(e,i,a,u))}})}}),Object.assign(globalThis,{$state:e=>T(e).store,$defineState:(e,i)=>{const f=e.indexOf(":");f>0&&T(e.slice(0,f)).define(e.slice(f+1),i)}});`;
50
+ var RUNTIME_SUSPENSE_JS = `const n={},o=e=>e.getAttribute("chunk-id");c("m-portal",e=>{n[o(e)]=e}),c("m-chunk",e=>{const t=o(e),s=n[t];s&&setTimeout(()=>{s.replaceWith(...e.firstChild.content.childNodes),delete n[t],e.remove()})});function c(e,t){customElements.define(e,class extends HTMLElement{connectedCallback(){t(this)}})}`;
51
+ var RUNTIME_COMPONENTS_JS = {
52
+ /** cx.js (239 bytes) */
53
+ cx: `var cx=(()=>{var n=e=>typeof e=="string",o=e=>typeof e=="object"&&e!==null;function t(e){return n(e)?e:o(e)?Array.isArray(e)?e.map(t).filter(Boolean).join(" "):Object.entries(e).filter(([,r])=>!!r).map(([r])=>r).join(" "):""}return t;})();`,
54
+ /** styleToCSS.js (1203 bytes) */
55
+ styleToCSS: `var styleToCSS=(()=>{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"]),s=e=>typeof e=="string",u=e=>typeof e=="object"&&e!==null,f=e=>e.replace(/[a-z][A-Z]/g,r=>r.charAt(0)+"-"+r.charAt(1).toLowerCase());function l(e){if(s(e))return e;if(u(e)){let r="";for(let[o,t]of Array.isArray(e)?e:Object.entries(e)){if(t==null||t===!1||Number.isNaN(t)||!s(o))return"";let n=f(o),i=typeof t=="number"?c.has(n)?""+t:t+"px":a(""+t);r+=(r!==""?";":"")+a(n)+":"+(n==="content"?JSON.stringify(i):i)}return r}return""}function a(e){return e.replace(/["<>]/g,r=>r==="<"?"&lt;":r===">"?"&gt;":"'")}return l;})();`,
56
+ /** event.js (176 bytes) */
57
+ event: `window.$emit=(evt,el,fn,fc)=>fn.call(window.$state?.(fc)??el,evt);window.$onsubmit=(evt,el,fn,fc)=>{evt.preventDefault();fn.call(window.$state?.(fc)??el,new FormData(el),evt)};`
58
+ };
52
59
 
53
60
  // runtime/utils.ts
54
61
  var cssBareUnitProps = /* @__PURE__ */ new Set([
@@ -112,26 +119,75 @@ function cx(className) {
112
119
  return "";
113
120
  }
114
121
  function styleToCSS(style) {
115
- if (isString(style)) return style;
116
- if (!isObject(style)) return "";
117
- let css = "";
118
- for (const [k, v] of Array.isArray(style) ? style : Object.entries(style)) {
119
- if (v === null || v === void 0 || v === false || Number.isNaN(v) || !isString(k)) return "";
120
- const cssKey = toHyphenCase(k);
121
- const cssValue = typeof v === "number" ? cssBareUnitProps.has(cssKey) ? "" + v : v + "px" : "" + v;
122
- css += (css !== "" ? ";" : "") + cssKey + ":" + (cssKey === "content" ? JSON.stringify(cssValue) : cssValue);
122
+ if (isString(style)) {
123
+ return style;
124
+ }
125
+ if (isObject(style)) {
126
+ let css = "";
127
+ for (const [k, v] of Array.isArray(style) ? style : Object.entries(style)) {
128
+ if (v === null || v === void 0 || v === false || Number.isNaN(v) || !isString(k)) return "";
129
+ const cssKey = toHyphenCase(k);
130
+ const cssValue = typeof v === "number" ? cssBareUnitProps.has(cssKey) ? "" + v : v + "px" : escapeCSSText("" + v);
131
+ css += (css !== "" ? ";" : "") + escapeCSSText(cssKey) + ":" + (cssKey === "content" ? JSON.stringify(cssValue) : cssValue);
132
+ }
133
+ return css;
134
+ }
135
+ return "";
136
+ }
137
+ function escapeCSSText(str) {
138
+ return str.replace(/["<>]/g, (m) => {
139
+ if (m === "<") return "&lt;";
140
+ if (m === ">") return "&gt;";
141
+ return "'";
142
+ });
143
+ }
144
+ var regexpHtmlSafe = /["'&<>]/;
145
+ function escapeHTML(str) {
146
+ if (typeof Bun === "object" && "escapeHTML" in Bun) return Bun.escapeHTML(str);
147
+ const match = regexpHtmlSafe.exec(str);
148
+ if (!match) {
149
+ return str;
150
+ }
151
+ let escape;
152
+ let index;
153
+ let lastIndex = 0;
154
+ let html2 = "";
155
+ for (index = match.index; index < str.length; index++) {
156
+ switch (str.charCodeAt(index)) {
157
+ case 34:
158
+ escape = "&quot;";
159
+ break;
160
+ case 38:
161
+ escape = "&amp;";
162
+ break;
163
+ case 39:
164
+ escape = "&#x27;";
165
+ break;
166
+ case 60:
167
+ escape = "&lt;";
168
+ break;
169
+ case 62:
170
+ escape = "&gt;";
171
+ break;
172
+ default:
173
+ continue;
174
+ }
175
+ if (lastIndex !== index) {
176
+ html2 += str.slice(lastIndex, index);
177
+ }
178
+ lastIndex = index + 1;
179
+ html2 += escape;
123
180
  }
124
- return css;
181
+ return lastIndex !== index ? html2 + str.slice(lastIndex, index) : html2;
125
182
  }
126
183
 
127
184
  // render.ts
128
185
  var encoder = new TextEncoder();
129
186
  var regexpHtmlTag = /^[a-z][\w\-$]*$/;
130
- var regexpHtmlSafe = /["'&<>]/;
131
187
  var selfClosingTags = new Set("area,base,br,col,embed,hr,img,input,keygen,link,meta,param,source,track,wbr".split(","));
132
- var toAttrStringLit = (str) => JSON.stringify(escapeHTML(str));
133
188
  var isVNode = (v) => Array.isArray(v) && v.length === 3 && v[2] === $vnode;
134
189
  var hashCode = (s) => [...s].reduce((hash, c) => Math.imul(31, hash) + c.charCodeAt(0) | 0, 0);
190
+ var toAttrStringLit = (str) => '"' + escapeHTML(str).replaceAll('"', '\\"') + '"';
135
191
  async function renderNode(ctx, node, stripSlotProp) {
136
192
  const { write, stateStore } = ctx;
137
193
  switch (typeof node) {
@@ -185,7 +241,7 @@ async function renderNode(ctx, node, stripSlotProp) {
185
241
  }
186
242
  break;
187
243
  }
188
- const fcIndex = toString36(ctx.index.fc);
244
+ const fcIndex = ctx.index.fc.toString(36);
189
245
  if (tag === $state) {
190
246
  const { key, value } = props;
191
247
  write('<m-state fc="' + fcIndex + '" key=' + toAttrStringLit(key) + ">");
@@ -325,7 +381,7 @@ async function renderNode(ctx, node, stripSlotProp) {
325
381
  if (eager) {
326
382
  await renderNode({ ...ctx, eager: true, slots: children }, await v);
327
383
  } else {
328
- const chunkId = toString36(ctx.suspenses.length + 1);
384
+ const chunkId = (ctx.suspenses.length + 1).toString(36);
329
385
  ctx.suspenses.push(v.then(async (c) => {
330
386
  write('<m-chunk chunk-id="' + chunkId + '"><template>');
331
387
  await renderNode({ ...ctx, eager, slots: children }, c);
@@ -395,11 +451,11 @@ async function renderNode(ctx, node, stripSlotProp) {
395
451
  }
396
452
  switch (propName) {
397
453
  case "class":
398
- buffer += " " + renderAttr(propName, cx(propValue));
454
+ buffer += " class=" + toAttrStringLit(cx(propValue));
399
455
  break;
400
456
  case "style":
401
457
  if (isString(propValue) && propValue !== "") {
402
- buffer += " " + renderAttr(propName, cx(propValue));
458
+ buffer += ' style="' + escapeCSSText(propValue) + '"';
403
459
  } else if (isObject(propValue) && !Array.isArray(propValue)) {
404
460
  const style = [];
405
461
  const pseudoStyles = [];
@@ -409,55 +465,53 @@ async function renderNode(ctx, node, stripSlotProp) {
409
465
  switch (k.charCodeAt(0)) {
410
466
  case /* ':' */
411
467
  58:
412
- pseudoStyles.push([k, styleToCSS(v)]);
468
+ pseudoStyles.push([escapeCSSText(k), styleToCSS(v)]);
413
469
  break;
414
470
  case /* '@' */
415
471
  64:
416
- atRuleStyles.push([k, styleToCSS(v)]);
472
+ atRuleStyles.push([escapeCSSText(k), styleToCSS(v)]);
417
473
  break;
418
474
  case /* '&' */
419
475
  38:
420
- nestingStyles.push([k, styleToCSS(v)]);
476
+ nestingStyles.push([escapeCSSText(k), styleToCSS(v)]);
421
477
  break;
422
478
  default:
423
479
  style.push([k, v]);
424
480
  }
425
481
  }
426
482
  if (pseudoStyles.length > 0 || atRuleStyles.length > 0 || nestingStyles.length > 0) {
427
- let raw = "";
428
483
  let css = "";
484
+ let raw = "";
429
485
  let styleIds;
430
486
  let id;
431
487
  let cssSelector;
432
- let key;
433
- let value;
434
488
  if (style.length > 0) {
435
489
  css = styleToCSS(style);
436
490
  raw += css + "|";
437
491
  }
438
492
  raw += [pseudoStyles, atRuleStyles, nestingStyles].flat(1).map(([k, v]) => k + ">" + v).join("|");
439
493
  styleIds = ctx.styleIds ?? (ctx.styleIds = /* @__PURE__ */ new Set());
440
- id = toString36(hashCode(raw));
494
+ id = hashCode(raw).toString(36);
441
495
  cssSelector = "[data-css-" + id + "]";
442
496
  if (!styleIds.has(id)) {
443
497
  styleIds.add(id);
444
498
  if (css) {
445
499
  css = cssSelector + "{" + css + "}";
446
500
  }
447
- for ([key, value] of pseudoStyles) {
448
- css += cssSelector + key + "{" + value + "}";
501
+ for (const [p, styles] of pseudoStyles) {
502
+ css += cssSelector + p + "{" + styles + "}";
449
503
  }
450
- for ([key, value] of atRuleStyles) {
451
- css += key + "{" + cssSelector + "{" + value + "}}";
504
+ for (const [at, styles] of atRuleStyles) {
505
+ css += at + "{" + cssSelector + "{" + styles + "}}";
452
506
  }
453
- for ([key, value] of nestingStyles) {
454
- css += cssSelector + key.slice(1) + "{" + value + "}";
507
+ for (const [n, styles] of nestingStyles) {
508
+ css += cssSelector + n.slice(1) + "{" + styles + "}";
455
509
  }
456
510
  write('<style id="css-' + id + '">' + css + "</style>");
457
511
  }
458
512
  buffer += " data-css-" + id;
459
513
  } else if (style.length > 0) {
460
- buffer += " " + renderAttr(propName, styleToCSS(style));
514
+ buffer += ' style="' + styleToCSS(style) + '"';
461
515
  }
462
516
  }
463
517
  break;
@@ -468,23 +522,23 @@ async function renderNode(ctx, node, stripSlotProp) {
468
522
  break;
469
523
  case "action":
470
524
  if (typeof propValue === "function" && tag === "form") {
471
- const id = "$MF_" + toString36(ctx.index.mf++);
525
+ const id = "$MF_" + (ctx.index.mf++).toString(36);
472
526
  write("<script>function " + id + "(fd){(" + propValue.toString() + ")(fd)}<\/script>");
473
527
  buffer += ' onsubmit="$onsubmit(event,this,' + id + ",'" + fcIndex + `')"`;
474
528
  } else if (isString(propValue)) {
475
- buffer += " " + renderAttr(propName, propValue);
529
+ buffer += " action=" + toAttrStringLit(propValue);
476
530
  }
477
531
  break;
478
532
  case "slot":
479
533
  if (!stripSlotProp && isString(propValue)) {
480
- buffer += " " + renderAttr(propName, propValue);
534
+ buffer += " slot=" + toAttrStringLit(propValue);
481
535
  }
482
536
  break;
483
537
  default:
484
538
  if (regexpHtmlTag.test(propName) && propValue !== void 0) {
485
539
  if (propName.startsWith("on")) {
486
540
  if (typeof propValue === "function") {
487
- const id = "$MF_" + toString36(ctx.index.mf++);
541
+ const id = "$MF_" + (ctx.index.mf++).toString(36);
488
542
  write("<script>function " + id + "(e){(" + propValue.toString() + ")(e)}<\/script>");
489
543
  buffer += " " + propName.toLowerCase() + '="$emit(event,this,' + id + ",'" + fcIndex + `')"`;
490
544
  }
@@ -493,7 +547,7 @@ async function renderNode(ctx, node, stripSlotProp) {
493
547
  buffer += " " + propName;
494
548
  }
495
549
  } else {
496
- buffer += " " + renderAttr(propName, propValue);
550
+ buffer += " " + (propValue === true ? escapeHTML(propName) : escapeHTML(propName) + "=" + toAttrStringLit("" + propValue));
497
551
  }
498
552
  }
499
553
  }
@@ -538,50 +592,6 @@ async function renderChildren(ctx, children, stripSlotProp) {
538
592
  await renderNode(ctx, children, stripSlotProp);
539
593
  }
540
594
  }
541
- function renderAttr(key, value) {
542
- return value === true ? key : key + "=" + toAttrStringLit("" + value);
543
- }
544
- function toString36(num) {
545
- return num.toString(36);
546
- }
547
- function escapeHTML(str) {
548
- const match = regexpHtmlSafe.exec(str);
549
- if (!match) {
550
- return str;
551
- }
552
- if (typeof Bun === "object" && "escapeHTML" in Bun) return Bun.escapeHTML(str);
553
- let escape;
554
- let index;
555
- let lastIndex = 0;
556
- let html2 = "";
557
- for (index = match.index; index < str.length; index++) {
558
- switch (str.charCodeAt(index)) {
559
- case 34:
560
- escape = "&quot;";
561
- break;
562
- case 38:
563
- escape = "&amp;";
564
- break;
565
- case 39:
566
- escape = "&#x27;";
567
- break;
568
- case 60:
569
- escape = "&lt;";
570
- break;
571
- case 62:
572
- escape = "&gt;";
573
- break;
574
- default:
575
- continue;
576
- }
577
- if (lastIndex !== index) {
578
- html2 += str.slice(lastIndex, index);
579
- }
580
- lastIndex = index + 1;
581
- html2 += escape;
582
- }
583
- return lastIndex !== index ? html2 + str.slice(lastIndex, index) : html2;
584
- }
585
595
  function render(node, renderOptions = {}) {
586
596
  const { request, status, headers: headersRaw, rendering } = renderOptions;
587
597
  const headers = /* @__PURE__ */ Object.create(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mono-jsx",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "`<html>` as a `Response`.",
5
5
  "type": "module",
6
6
  "module": "./index.mjs",
package/types/aria.d.ts CHANGED
@@ -231,7 +231,7 @@ export interface Attributes {
231
231
  }
232
232
 
233
233
  // All the WAI-ARIA 1.2 role attribute values from https://www.w3.org/TR/wai-aria-1.2/#role_definitions
234
- type Role =
234
+ export type Role =
235
235
  | "alert"
236
236
  | "alertdialog"
237
237
  | "application"
package/types/html.d.ts CHANGED
@@ -135,7 +135,7 @@ export namespace HTML {
135
135
 
136
136
  interface FormAttributes<T extends EventTarget> extends GlobalAttributes<T> {
137
137
  "accept-charset"?: string;
138
- action: string | (/* Mono specific */ (data: FormData) => void | Promise<void>);
138
+ action: string | (/* mono-jsx specific */ (data: FormData, event: SubmitEvent) => void | Promise<void>);
139
139
  autoComplete?: "on" | "off";
140
140
  encType?: "application/x-www-form-urlencoded" | "multipart/form-data" | "text/plain";
141
141
  method?: "GET" | "POST" | "dialog";
@@ -820,8 +820,8 @@ export namespace HTML {
820
820
  }
821
821
 
822
822
  interface EventAttributes<T extends EventTarget> {
823
- // Mono specific
824
- onMount?: (e: { type: "mount"; target: T }) => void | Promise<void>;
823
+ // mono-jsx specific
824
+ onMount?: (e: { type: "mount"; currentTarget: T; target: T }) => void | Promise<void>;
825
825
 
826
826
  // Input Events
827
827
  onBeforeInput?: EventHandler<Event, T>;