irisout 0.2.1
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/CHANGELOG.md +24 -0
- package/README.md +25 -0
- package/dist/LICENSE +190 -0
- package/dist/compiler/analyze.d.ts +61 -0
- package/dist/compiler/ast-codegen.d.ts +8 -0
- package/dist/compiler/decl-graph.d.ts +7 -0
- package/dist/compiler/inline-components.d.ts +4 -0
- package/dist/compiler/module-linker.d.ts +13 -0
- package/dist/compiler/render.d.ts +27 -0
- package/dist/compiler/state.d.ts +221 -0
- package/dist/diagnostics.d.ts +26 -0
- package/dist/diagnostics.js +83 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +28519 -0
- package/dist/jsx.d.ts +132 -0
- package/dist/runtime.d.ts +77 -0
- package/dist/runtime.js +286 -0
- package/dist/state.js +46 -0
- package/dist/vite.d.ts +18 -0
- package/dist/vite.js +67 -0
- package/package.json +37 -0
package/dist/jsx.d.ts
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// authored .jsx 向けの型検査基盤(ROADMAP.md 次のアクション10)。
|
|
2
|
+
//
|
|
3
|
+
// このコンパイラは .jsx を @babel/parser で直接解析するだけで、JSX を
|
|
4
|
+
// createElement 相当のランタイム呼び出しへ変換しない(docs/architecture.md
|
|
5
|
+
// コンパイルパイプライン参照)。したがって JSX.Element は実行時に何かを
|
|
6
|
+
// 表す型ではなく、TS の型検査を素通りさせるためのプレースホルダー型
|
|
7
|
+
// (TS公式の「カスタムJSX」パターン、React非依存)。
|
|
8
|
+
//
|
|
9
|
+
// 属性名は意図的に緩くしている: 共通属性(key/use/onXxxハンドラ/children)
|
|
10
|
+
// のみ明示的に型付けし、それ以外は string キーの index signature で
|
|
11
|
+
// 受ける。コンパイラ自身が host 属性名をホワイトリスト化していない
|
|
12
|
+
// (M4静的host属性・ADR-0012動的host属性はchecked/valueの特別扱い以外
|
|
13
|
+
// 任意の属性名をsetAttributeへ通す)ため、型を先に厳しくすると
|
|
14
|
+
// aria-*/data-* のような正当な属性を誤検出してしまう。
|
|
15
|
+
// 詳細は openspec/specs/authored-jsx-type-checking/spec.md 参照。
|
|
16
|
+
//
|
|
17
|
+
// 重要: 型が通ることと実行時に compile() が受理することは別軸のまま。
|
|
18
|
+
// 型はコンパイラの scope limit 判定を代替しない(例: リストアイテム内の
|
|
19
|
+
// use= は型上も実行時も要素・リストアイテム・条件分岐ブランチで受理されるが、
|
|
20
|
+
// 字句スコープ外のsignal参照など、STATUS.md のscope limitは別に適用される。
|
|
21
|
+
|
|
22
|
+
// イベントの実体はブラウザ標準のまま維持し、直接addEventListenerされる
|
|
23
|
+
// currentTargetだけを属性が書かれた要素へ絞る。targetは子要素になり得るため
|
|
24
|
+
// EventTarget | nullから変更しない(ADR-0009 UNRESOLVED(09)の解消)。
|
|
25
|
+
type IrisElementEvent<EventType extends Event, El extends Element> = EventType & {
|
|
26
|
+
readonly currentTarget: El
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type IrisEventHandler<EventType extends Event, El extends Element> = (
|
|
30
|
+
event: IrisElementEvent<EventType, El>,
|
|
31
|
+
) => void
|
|
32
|
+
|
|
33
|
+
// 任意のonXxxを受理する既存契約を維持しつつ、既知属性の関数型が
|
|
34
|
+
// テンプレートリテラル型の索引シグネチャにも代入できるようにする。
|
|
35
|
+
// 未知のイベント名では個別のイベント型を保証しない。
|
|
36
|
+
type IrisAnyEventHandler<El extends Element> =
|
|
37
|
+
| IrisEventHandler<Event, El>
|
|
38
|
+
| IrisEventHandler<FocusEvent, El>
|
|
39
|
+
| IrisEventHandler<InputEvent, El>
|
|
40
|
+
| IrisEventHandler<KeyboardEvent, El>
|
|
41
|
+
| IrisEventHandler<MouseEvent, El>
|
|
42
|
+
|
|
43
|
+
type IrisKnownEventAttributes<El extends Element> = {
|
|
44
|
+
onBlur?: IrisEventHandler<FocusEvent, El>
|
|
45
|
+
onChange?: IrisEventHandler<Event, El>
|
|
46
|
+
onClick?: IrisEventHandler<MouseEvent, El>
|
|
47
|
+
onDblClick?: IrisEventHandler<MouseEvent, El>
|
|
48
|
+
onInput?: IrisEventHandler<InputEvent, El>
|
|
49
|
+
onKeyDown?: IrisEventHandler<KeyboardEvent, El>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// mount 時に1回呼ばれ、関数返り値は従来どおり「更新のたびに呼ばれる
|
|
53
|
+
// 再描画クロージャ」として配線される。object 形式は更新クロージャと
|
|
54
|
+
// unmount 時だけ呼ぶ destroy を明示できる(ADR-0011/ADR-0022)。
|
|
55
|
+
type IrisUseActionResult = (() => void) | { update?: () => void; destroy?: () => void }
|
|
56
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: 「返り値なし」を`void`で表す意図的な設計(`undefined`への機械的置換はしない)
|
|
57
|
+
type IrisUseAction<El extends Element> = (el: El) => void | IrisUseActionResult
|
|
58
|
+
|
|
59
|
+
type IrisCommonAttributes<El extends Element> = IrisKnownEventAttributes<El> & {
|
|
60
|
+
use?: IrisUseAction<El>
|
|
61
|
+
children?: unknown
|
|
62
|
+
// onXxx パターンの未知のイベント処理属性も関数に限って受理する。
|
|
63
|
+
[handler: `on${string}`]: IrisAnyEventHandler<El> | undefined
|
|
64
|
+
// それ以外の属性名(aria-*/data-* 含む)は緩く受ける(design.md Decision 3)。
|
|
65
|
+
[attr: string]: unknown
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type IrisSvgAttributes<El extends SVGElement> = IrisCommonAttributes<El> & {
|
|
69
|
+
// 名前空間属性はSVGの初期HTMLで使う静的な参照に限る。動的な値は
|
|
70
|
+
// compiler側のscope limitで拒否する。
|
|
71
|
+
'xlink:href'?: string
|
|
72
|
+
'xml:space'?: string
|
|
73
|
+
'xmlns:xlink'?: string
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface IrisSignal<T> {
|
|
77
|
+
(): T
|
|
78
|
+
(next: T | ((previous: T) => T)): T
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
declare function signal<T>(initial: T): IrisSignal<T>
|
|
82
|
+
declare function derived<T>(compute: () => T): () => T
|
|
83
|
+
declare function render(element: JSX.Element): void
|
|
84
|
+
// componentのmount/hydrate完了後に一度だけ呼ばれ、返り値のcleanupは
|
|
85
|
+
// instanceのunmount時に一度だけ呼ばれる。構造unit内ではunit factoryが所有する。
|
|
86
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: callbackの「返り値なし」を表す
|
|
87
|
+
declare function onMount(callback: () => void | (() => void)): void
|
|
88
|
+
// root componentの依存signal/derivedが変わるたびに再実行され、前回の返り値の
|
|
89
|
+
// cleanupは再実行前とinstanceのunmount時に呼ばれる。compilerのscope limitに
|
|
90
|
+
// よる制約(signal書き込み禁止・root動きゾーン専用)は型宣言の代替ではない。
|
|
91
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: callbackの「返り値なし」を表す
|
|
92
|
+
declare function effect(callback: () => void | (() => void)): void
|
|
93
|
+
|
|
94
|
+
interface IrisContext<T> {
|
|
95
|
+
readonly __irisoutContextType?: T
|
|
96
|
+
}
|
|
97
|
+
interface IrisAsyncContext<T> extends IrisContext<PromiseLike<T>> {}
|
|
98
|
+
declare function createContext<T>(defaultValue: T): IrisContext<T>
|
|
99
|
+
// 非同期contextはPromiseLike<T>を値として静的置換する。compilerはawait、Suspense、
|
|
100
|
+
// schedulerを暗黙に追加せず、解決後の処理はauthorがthen/await可能な動きゾーンで行う。
|
|
101
|
+
declare function createAsyncContext<T>(defaultValue: PromiseLike<T>): IrisAsyncContext<T>
|
|
102
|
+
declare function provideContext<T>(context: IrisContext<T>, value: T): void
|
|
103
|
+
declare function useContext<T>(context: IrisContext<T>): T
|
|
104
|
+
|
|
105
|
+
declare namespace JSX {
|
|
106
|
+
// 同一ファイル内合成(ADR-0014)のコンポーネントは`render()`を内部で
|
|
107
|
+
// 呼ぶだけで値を返さない(推論される返り値型は`void`)。TSのJSX
|
|
108
|
+
// コンポーネントチェックは「タグの返り値がJSX.Elementに代入可能か」を
|
|
109
|
+
// 見るため、`void`も許容しておかないと同一ファイル内合成コンポーネントの
|
|
110
|
+
// JSXタグ使用が軒並み型エラーになる。`undefined`への置換は不可
|
|
111
|
+
// (「返り値なし関数」の推論型は`void`であって`undefined`ではないため、
|
|
112
|
+
// 置換すると同一ファイル内合成コンポーネントの型エラーが復活する)。
|
|
113
|
+
// biome-ignore lint/suspicious/noConfusingVoidType: 上記の理由で意図的
|
|
114
|
+
type Element = void | object
|
|
115
|
+
interface ElementChildrenAttribute {
|
|
116
|
+
children: unknown
|
|
117
|
+
}
|
|
118
|
+
// `key`はReactと同じくintrinsic要素・コンポーネント両方のJSXタグに
|
|
119
|
+
// 無条件で乗る特別な属性(ADR-0005 factory closureのリストアイテム識別、
|
|
120
|
+
// DOM属性ではない)。コンポーネント側は各自のprops型にkeyを含めなくて
|
|
121
|
+
// 済むよう、ここで一括宣言する(TS公式のIntrinsicAttributesパターン)。
|
|
122
|
+
interface IntrinsicAttributes {
|
|
123
|
+
key?: string | number
|
|
124
|
+
}
|
|
125
|
+
type IntrinsicElements = {
|
|
126
|
+
[K in keyof HTMLElementTagNameMap]: IrisCommonAttributes<HTMLElementTagNameMap[K]>
|
|
127
|
+
} & {
|
|
128
|
+
[K in Exclude<keyof SVGElementTagNameMap, keyof HTMLElementTagNameMap>]: IrisSvgAttributes<
|
|
129
|
+
SVGElementTagNameMap[K]
|
|
130
|
+
>
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
type DeclId = string;
|
|
2
|
+
type DeclKind = 'signal' | 'derived';
|
|
3
|
+
export interface ListItemState {
|
|
4
|
+
readonly listId: string;
|
|
5
|
+
readonly itemId: unknown;
|
|
6
|
+
readonly bindings: Map<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
export interface ListItemHandle<T = unknown> {
|
|
9
|
+
el: Element;
|
|
10
|
+
/** 複雑なネスト構造向けの互換経路。通常のList itemは共有updaterを使う。 */
|
|
11
|
+
update?(next: T): void;
|
|
12
|
+
/** DOMへ接続された後に、このitemが所有するactionを初期化する。 */
|
|
13
|
+
mount?(): void;
|
|
14
|
+
/** itemと子unitの所有資源を解放する。複数回呼び出しても安全であること。 */
|
|
15
|
+
destroy?(): void;
|
|
16
|
+
}
|
|
17
|
+
export interface DomRange {
|
|
18
|
+
readonly start: Comment;
|
|
19
|
+
readonly end: Comment;
|
|
20
|
+
}
|
|
21
|
+
export type UseActionUpdate = () => void;
|
|
22
|
+
export type UseActionDestroy = () => void;
|
|
23
|
+
export type UseActionResult = void | UseActionUpdate | {
|
|
24
|
+
update?: UseActionUpdate;
|
|
25
|
+
destroy?: UseActionDestroy;
|
|
26
|
+
};
|
|
27
|
+
export interface NormalizedUseActionResult {
|
|
28
|
+
update?: UseActionUpdate;
|
|
29
|
+
destroy?: UseActionDestroy;
|
|
30
|
+
}
|
|
31
|
+
export declare function normalizeUseActionResult(value: unknown, actionId: string): NormalizedUseActionResult;
|
|
32
|
+
export type ListItemUpdater<T> = (handle: ListItemHandle<T>, next: T) => void;
|
|
33
|
+
interface ListRecord<T> {
|
|
34
|
+
state: ListItemState;
|
|
35
|
+
handle: ListItemHandle<T>;
|
|
36
|
+
}
|
|
37
|
+
export interface ListRuntime<T> {
|
|
38
|
+
readonly listId: string;
|
|
39
|
+
readonly items: Map<unknown, ListRecord<T>>;
|
|
40
|
+
}
|
|
41
|
+
export declare function createListRuntime<T = unknown>(listId: string): ListRuntime<T>;
|
|
42
|
+
export declare function updateListBinding(item: ListItemState, bindingId: string, value: unknown): boolean;
|
|
43
|
+
export declare function updateListItem<T>(runtime: ListRuntime<T>, itemId: unknown, next: T, update?: ListItemUpdater<T>): void;
|
|
44
|
+
export declare function reconcileList<T>(runtime: ListRuntime<T>, container: Element | DomRange | undefined, values: readonly T[], keyOf: (value: T) => unknown, create: (value: T, state: ListItemState) => ListItemHandle<T>, update?: ListItemUpdater<T>): void;
|
|
45
|
+
export declare function reconcileListWithLifecycle<T>(runtime: ListRuntime<T>, container: Element | DomRange | undefined, values: readonly T[], keyOf: (value: T) => unknown, create: (value: T, state: ListItemState) => ListItemHandle<T>, update?: ListItemUpdater<T>, mountItems?: boolean): void;
|
|
46
|
+
export declare function mountListRuntime<T>(runtime: ListRuntime<T>): void;
|
|
47
|
+
export declare function destroyListRuntime<T>(runtime: ListRuntime<T>): void;
|
|
48
|
+
export declare const registry: Map<string, {
|
|
49
|
+
kind: DeclKind;
|
|
50
|
+
}>;
|
|
51
|
+
export interface SignalAccessor<T> {
|
|
52
|
+
(): T;
|
|
53
|
+
(next: T | ((previous: T) => T)): T;
|
|
54
|
+
}
|
|
55
|
+
export declare function signal<T>(initial: T, declId?: DeclId): SignalAccessor<T>;
|
|
56
|
+
export interface SharedSignal<T> {
|
|
57
|
+
(): T;
|
|
58
|
+
(next: T | ((previous: T) => T)): T;
|
|
59
|
+
subscribe(listener: () => void): () => void;
|
|
60
|
+
}
|
|
61
|
+
export declare function sharedSignal<T>(initial: T): SharedSignal<T>;
|
|
62
|
+
export declare function derived<T>(compute: () => T, declId?: DeclId): () => T;
|
|
63
|
+
export declare function hydrate(container: Element, expectedIds?: readonly string[]): {
|
|
64
|
+
markers: Map<string, Element>;
|
|
65
|
+
};
|
|
66
|
+
export declare function mount(container: Element, html: string, expectedIds?: readonly string[]): {
|
|
67
|
+
markers: Map<string, Element>;
|
|
68
|
+
};
|
|
69
|
+
export declare function hydrateWithRanges(container: Element, expectedIds?: readonly string[], expectedRangeIds?: readonly string[]): {
|
|
70
|
+
markers: Map<string, Element>;
|
|
71
|
+
ranges: Map<string, DomRange>;
|
|
72
|
+
};
|
|
73
|
+
export declare function mountWithRanges(container: Element, html: string, expectedIds?: readonly string[], expectedRangeIds?: readonly string[]): {
|
|
74
|
+
markers: Map<string, Element>;
|
|
75
|
+
ranges: Map<string, DomRange>;
|
|
76
|
+
};
|
|
77
|
+
export {};
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
//#region packages/runtime/src/index.ts
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
if (e === void 0) return {};
|
|
4
|
+
if (typeof e == "function") return { update: e };
|
|
5
|
+
if (typeof e != "object" || !e || Array.isArray(e)) throw Error(`use action ${t} must return void, a zero-argument update function, or { update?, destroy? }`);
|
|
6
|
+
let n = e;
|
|
7
|
+
for (let e of Object.keys(n)) if (e !== "update" && e !== "destroy") throw Error(`use action ${t} returned an unsupported property: ${e}`);
|
|
8
|
+
if (n.update !== void 0 && typeof n.update != "function") throw Error(`use action ${t}.update must be a function when provided`);
|
|
9
|
+
if (n.destroy !== void 0 && typeof n.destroy != "function") throw Error(`use action ${t}.destroy must be a function when provided`);
|
|
10
|
+
return {
|
|
11
|
+
update: n.update,
|
|
12
|
+
destroy: n.destroy
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function t(e) {
|
|
16
|
+
return {
|
|
17
|
+
listId: e,
|
|
18
|
+
items: /* @__PURE__ */ new Map()
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function n(e, t, n) {
|
|
22
|
+
if (e.bindings.has(t)) {
|
|
23
|
+
let r = e.bindings.get(t);
|
|
24
|
+
if (Object.is(r, n)) return !1;
|
|
25
|
+
}
|
|
26
|
+
return e.bindings.set(t, n), !0;
|
|
27
|
+
}
|
|
28
|
+
function r(e, t, n, r) {
|
|
29
|
+
let i = e.items.get(t);
|
|
30
|
+
if (!i) throw Error(`updateListItem: unknown item ${String(t)} in list ${e.listId}`);
|
|
31
|
+
if (r) r(i.handle, n);
|
|
32
|
+
else if (i.handle.update) i.handle.update(n);
|
|
33
|
+
else throw Error(`updateListItem: no updater for item ${String(t)} in list ${e.listId}`);
|
|
34
|
+
}
|
|
35
|
+
function i(e, t, n, r) {
|
|
36
|
+
if (r && n.length > 0) {
|
|
37
|
+
let r = e.ownerDocument;
|
|
38
|
+
if (r) {
|
|
39
|
+
let i = r.createDocumentFragment();
|
|
40
|
+
for (let e of n) i.append(e.handle.el);
|
|
41
|
+
e.insertBefore(i, t);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let i = null;
|
|
46
|
+
for (let r = n.length - 1; r >= 0; r--) {
|
|
47
|
+
let a = n[r].handle.el;
|
|
48
|
+
(a.parentNode !== e || a.nextSibling !== (i ?? t)) && e.insertBefore(a, i ?? t), i = a;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function a(e, t, n, r, a, o) {
|
|
52
|
+
let s = e.items.size === 0, c = [];
|
|
53
|
+
if (s) for (let t of n) {
|
|
54
|
+
let n = r(t);
|
|
55
|
+
if (e.items.get(n) !== void 0) throw Error(`reconcileList: duplicate key ${String(n)} in list ${e.listId}`);
|
|
56
|
+
let i = {
|
|
57
|
+
listId: e.listId,
|
|
58
|
+
itemId: n,
|
|
59
|
+
bindings: /* @__PURE__ */ new Map()
|
|
60
|
+
}, o = {
|
|
61
|
+
state: i,
|
|
62
|
+
handle: a(t, i)
|
|
63
|
+
};
|
|
64
|
+
e.items.set(n, o), c.push(o);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
let t = /* @__PURE__ */ new Set();
|
|
68
|
+
for (let i of n) {
|
|
69
|
+
let n = r(i);
|
|
70
|
+
if (t.has(n)) throw Error(`reconcileList: duplicate key ${String(n)} in list ${e.listId}`);
|
|
71
|
+
t.add(n);
|
|
72
|
+
let s = e.items.get(n);
|
|
73
|
+
if (s) {
|
|
74
|
+
if (o) o(s.handle, i);
|
|
75
|
+
else if (s.handle.update) s.handle.update(i);
|
|
76
|
+
else throw Error(`reconcileList: no updater for item ${String(n)} in list ${e.listId}`);
|
|
77
|
+
} else {
|
|
78
|
+
let t = {
|
|
79
|
+
listId: e.listId,
|
|
80
|
+
itemId: n,
|
|
81
|
+
bindings: /* @__PURE__ */ new Map()
|
|
82
|
+
}, r = {
|
|
83
|
+
state: t,
|
|
84
|
+
handle: a(i, t)
|
|
85
|
+
};
|
|
86
|
+
e.items.set(n, r), c.push(r);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
c.push(s);
|
|
90
|
+
}
|
|
91
|
+
for (let [n, r] of e.items) t.has(n) || (r.handle.el.remove(), e.items.delete(n));
|
|
92
|
+
}
|
|
93
|
+
if (!t) return;
|
|
94
|
+
let u = l(t) ? t.start.parentNode : t;
|
|
95
|
+
u && i(u, l(t) ? t.end : null, c, s && c.length > 0);
|
|
96
|
+
}
|
|
97
|
+
function o(e, t, n, r, a, o, s = !0) {
|
|
98
|
+
let c = e.items.size === 0, u = c ? null : /* @__PURE__ */ new Set(), d = [], f = [], p = (t) => {
|
|
99
|
+
let n = t;
|
|
100
|
+
for (let t = f.length - 1; t >= 0; t--) {
|
|
101
|
+
let r = f[t];
|
|
102
|
+
try {
|
|
103
|
+
r.handle.destroy?.();
|
|
104
|
+
} catch (e) {
|
|
105
|
+
n ??= e;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
r.handle.el.remove();
|
|
109
|
+
} catch (e) {
|
|
110
|
+
n ??= e;
|
|
111
|
+
}
|
|
112
|
+
e.items.get(r.state.itemId) === r && e.items.delete(r.state.itemId);
|
|
113
|
+
}
|
|
114
|
+
throw n;
|
|
115
|
+
};
|
|
116
|
+
try {
|
|
117
|
+
for (let t of n) {
|
|
118
|
+
let n = r(t), i = e.items.get(n);
|
|
119
|
+
if (u ? u.has(n) : i !== void 0) throw Error("reconcileList: duplicate key " + String(n) + " in list " + e.listId);
|
|
120
|
+
if (u?.add(n), i) {
|
|
121
|
+
if (o) o(i.handle, t);
|
|
122
|
+
else if (i.handle.update) i.handle.update(t);
|
|
123
|
+
else throw Error("reconcileList: no updater for item " + String(n) + " in list " + e.listId);
|
|
124
|
+
} else {
|
|
125
|
+
let r = {
|
|
126
|
+
listId: e.listId,
|
|
127
|
+
itemId: n,
|
|
128
|
+
bindings: /* @__PURE__ */ new Map()
|
|
129
|
+
};
|
|
130
|
+
i = {
|
|
131
|
+
state: r,
|
|
132
|
+
handle: a(t, r)
|
|
133
|
+
}, e.items.set(n, i), f.push(i);
|
|
134
|
+
}
|
|
135
|
+
d.push(i);
|
|
136
|
+
}
|
|
137
|
+
} catch (e) {
|
|
138
|
+
p(e);
|
|
139
|
+
}
|
|
140
|
+
let m, h = c ? [] : [...e.items].filter(([e]) => !u.has(e));
|
|
141
|
+
for (let t = h.length - 1; t >= 0; t--) {
|
|
142
|
+
let [n, r] = h[t];
|
|
143
|
+
try {
|
|
144
|
+
r.handle.destroy?.();
|
|
145
|
+
} catch (e) {
|
|
146
|
+
m ??= e;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
r.handle.el.remove();
|
|
150
|
+
} catch (e) {
|
|
151
|
+
m ??= e;
|
|
152
|
+
}
|
|
153
|
+
e.items.delete(n);
|
|
154
|
+
}
|
|
155
|
+
let g = null, _;
|
|
156
|
+
if (t && (g = l(t) ? t.start.parentNode : t, g)) {
|
|
157
|
+
let e = l(t) ? t.end : null;
|
|
158
|
+
try {
|
|
159
|
+
i(g, e, d, c && f.length > 0);
|
|
160
|
+
} catch (e) {
|
|
161
|
+
m ??= e, _ ??= e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (_ && f.length > 0 && p(m ?? _), s) {
|
|
165
|
+
g || f.length > 0 && p(m ?? /* @__PURE__ */ Error("reconcileList: range is detached"));
|
|
166
|
+
for (let t of f) if (e.items.has(t.state.itemId) && t.handle.el.parentNode === g) try {
|
|
167
|
+
t.handle.mount?.();
|
|
168
|
+
} catch (e) {
|
|
169
|
+
p(m ?? e);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
if (m) throw m;
|
|
173
|
+
}
|
|
174
|
+
function s(e) {
|
|
175
|
+
try {
|
|
176
|
+
for (let t of e.items.values()) t.handle.mount?.();
|
|
177
|
+
} catch (t) {
|
|
178
|
+
let n = t;
|
|
179
|
+
try {
|
|
180
|
+
c(e);
|
|
181
|
+
} catch (e) {
|
|
182
|
+
n ??= e;
|
|
183
|
+
}
|
|
184
|
+
throw n;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function c(e) {
|
|
188
|
+
let t, n = [...e.items.values()];
|
|
189
|
+
for (let e = n.length - 1; e >= 0; e--) {
|
|
190
|
+
let r = n[e];
|
|
191
|
+
try {
|
|
192
|
+
r.handle.destroy?.();
|
|
193
|
+
} catch (e) {
|
|
194
|
+
t ??= e;
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
r.handle.el.remove();
|
|
198
|
+
} catch (e) {
|
|
199
|
+
t ??= e;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (e.items.clear(), t) throw t;
|
|
203
|
+
}
|
|
204
|
+
function l(e) {
|
|
205
|
+
return !("nodeType" in e);
|
|
206
|
+
}
|
|
207
|
+
var u = /* @__PURE__ */ new Map();
|
|
208
|
+
function d(e, t) {
|
|
209
|
+
let n = e;
|
|
210
|
+
function r(...e) {
|
|
211
|
+
if (e.length === 0) return n;
|
|
212
|
+
let t = e[0];
|
|
213
|
+
return n = typeof t == "function" ? t(n) : t, n;
|
|
214
|
+
}
|
|
215
|
+
return t && u.set(t, { kind: "signal" }), r;
|
|
216
|
+
}
|
|
217
|
+
function f(e) {
|
|
218
|
+
let t = e, n = /* @__PURE__ */ new Set(), r = ((...e) => {
|
|
219
|
+
if (e.length === 0) return t;
|
|
220
|
+
let r = e[0];
|
|
221
|
+
t = typeof r == "function" ? r(t) : r;
|
|
222
|
+
for (let e of Array.from(n)) e();
|
|
223
|
+
return t;
|
|
224
|
+
});
|
|
225
|
+
return r.subscribe = (e) => {
|
|
226
|
+
n.add(e);
|
|
227
|
+
let t = !0;
|
|
228
|
+
return () => {
|
|
229
|
+
t && (t = !1, n.delete(e));
|
|
230
|
+
};
|
|
231
|
+
}, r;
|
|
232
|
+
}
|
|
233
|
+
function p(e, t) {
|
|
234
|
+
return t && u.set(t, { kind: "derived" }), e;
|
|
235
|
+
}
|
|
236
|
+
function m(e, t) {
|
|
237
|
+
let n = /* @__PURE__ */ new Map();
|
|
238
|
+
if (v(e, n), t) {
|
|
239
|
+
let e = t.filter((e) => !n.has(e));
|
|
240
|
+
if (e.length > 0) throw Error(`hydrate: missing marker(s): ${e.join(", ")} — initial HTML does not match compiled output`);
|
|
241
|
+
}
|
|
242
|
+
return { markers: n };
|
|
243
|
+
}
|
|
244
|
+
function h(e, t, n) {
|
|
245
|
+
return e.innerHTML = t, m(e, n);
|
|
246
|
+
}
|
|
247
|
+
function g(e, t, n) {
|
|
248
|
+
let { markers: r } = m(e, t), i = /* @__PURE__ */ new Map();
|
|
249
|
+
if (n && y(e, i), n) {
|
|
250
|
+
let e = n.filter((e) => !i.has(e));
|
|
251
|
+
if (e.length > 0) throw Error(`hydrate: missing range anchor(s): ${e.join(", ")} — initial HTML does not match compiled output`);
|
|
252
|
+
}
|
|
253
|
+
return {
|
|
254
|
+
markers: r,
|
|
255
|
+
ranges: i
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function _(e, t, n, r) {
|
|
259
|
+
return e.innerHTML = t, g(e, n, r);
|
|
260
|
+
}
|
|
261
|
+
function v(e, t) {
|
|
262
|
+
let n = e.getAttribute("data-iris-id");
|
|
263
|
+
n && t.set(n, e);
|
|
264
|
+
for (let n of e.children) v(n, t);
|
|
265
|
+
}
|
|
266
|
+
function y(e, t) {
|
|
267
|
+
let n = /* @__PURE__ */ new Map(), r = (e) => {
|
|
268
|
+
for (let i = e.firstChild; i; i = i.nextSibling) {
|
|
269
|
+
if (i.nodeType === 8) {
|
|
270
|
+
let e = i.data;
|
|
271
|
+
if (e.startsWith("irisout:start:")) n.set(e.slice(14), i);
|
|
272
|
+
else if (e.startsWith("irisout:end:")) {
|
|
273
|
+
let r = e.slice(12), a = n.get(r);
|
|
274
|
+
a && a.parentNode === i.parentNode && t.set(r, {
|
|
275
|
+
start: a,
|
|
276
|
+
end: i
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
r(i);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
r(e);
|
|
284
|
+
}
|
|
285
|
+
//#endregion
|
|
286
|
+
export { t as createListRuntime, p as derived, c as destroyListRuntime, m as hydrate, g as hydrateWithRanges, h as mount, s as mountListRuntime, _ as mountWithRanges, e as normalizeUseActionResult, a as reconcileList, o as reconcileListWithLifecycle, u as registry, f as sharedSignal, d as signal, n as updateListBinding, r as updateListItem };
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region packages/compiler/src/compiler/state.ts
|
|
2
|
+
var e = (e) => e, t = (e) => e, n = (e) => e;
|
|
3
|
+
function r(e, t = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set()) {
|
|
4
|
+
return {
|
|
5
|
+
source: e,
|
|
6
|
+
supportNames: n,
|
|
7
|
+
transformedNodes: t,
|
|
8
|
+
declIdByKey: /* @__PURE__ */ new Map(),
|
|
9
|
+
declKind: /* @__PURE__ */ new Map(),
|
|
10
|
+
declOutputName: /* @__PURE__ */ new Map(),
|
|
11
|
+
derivedDeps: /* @__PURE__ */ new Map(),
|
|
12
|
+
derivedRecompute: /* @__PURE__ */ new Map(),
|
|
13
|
+
collectionKeyRendered: /* @__PURE__ */ new Map(),
|
|
14
|
+
usedOutputNames: /* @__PURE__ */ new Set(),
|
|
15
|
+
markers: [],
|
|
16
|
+
markerDeps: /* @__PURE__ */ new Map(),
|
|
17
|
+
handlers: [],
|
|
18
|
+
actions: [],
|
|
19
|
+
mounts: [],
|
|
20
|
+
effects: [],
|
|
21
|
+
contexts: /* @__PURE__ */ new Map(),
|
|
22
|
+
contextIdByKey: /* @__PURE__ */ new Map(),
|
|
23
|
+
contextValues: /* @__PURE__ */ new Map(),
|
|
24
|
+
attrBindings: [],
|
|
25
|
+
markerCounter: 0,
|
|
26
|
+
instanceCounter: 0,
|
|
27
|
+
movementFns: /* @__PURE__ */ new Map(),
|
|
28
|
+
trackedFns: /* @__PURE__ */ new Map(),
|
|
29
|
+
localDeclIds: /* @__PURE__ */ new Set(),
|
|
30
|
+
sharedDecls: [],
|
|
31
|
+
sharedDeclIdByBindingKey: /* @__PURE__ */ new Map(),
|
|
32
|
+
sharedDeclIds: /* @__PURE__ */ new Set(),
|
|
33
|
+
usedSharedDeclIds: /* @__PURE__ */ new Set()
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var i = (e, t, n) => `${e}:${t}:${n}`;
|
|
37
|
+
function a(e) {
|
|
38
|
+
return t(`m${e.markerCounter++}`);
|
|
39
|
+
}
|
|
40
|
+
function o(e, t, n) {
|
|
41
|
+
let r = t, i = 1;
|
|
42
|
+
for (; e.usedOutputNames.has(r);) r = `${t}$${i++}`;
|
|
43
|
+
return e.usedOutputNames.add(r), e.declOutputName.set(n, r), r;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { o as assignOutputName, r as createCompilerState, i as declKey, a as nextMarkerId, n as toContextId, e as toDeclId, t as toMarkerId };
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Plugin } from 'vite-plus';
|
|
2
|
+
export interface IrisoutPluginOptions {
|
|
3
|
+
/** Viteのrootから解決する入口。絶対pathも受け付ける。 */
|
|
4
|
+
entry: string;
|
|
5
|
+
/** 初期HTMLを埋め込む場所とhydrate対象を示すCSS selector。 */
|
|
6
|
+
container?: string;
|
|
7
|
+
/** index.html内で初期HTMLを置き換える文字列。 */
|
|
8
|
+
htmlMarker?: string;
|
|
9
|
+
/** main.jsからimportする仮想module名。 */
|
|
10
|
+
virtualModuleId?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* authored JSXをcompileProject()で生成し、Viteの標準module graphへ渡す連携。
|
|
14
|
+
* compilerの実行はビルド時と入口・依存のHMR時だけで、ブラウザへはhydrate用の
|
|
15
|
+
* 生成moduleと初期HTMLを渡す。
|
|
16
|
+
*/
|
|
17
|
+
export declare function irisout(options: IrisoutPluginOptions): Plugin;
|
|
18
|
+
export default irisout;
|
package/dist/vite.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import e from "node:path";
|
|
2
|
+
import { compileProject as t } from "./index.js";
|
|
3
|
+
//#region packages/vite-plugin/src/index.ts
|
|
4
|
+
var n = "virtual:irisout-entry", r = "<!--irisout-html-->", i = "#app";
|
|
5
|
+
function a(t) {
|
|
6
|
+
return e.normalize(e.resolve(t));
|
|
7
|
+
}
|
|
8
|
+
function o(o) {
|
|
9
|
+
let s = o.virtualModuleId ?? n, c = o.htmlMarker ?? r, l = o.container ?? i, u = process.cwd(), d = a(e.resolve(u, o.entry)), f = e.join(u, `.irisout-${encodeURIComponent(s)}.js`), p = null, m = /* @__PURE__ */ new Set(), h = () => {
|
|
10
|
+
let e = t(d);
|
|
11
|
+
return p = e, m = new Set(e.dependencies.map(a)), e;
|
|
12
|
+
}, g = () => p ?? h(), _ = (e) => {
|
|
13
|
+
for (let t of m) e(t);
|
|
14
|
+
}, v = () => {
|
|
15
|
+
if (l === "#app") return "hydrateComponent(document.getElementById('app'));";
|
|
16
|
+
let e = JSON.stringify(l), t = JSON.stringify(`irisout hydrate container not found: ${l}`);
|
|
17
|
+
return [
|
|
18
|
+
`const __irisout_container__ = document.querySelector(${e});`,
|
|
19
|
+
`if (!__irisout_container__) throw new Error(${t});`,
|
|
20
|
+
"hydrateComponent(__irisout_container__);"
|
|
21
|
+
].join("\n");
|
|
22
|
+
};
|
|
23
|
+
return {
|
|
24
|
+
name: "irisout",
|
|
25
|
+
configResolved(t) {
|
|
26
|
+
u = t.root, d = a(e.resolve(u, o.entry)), f = e.join(u, `.irisout-${encodeURIComponent(s)}.js`), p = null, m = /* @__PURE__ */ new Set();
|
|
27
|
+
},
|
|
28
|
+
buildStart() {
|
|
29
|
+
h(), _((e) => this.addWatchFile(e));
|
|
30
|
+
},
|
|
31
|
+
configureServer(e) {
|
|
32
|
+
let t = g();
|
|
33
|
+
e.watcher.add([...t.dependencies]);
|
|
34
|
+
},
|
|
35
|
+
resolveId(e) {
|
|
36
|
+
return e === s ? f : null;
|
|
37
|
+
},
|
|
38
|
+
load(e) {
|
|
39
|
+
if (e !== f) return null;
|
|
40
|
+
let t = g();
|
|
41
|
+
return {
|
|
42
|
+
code: `${t.code}\n${v()}`,
|
|
43
|
+
map: t.map
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
transformIndexHtml(e) {
|
|
47
|
+
return e.includes(c) ? e.replaceAll(c, g().initialHtml) : e;
|
|
48
|
+
},
|
|
49
|
+
async handleHotUpdate(e) {
|
|
50
|
+
let t = a(e.file);
|
|
51
|
+
if (m.size === 0 && g(), !m.has(t)) return;
|
|
52
|
+
let n = p;
|
|
53
|
+
try {
|
|
54
|
+
let t = h();
|
|
55
|
+
e.server.watcher.add([...t.dependencies]);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
throw p = n, e;
|
|
58
|
+
}
|
|
59
|
+
return e.server.ws.send({
|
|
60
|
+
type: "full-reload",
|
|
61
|
+
path: "*"
|
|
62
|
+
}), [];
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { o as default, o as irisout };
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "irisout",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist",
|
|
7
|
+
"README.md",
|
|
8
|
+
"CHANGELOG.md"
|
|
9
|
+
],
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./vite": {
|
|
17
|
+
"types": "./dist/vite.d.ts",
|
|
18
|
+
"import": "./dist/vite.js"
|
|
19
|
+
},
|
|
20
|
+
"./runtime": {
|
|
21
|
+
"types": "./dist/runtime.d.ts",
|
|
22
|
+
"import": "./dist/runtime.js"
|
|
23
|
+
},
|
|
24
|
+
"./diagnostics": {
|
|
25
|
+
"types": "./dist/diagnostics.d.ts",
|
|
26
|
+
"import": "./dist/diagnostics.js"
|
|
27
|
+
},
|
|
28
|
+
"./state": {
|
|
29
|
+
"types": "./dist/compiler/state.d.ts",
|
|
30
|
+
"import": "./dist/state.js"
|
|
31
|
+
},
|
|
32
|
+
"./jsx": "./dist/jsx.d.ts"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"vite-plus": ">=0.3.0"
|
|
36
|
+
}
|
|
37
|
+
}
|