mono-jsx 0.1.1 → 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 +36 -18
- package/jsx-runtime.mjs +91 -81
- package/package.json +1 -1
- package/types/aria.d.ts +1 -1
- package/types/css.d.ts +699 -586
- package/types/html.d.ts +3 -3
- package/types/mono.d.ts +1 -1
package/README.md
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
mono-jsx is a JSX runtime that renders `<html>` element to a `Response` object in JavaScript runtimes like Node.js, Deno, Bun, Cloudflare Workers, etc.
|
|
6
6
|
|
|
7
7
|
- 🚀 No build step needed
|
|
8
|
-
- 🦋 Lightweight(8KB gzipped), zero dependencies
|
|
8
|
+
- 🦋 Lightweight (8KB gzipped), zero dependencies
|
|
9
9
|
- 🔫 Minimal state runtime
|
|
10
|
-
- 🚨
|
|
10
|
+
- 🚨 Complete Web API Typescript definitions
|
|
11
11
|
- ⏳ Streaming rendering
|
|
12
12
|
- 🌎 Universal, works in Node.js, Deno, Bun, Cloudflare Workers, etc.
|
|
13
13
|
|
|
@@ -57,7 +57,7 @@ bunx mono-jsx setup
|
|
|
57
57
|
|
|
58
58
|
## Usage
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
mono-jsx allows you to return an `<html>` JSX element as a `Response` object in the `fetch` handler.
|
|
61
61
|
|
|
62
62
|
```tsx
|
|
63
63
|
// app.tsx
|
|
@@ -65,7 +65,7 @@ To create a html response in server-side, you just need to return a `<html>` ele
|
|
|
65
65
|
export default {
|
|
66
66
|
fetch: (req) => (
|
|
67
67
|
<html>
|
|
68
|
-
<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>
|
|
98
|
+
<h1>Welcome to mono-jsx!</h1>
|
|
99
99
|
</html>
|
|
100
100
|
),
|
|
101
101
|
});
|
|
@@ -113,11 +113,11 @@ mono-jsx uses [**JSX**](https://react.dev/learn/describing-the-ui) to describe t
|
|
|
113
113
|
|
|
114
114
|
### Using Standard HTML Property Names
|
|
115
115
|
|
|
116
|
-
mono-jsx
|
|
116
|
+
mono-jsx adopts standard HTML property names, avoiding React's custom property naming conventions.
|
|
117
117
|
|
|
118
|
-
- `className`
|
|
119
|
-
- `htmlFor`
|
|
120
|
-
- `onChange`
|
|
118
|
+
- `className` becomes `class`
|
|
119
|
+
- `htmlFor` becomes `for`
|
|
120
|
+
- `onChange` becomes `onInput`
|
|
121
121
|
|
|
122
122
|
### Composition `class`
|
|
123
123
|
|
|
@@ -148,7 +148,7 @@ mono-jsx allows you to use [pseudo classes](https://developer.mozilla.org/en-US/
|
|
|
148
148
|
|
|
149
149
|
### `<slot>` Element
|
|
150
150
|
|
|
151
|
-
mono-jsx uses [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) element to render the slotted content(Equivalent to React's `children`
|
|
151
|
+
mono-jsx uses [`<slot>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot) element to render the slotted content (Equivalent to React's `children` property). Plus, you also can add the `name` attribute to define a named slot.
|
|
152
152
|
|
|
153
153
|
```jsx
|
|
154
154
|
function Container() {
|
|
@@ -208,7 +208,7 @@ function Button() {
|
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
> [!NOTE]
|
|
211
|
-
> the event handler would never be called in server-side.
|
|
211
|
+
> the event handler would never be called in server-side. It will be serialized to a string and sent to the client-side. **This means you should NOT use any server-side variables or functions in the event handler.**
|
|
212
212
|
|
|
213
213
|
```tsx
|
|
214
214
|
function Button(this: FC, props: { role: string }) {
|
|
@@ -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>
|
|
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>
|
|
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>
|
|
@@ -333,18 +351,18 @@ function App(this: FC<{ lang: "en" | "zh" | "emoji" }>) {
|
|
|
333
351
|
|
|
334
352
|
## Streaming Rendering
|
|
335
353
|
|
|
336
|
-
mono-jsx renders your `<html>` as a readable stream, that allows async function components are rendered
|
|
354
|
+
mono-jsx renders your `<html>` as a readable stream, that allows async function components are rendered asynchronously. You can set a `placeholder` attribute to show a loading state while the async component is loading.
|
|
337
355
|
|
|
338
356
|
```jsx
|
|
339
357
|
async function Sleep(ms) {
|
|
340
358
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
341
|
-
return <
|
|
359
|
+
return <slot />;
|
|
342
360
|
}
|
|
343
361
|
|
|
344
362
|
export default {
|
|
345
363
|
fetch: (req) => (
|
|
346
364
|
<html>
|
|
347
|
-
<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>
|
|
@@ -358,13 +376,13 @@ You can also set `rendering` attribute to "eager" to render the async component
|
|
|
358
376
|
```jsx
|
|
359
377
|
async function Sleep(ms) {
|
|
360
378
|
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
361
|
-
return <
|
|
379
|
+
return <slot />;
|
|
362
380
|
}
|
|
363
381
|
|
|
364
382
|
export default {
|
|
365
383
|
fetch: (req) => (
|
|
366
384
|
<html>
|
|
367
|
-
<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 =
|
|
50
|
-
var RUNTIME_SUSPENSE_JS =
|
|
51
|
-
var RUNTIME_COMPONENTS_JS = {
|
|
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==="<"?"<":r===">"?">":"'")}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))
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
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 "<";
|
|
140
|
+
if (m === ">") return ">";
|
|
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 = """;
|
|
159
|
+
break;
|
|
160
|
+
case 38:
|
|
161
|
+
escape = "&";
|
|
162
|
+
break;
|
|
163
|
+
case 39:
|
|
164
|
+
escape = "'";
|
|
165
|
+
break;
|
|
166
|
+
case 60:
|
|
167
|
+
escape = "<";
|
|
168
|
+
break;
|
|
169
|
+
case 62:
|
|
170
|
+
escape = ">";
|
|
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
|
|
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 =
|
|
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 =
|
|
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 += " " +
|
|
454
|
+
buffer += " class=" + toAttrStringLit(cx(propValue));
|
|
399
455
|
break;
|
|
400
456
|
case "style":
|
|
401
457
|
if (isString(propValue) && propValue !== "") {
|
|
402
|
-
buffer +=
|
|
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 =
|
|
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 ([
|
|
448
|
-
css += cssSelector +
|
|
501
|
+
for (const [p, styles] of pseudoStyles) {
|
|
502
|
+
css += cssSelector + p + "{" + styles + "}";
|
|
449
503
|
}
|
|
450
|
-
for ([
|
|
451
|
-
css +=
|
|
504
|
+
for (const [at, styles] of atRuleStyles) {
|
|
505
|
+
css += at + "{" + cssSelector + "{" + styles + "}}";
|
|
452
506
|
}
|
|
453
|
-
for ([
|
|
454
|
-
css += cssSelector +
|
|
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 +=
|
|
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_" +
|
|
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 += " " +
|
|
529
|
+
buffer += " action=" + toAttrStringLit(propValue);
|
|
476
530
|
}
|
|
477
531
|
break;
|
|
478
532
|
case "slot":
|
|
479
533
|
if (!stripSlotProp && isString(propValue)) {
|
|
480
|
-
buffer += " " +
|
|
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_" +
|
|
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 += " " +
|
|
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 = """;
|
|
561
|
-
break;
|
|
562
|
-
case 38:
|
|
563
|
-
escape = "&";
|
|
564
|
-
break;
|
|
565
|
-
case 39:
|
|
566
|
-
escape = "'";
|
|
567
|
-
break;
|
|
568
|
-
case 60:
|
|
569
|
-
escape = "<";
|
|
570
|
-
break;
|
|
571
|
-
case 62:
|
|
572
|
-
escape = ">";
|
|
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
package/types/aria.d.ts
CHANGED