ilha 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,61 @@
1
+ import { S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-DZI0fEmR.js";
2
+ //#region src/internal.d.ts
3
+ /** Registry of live island mount handles keyed by host element. */
4
+ declare const ISLAND_MOUNT_HANDLES: WeakMap<Element, {
5
+ unmount: () => void | Promise<void>;
6
+ updateProps: (props?: Record<string, unknown>) => void;
7
+ }>;
8
+ /** Hook a parent's mountSlots uses to mount a child island and keep a handle
9
+ * for pushing updated props on later parent re-renders. */
10
+ declare const ISLAND_MOUNT_INTERNAL: unique symbol;
11
+ interface JsxEventRegistration {
12
+ type: string;
13
+ handler: NativeEventHandler;
14
+ modifier?: NativeEventModifier;
15
+ }
16
+ /**
17
+ * Bridge between the framework-agnostic JSX runtime and the active render.
18
+ * The core registers an implementation at module init; before that (or
19
+ * outside an island render) event registration yields no sentinel.
20
+ */
21
+ interface JsxRuntimeBridge {
22
+ registerEvent(registration: JsxEventRegistration): number | undefined;
23
+ /** Compose a child-island slot marker for direct `<Island />` calls. */
24
+ slot(options: {
25
+ island: unknown;
26
+ props: Record<string, unknown> | undefined;
27
+ key: string | undefined;
28
+ }): RawHtml;
29
+ }
30
+ /** Register the core's bridge implementation. Internal — called once by ilha. */
31
+ declare function setJsxRuntimeBridge(implementation: JsxRuntimeBridge): void;
32
+ /** @internal Register a native event handler with the active render context. */
33
+ declare function __ilhaJsxEvent(registration: JsxEventRegistration): number | undefined;
34
+ /** @internal Preserve island slot composition from the JSX runtime. */
35
+ declare function __ilhaJsxSlot(options: {
36
+ island: unknown;
37
+ props: Record<string, unknown> | undefined;
38
+ key: string | undefined;
39
+ }): RawHtml;
40
+ /** A hydration-manifest entry: sentinel key → action id or captured payload. */
41
+ type ManifestEntry = string | {
42
+ k: string;
43
+ a: unknown[];
44
+ };
45
+ interface ServerManifestSerializer {
46
+ /**
47
+ * Serialize one island's event→action manifest into markup hoisted ahead of
48
+ * the island HTML (e.g. a `<template data-ilha-actions>` element).
49
+ */
50
+ template(manifest: Map<string, ManifestEntry>): string;
51
+ }
52
+ /**
53
+ * Register the server-manifest serializer. Owned by @ilha/router — core only
54
+ * collects manifest data and delegates all markup serialization to the
55
+ * registered adapter (no-op until one registers).
56
+ */
57
+ declare function setServerManifestSerializer(serializer: ServerManifestSerializer | null): void;
58
+ /** @internal Used by island rendering to serialize nested child manifests. */
59
+ declare function serializeServerManifest(manifest: Map<string, ManifestEntry>): string;
60
+ //#endregion
61
+ export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, JsxEventRegistration, JsxRuntimeBridge, ManifestEntry, ServerManifestSerializer, __ilhaJsxEvent, __ilhaJsxSlot, serializeServerManifest, setJsxRuntimeBridge, setServerManifestSerializer };
@@ -0,0 +1,39 @@
1
+ //#region src/internal.ts
2
+ /** Registry of live island mount handles keyed by host element. */
3
+ const ISLAND_MOUNT_HANDLES = /* @__PURE__ */ new WeakMap();
4
+ /** Hook a parent's mountSlots uses to mount a child island and keep a handle
5
+ * for pushing updated props on later parent re-renders. */
6
+ const ISLAND_MOUNT_INTERNAL = Symbol.for("ilha.islandMountInternal");
7
+ let bridge = null;
8
+ /** Register the core's bridge implementation. Internal — called once by ilha. */
9
+ function setJsxRuntimeBridge(implementation) {
10
+ bridge = implementation;
11
+ }
12
+ /** @internal Register a native event handler with the active render context. */
13
+ function __ilhaJsxEvent(registration) {
14
+ return bridge?.registerEvent(registration);
15
+ }
16
+ /** @internal Preserve island slot composition from the JSX runtime. */
17
+ function __ilhaJsxSlot(options) {
18
+ return bridge?.slot(options) ?? {
19
+ [Symbol.for("ilha.raw")]: true,
20
+ value: ""
21
+ };
22
+ }
23
+ let serverManifestSerializer = null;
24
+ /**
25
+ * Register the server-manifest serializer. Owned by @ilha/router — core only
26
+ * collects manifest data and delegates all markup serialization to the
27
+ * registered adapter (no-op until one registers).
28
+ */
29
+ function setServerManifestSerializer(serializer) {
30
+ serverManifestSerializer = serializer;
31
+ }
32
+ /** @internal Used by island rendering to serialize nested child manifests. */
33
+ function serializeServerManifest(manifest) {
34
+ if (!serverManifestSerializer || manifest.size === 0) return "";
35
+ return serverManifestSerializer.template(manifest);
36
+ }
37
+
38
+ //#endregion
39
+ export { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, __ilhaJsxSlot, serializeServerManifest, setJsxRuntimeBridge, setServerManifestSerializer };
@@ -1,2 +1,2 @@
1
- import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-B-viVOB1.js";
1
+ import { a as JSX, r as jsxDEV, t as Fragment } from "./jsx-runtime-BCGuHwTg.js";
2
2
  export { Fragment, type JSX, jsxDEV };
@@ -1,4 +1,4 @@
1
- import { C as NativeEventModifier, E as SignalAccessor, O as SignalWriter, S as NativeEventHandler, T as RawHtml } from "./index-Cx35Xugv.js";
1
+ import { E as SignalAccessor, O as SignalWriter, S as NativeEventModifier, T as RawHtml, x as NativeEventHandler } from "./index-DZI0fEmR.js";
2
2
  //#region src/jsx-types.d.ts
3
3
  declare namespace JSX {
4
4
  export type Child = unknown;
@@ -200,8 +200,6 @@ declare namespace JSX {
200
200
  value?: string | number;
201
201
  width?: Numberish;
202
202
  "bind:value"?: BindAccessor<string | number>;
203
- "bind:valueAsNumber"?: BindAccessor<number | null>;
204
- "bind:valueAsDate"?: BindAccessor<Date | null>;
205
203
  "bind:checked"?: BindAccessor<boolean>;
206
204
  "bind:group"?: BindAccessor<string | number | Array<string | number>>;
207
205
  "bind:files"?: BindAccessor<FileList | null>;
@@ -1,2 +1,2 @@
1
- import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-B-viVOB1.js";
1
+ import { a as JSX, i as jsxs, n as jsx, r as jsxDEV, t as Fragment } from "./jsx-runtime-BCGuHwTg.js";
2
2
  export { Fragment, type JSX, jsx, jsxDEV, jsxs };
@@ -1,6 +1,10 @@
1
- import { __ilhaJsxEvent, __ilhaJsxSlot, html, raw } from "./index.js";
1
+ import { __ilhaJsxEvent, __ilhaJsxSlot } from "./internal.js";
2
+ import { html, isSafeUrlAttrValue, isUrlAttributeName, raw, serializeStyle } from "./index.js";
2
3
 
3
4
  //#region src/jsx-runtime.ts
5
+ function toTemplateStrings(chunks) {
6
+ return Object.assign(chunks, { raw: chunks });
7
+ }
4
8
  const RAW = Symbol.for("ilha.raw");
5
9
  const SIGNAL_ACCESSOR = Symbol.for("ilha.signalAccessor");
6
10
  const ISLAND = Symbol.for("ilha.island");
@@ -65,20 +69,6 @@ const VOID_ELEMENTS = /* @__PURE__ */ new Set([
65
69
  "track",
66
70
  "wbr"
67
71
  ]);
68
- const SAFE_CSS_PROP_RE = /^(-{2}[a-zA-Z][a-zA-Z0-9-]*|-?[a-zA-Z][a-zA-Z0-9-]*)$/;
69
- const URL_ATTRS = /* @__PURE__ */ new Set([
70
- "href",
71
- "src",
72
- "action",
73
- "formaction",
74
- "cite",
75
- "data",
76
- "poster"
77
- ]);
78
- const SAFE_URL_RE = /^(?!javascript:|data:text\/html|data:text\/xml|data:application\/xhtml\+xml|data:image\/svg|vbscript:)/i;
79
- function isSafeUrl(value) {
80
- return SAFE_URL_RE.test(value.replace(/[\u0000-\u0020]/g, ""));
81
- }
82
72
  function isRawHtml(v) {
83
73
  return !!(v && typeof v === "object" && RAW in v);
84
74
  }
@@ -114,16 +104,7 @@ function extractJsxSlotKey(props, keyArg) {
114
104
  if (rawKey == null) return void 0;
115
105
  return normalizeJsxSlotKey(rawKey);
116
106
  }
117
- function serializeStyle(value) {
118
- return Object.entries(value).map(([k, v]) => {
119
- if (!SAFE_CSS_PROP_RE.test(k)) return "";
120
- const prop = k.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
121
- const str = String(v);
122
- if (/[<>{};]/.test(str) || /expression\(/i.test(str) || /javascript:/i.test(str)) return "";
123
- return `${prop}:${str}`;
124
- }).filter(Boolean).join(";");
125
- }
126
- function pushJsxAttr({ chunks, values, eventSpecs, name, value }) {
107
+ function pushJsxAttr({ chunks, values, eventSpecs, tagName, name, value }) {
127
108
  if (value == null || name === "children" || name === "key") return;
128
109
  if (name === "__proto__" || name === "constructor" || name === "prototype") return;
129
110
  if (name.startsWith("bind:")) {
@@ -157,7 +138,7 @@ function pushJsxAttr({ chunks, values, eventSpecs, name, value }) {
157
138
  else if (value === false) return;
158
139
  if (safeName === "class" && !isRawHtml(value)) value = normalizeClass(value);
159
140
  if (safeName === "style" && value && typeof value === "object" && !isRawHtml(value)) value = serializeStyle(value);
160
- if ((URL_ATTRS.has(securityName) || /:(href|src|action|formaction|cite|data|poster)$/.test(securityName)) && !isSafeUrl(typeof value === "string" ? value : String(value))) return;
141
+ if (isUrlAttributeName(securityName) && !isSafeUrlAttrValue(tagName, securityName, typeof value === "string" ? value : String(value))) return;
161
142
  if (value === true) {
162
143
  chunks[chunks.length - 1] += ` ${safeName}`;
163
144
  return;
@@ -186,6 +167,7 @@ function renderJsxElement({ type, props, children, slotKey }) {
186
167
  chunks,
187
168
  values,
188
169
  eventSpecs,
170
+ tagName: type,
189
171
  name,
190
172
  value
191
173
  });
@@ -193,6 +175,7 @@ function renderJsxElement({ type, props, children, slotKey }) {
193
175
  chunks,
194
176
  values,
195
177
  eventSpecs,
178
+ tagName: type,
196
179
  name: "data-key",
197
180
  value: slotKey
198
181
  });
@@ -205,7 +188,7 @@ function renderJsxElement({ type, props, children, slotKey }) {
205
188
  }
206
189
  chunks[chunks.length - 1] += `</${type}>`;
207
190
  }
208
- return html(chunks, ...values);
191
+ return html(toTemplateStrings(chunks), ...values);
209
192
  }
210
193
  function jsx(type, props, maybeKey, ...restChildren) {
211
194
  const hasKeyArg = typeof maybeKey === "string" || typeof maybeKey === "number";
@@ -244,7 +227,7 @@ const jsxs = jsx;
244
227
  function Fragment(props, ...children) {
245
228
  const normalizedChildren = normalizeJsxChildren(props, children);
246
229
  const chunks = ["", ...normalizedChildren.map(() => "")];
247
- return html(chunks, ...normalizedChildren);
230
+ return html(toTemplateStrings(chunks), ...normalizedChildren);
248
231
  }
249
232
  function jsxDEV(type, props, maybeKey, _source, _self) {
250
233
  return jsx(type, props, maybeKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ilha",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "A tiny, framework-free island architecture library",
5
5
  "keywords": [
6
6
  "framework-free",
@@ -29,6 +29,7 @@
29
29
  ],
30
30
  "type": "module",
31
31
  "sideEffects": false,
32
+ "main": "./dist/index.js",
32
33
  "module": "./dist/index.js",
33
34
  "browser": {
34
35
  "process": false
@@ -46,13 +47,17 @@
46
47
  "./jsx-dev-runtime": {
47
48
  "types": "./dist/jsx-dev-runtime.d.ts",
48
49
  "import": "./dist/jsx-dev-runtime.js"
50
+ },
51
+ "./internal": {
52
+ "types": "./dist/internal.d.ts",
53
+ "import": "./dist/internal.js"
49
54
  }
50
55
  },
51
56
  "publishConfig": {
52
57
  "access": "public"
53
58
  },
54
59
  "scripts": {
55
- "build": "tsc && tsdown",
60
+ "build": "tsc -p tsconfig.build.json && tsdown",
56
61
  "cleanup": "rimraf dist node_modules",
57
62
  "test": "bun test"
58
63
  },