@alloy-js/core 0.4.0 → 0.6.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.
- package/CHANGELOG.md +53 -0
- package/babel.config.cjs +4 -1
- package/dist/src/binder.d.ts +20 -13
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +33 -15
- package/dist/src/binder.js.map +1 -1
- package/dist/src/code.d.ts +2 -2
- package/dist/src/code.d.ts.map +1 -1
- package/dist/src/code.js +4 -4
- package/dist/src/code.js.map +1 -1
- package/dist/src/components/Block.d.ts +25 -0
- package/dist/src/components/Block.d.ts.map +1 -0
- package/dist/src/components/Block.js +25 -0
- package/dist/src/components/Block.js.map +1 -0
- package/dist/src/components/Declaration.d.ts +1 -1
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +4 -0
- package/dist/src/components/Declaration.js.map +1 -1
- package/dist/src/components/For.d.ts +44 -0
- package/dist/src/components/For.d.ts.map +1 -0
- package/dist/src/components/For.js +41 -0
- package/dist/src/components/For.js.map +1 -0
- package/dist/src/components/Indent.d.ts +6 -10
- package/dist/src/components/Indent.d.ts.map +1 -1
- package/dist/src/components/Indent.js +7 -18
- package/dist/src/components/Indent.js.map +1 -1
- package/dist/src/components/List.d.ts +38 -0
- package/dist/src/components/List.d.ts.map +1 -0
- package/dist/src/components/List.js +40 -0
- package/dist/src/components/List.js.map +1 -0
- package/dist/src/components/MemberDeclaration.d.ts +1 -1
- package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
- package/dist/src/components/MemberDeclaration.js.map +1 -1
- package/dist/src/components/MemberName.d.ts +1 -1
- package/dist/src/components/MemberName.d.ts.map +1 -1
- package/dist/src/components/MemberName.js +1 -1
- package/dist/src/components/MemberName.js.map +1 -1
- package/dist/src/components/MemberScope.d.ts +1 -1
- package/dist/src/components/MemberScope.d.ts.map +1 -1
- package/dist/src/components/MemberScope.js.map +1 -1
- package/dist/src/components/Name.d.ts +1 -1
- package/dist/src/components/Name.d.ts.map +1 -1
- package/dist/src/components/Name.js +1 -1
- package/dist/src/components/Name.js.map +1 -1
- package/dist/src/components/Output.d.ts +3 -2
- package/dist/src/components/Output.d.ts.map +1 -1
- package/dist/src/components/Output.js +12 -2
- package/dist/src/components/Output.js.map +1 -1
- package/dist/src/components/Scope.d.ts +1 -1
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js.map +1 -1
- package/dist/src/components/Show.d.ts +8 -0
- package/dist/src/components/Show.d.ts.map +1 -0
- package/dist/src/components/Show.js +4 -0
- package/dist/src/components/Show.js.map +1 -0
- package/dist/src/components/SourceDirectory.d.ts +2 -2
- package/dist/src/components/SourceDirectory.d.ts.map +1 -1
- package/dist/src/components/SourceDirectory.js +1 -0
- package/dist/src/components/SourceDirectory.js.map +1 -1
- package/dist/src/components/SourceFile.d.ts +4 -8
- package/dist/src/components/SourceFile.d.ts.map +1 -1
- package/dist/src/components/SourceFile.js +6 -13
- package/dist/src/components/SourceFile.js.map +1 -1
- package/dist/src/components/StatementList.d.ts +9 -0
- package/dist/src/components/StatementList.d.ts.map +1 -0
- package/dist/src/components/StatementList.js +17 -0
- package/dist/src/components/StatementList.js.map +1 -0
- package/dist/src/components/Switch.d.ts +41 -0
- package/dist/src/components/Switch.d.ts.map +1 -0
- package/dist/src/components/Switch.js +41 -0
- package/dist/src/components/Switch.js.map +1 -0
- package/dist/src/components/Wrap.d.ts +20 -0
- package/dist/src/components/Wrap.d.ts.map +1 -0
- package/dist/src/components/Wrap.js +15 -0
- package/dist/src/components/Wrap.js.map +1 -0
- package/dist/src/components/index.d.ts +8 -1
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +7 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/components/stc/index.d.ts +89 -18
- package/dist/src/components/stc/index.d.ts.map +1 -1
- package/dist/src/components/stc/index.js +17 -1
- package/dist/src/components/stc/index.js.map +1 -1
- package/dist/src/context/index.d.ts +0 -1
- package/dist/src/context/index.d.ts.map +1 -1
- package/dist/src/context/index.js +0 -1
- package/dist/src/context/index.js.map +1 -1
- package/dist/src/context/member-declaration.d.ts +1 -0
- package/dist/src/context/member-declaration.d.ts.map +1 -1
- package/dist/src/context/member-declaration.js +4 -1
- package/dist/src/context/member-declaration.js.map +1 -1
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +3 -3
- package/dist/src/context.js.map +1 -1
- package/dist/src/index.browser.d.ts +3 -0
- package/dist/src/index.browser.d.ts.map +1 -0
- package/dist/src/index.browser.js +3 -0
- package/dist/src/index.browser.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/jsx-runtime.d.ts +151 -7
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +113 -12
- package/dist/src/jsx-runtime.js.map +1 -1
- package/dist/src/render.d.ts +107 -132
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +272 -178
- package/dist/src/render.js.map +1 -1
- package/dist/src/stc.d.ts +14 -0
- package/dist/src/stc.d.ts.map +1 -0
- package/dist/src/stc.js +52 -0
- package/dist/src/stc.js.map +1 -0
- package/dist/src/tap.d.ts +19 -0
- package/dist/src/tap.d.ts.map +1 -0
- package/dist/src/tap.js +39 -0
- package/dist/src/tap.js.map +1 -0
- package/dist/src/utils.d.ts +22 -15
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +95 -59
- package/dist/src/utils.js.map +1 -1
- package/dist/test/browser-build.test.d.ts +2 -0
- package/dist/test/browser-build.test.d.ts.map +1 -0
- package/dist/test/components/block.test.d.ts +2 -0
- package/dist/test/components/block.test.d.ts.map +1 -0
- package/dist/test/components/declaration.test.d.ts +2 -0
- package/dist/test/components/declaration.test.d.ts.map +1 -0
- package/dist/test/components/list.test.d.ts +2 -0
- package/dist/test/components/list.test.d.ts.map +1 -0
- package/dist/test/components/wrap.test.d.ts +2 -0
- package/dist/test/components/wrap.test.d.ts.map +1 -0
- package/dist/test/control-flow/for.test.d.ts +2 -0
- package/dist/test/control-flow/for.test.d.ts.map +1 -0
- package/dist/test/control-flow/match.test.d.ts +2 -0
- package/dist/test/control-flow/match.test.d.ts.map +1 -0
- package/dist/test/control-flow/show.test.d.ts +2 -0
- package/dist/test/control-flow/show.test.d.ts.map +1 -0
- package/dist/test/reactivity/cleanup.test.d.ts +2 -0
- package/dist/test/reactivity/cleanup.test.d.ts.map +1 -0
- package/dist/test/reactivity/memo.test.d.ts +2 -0
- package/dist/test/reactivity/memo.test.d.ts.map +1 -0
- package/dist/test/reactivity/untrack.test.d.ts +2 -0
- package/dist/test/reactivity/untrack.test.d.ts.map +1 -0
- package/dist/test/rendering/formatting.test.d.ts +2 -0
- package/dist/test/rendering/formatting.test.d.ts.map +1 -0
- package/dist/test/rendering/memoization.test.d.ts +2 -0
- package/dist/test/rendering/memoization.test.d.ts.map +1 -0
- package/dist/test/split-props.test.d.ts +2 -0
- package/dist/test/split-props.test.d.ts.map +1 -0
- package/dist/test/stc.test.d.ts.map +1 -1
- package/dist/test/utils.test.d.ts.map +1 -1
- package/dist/testing/extend-expect.js +4 -4
- package/dist/testing/extend-expect.js.map +1 -1
- package/dist/testing/render.d.ts +2 -3
- package/dist/testing/render.d.ts.map +1 -1
- package/dist/testing/render.js +2 -4
- package/dist/testing/render.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -9
- package/src/binder.ts +60 -50
- package/src/code.ts +17 -12
- package/src/components/Block.tsx +44 -0
- package/src/components/Declaration.tsx +10 -4
- package/src/components/For.tsx +81 -0
- package/src/components/Indent.tsx +20 -27
- package/src/components/List.tsx +94 -0
- package/src/components/MemberDeclaration.tsx +9 -6
- package/src/components/MemberScope.tsx +4 -2
- package/src/components/Output.tsx +27 -14
- package/src/components/Scope.tsx +4 -2
- package/src/components/Show.tsx +11 -0
- package/src/components/SourceDirectory.tsx +6 -2
- package/src/components/SourceFile.tsx +13 -17
- package/src/components/StatementList.tsx +16 -0
- package/src/components/Switch.tsx +62 -0
- package/src/components/Wrap.tsx +29 -0
- package/src/components/index.tsx +8 -1
- package/src/components/stc/index.ts +18 -1
- package/src/context/index.ts +0 -1
- package/src/context/member-declaration.ts +9 -1
- package/src/context.ts +2 -3
- package/src/index.browser.ts +2 -0
- package/src/index.ts +2 -0
- package/src/jsx-runtime.ts +265 -23
- package/src/render.ts +382 -200
- package/src/stc.ts +95 -0
- package/src/tap.ts +69 -0
- package/src/utils.ts +162 -95
- package/temp/api.json +8042 -1886
- package/test/browser-build.test.ts +91 -0
- package/test/children.test.tsx +8 -10
- package/test/components/block.test.tsx +48 -0
- package/test/components/declaration.test.tsx +37 -0
- package/test/components/list.test.tsx +91 -0
- package/test/components/slot.test.tsx +31 -25
- package/test/components/source-file.test.tsx +11 -31
- package/test/components/wrap.test.tsx +42 -0
- package/test/control-flow/for.test.tsx +194 -0
- package/test/control-flow/match.test.tsx +49 -0
- package/test/control-flow/show.test.tsx +25 -0
- package/test/name-policy.test.tsx +5 -5
- package/test/reactivity/cleanup.test.tsx +91 -0
- package/test/reactivity/memo.test.tsx +17 -0
- package/test/reactivity/ref-rendering.test.tsx +3 -8
- package/test/reactivity/test.test.tsx +7 -6
- package/test/reactivity/untrack.test.ts +33 -0
- package/test/rendering/basic.test.tsx +25 -47
- package/test/rendering/code.test.tsx +3 -3
- package/test/rendering/formatting.test.tsx +487 -0
- package/test/rendering/indent.test.tsx +42 -529
- package/test/rendering/memoization.test.tsx +30 -0
- package/test/split-props.test.ts +87 -0
- package/test/stc.test.tsx +29 -8
- package/test/symbols.test.ts +132 -3
- package/test/utils.test.tsx +129 -20
- package/testing/extend-expect.ts +14 -4
- package/testing/render.ts +2 -4
- package/testing/vitest.d.ts +6 -1
- package/vitest.config.ts +1 -1
- package/dist/src/context/indent.d.ts +0 -5
- package/dist/src/context/indent.d.ts.map +0 -1
- package/dist/src/context/indent.js +0 -8
- package/dist/src/context/indent.js.map +0 -1
- package/dist/test/rendering/linebreaks.test.d.ts +0 -2
- package/dist/test/rendering/linebreaks.test.d.ts.map +0 -1
- package/src/context/indent.ts +0 -17
- package/test/rendering/linebreaks.test.tsx +0 -72
package/package.json
CHANGED
|
@@ -1,27 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alloy-js/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./dist/src/index.js",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
8
|
-
"
|
|
8
|
+
"browser": "./dist/src/index.browser.js",
|
|
9
9
|
"import": "./dist/src/index.js"
|
|
10
10
|
},
|
|
11
11
|
"./jsx-runtime": {
|
|
12
|
-
"
|
|
12
|
+
"types": "./dist/src/jsx-runtime.d.ts",
|
|
13
13
|
"import": "./dist/src/jsx-runtime.js"
|
|
14
14
|
},
|
|
15
15
|
"./testing": {
|
|
16
|
-
"development": "./testing/index.ts",
|
|
17
16
|
"import": "./dist/testing/index.js"
|
|
18
17
|
},
|
|
19
18
|
"./stc": {
|
|
20
|
-
"development": "./src/components/stc/index.ts",
|
|
21
19
|
"import": "./dist/src/components/stc/index.js"
|
|
22
20
|
},
|
|
23
21
|
"./components": {
|
|
24
|
-
"development": "./src/components/index.ts",
|
|
25
22
|
"import": "./dist/src/components/index.js"
|
|
26
23
|
}
|
|
27
24
|
},
|
|
@@ -39,7 +36,8 @@
|
|
|
39
36
|
"chalk": "^5.3.0",
|
|
40
37
|
"cli-table3": "^0.6.5",
|
|
41
38
|
"pathe": "^1.1.2",
|
|
42
|
-
"
|
|
39
|
+
"prettier": "^3.5.1",
|
|
40
|
+
"@alloy-js/babel-preset": "~0.2.0"
|
|
43
41
|
},
|
|
44
42
|
"devDependencies": {
|
|
45
43
|
"@babel/cli": "^7.24.7",
|
|
@@ -47,8 +45,9 @@
|
|
|
47
45
|
"@rollup/plugin-babel": "^6.0.4",
|
|
48
46
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
49
47
|
"concurrently": "^8.2.2",
|
|
50
|
-
"typescript": "^5.
|
|
51
|
-
"vitest": "^3.0.4"
|
|
48
|
+
"typescript": "^5.7.3",
|
|
49
|
+
"vitest": "^3.0.4",
|
|
50
|
+
"vite": "^6.0.1"
|
|
52
51
|
},
|
|
53
52
|
"type": "module",
|
|
54
53
|
"scripts": {
|
package/src/binder.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ShallowRef,
|
|
8
8
|
shallowRef,
|
|
9
9
|
} from "@vue/reactivity";
|
|
10
|
+
import { useBinder } from "./context/binder.js";
|
|
10
11
|
import { useMemberScope } from "./context/member-scope.js";
|
|
11
12
|
import { useScope } from "./context/scope.js";
|
|
12
13
|
import { memo, untrack } from "./jsx-runtime.js";
|
|
@@ -223,6 +224,21 @@ export interface OutputScope {
|
|
|
223
224
|
getSymbolNames(): Set<string>;
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
export type CreateSymbolOptions<T extends OutputSymbol = OutputSymbol> = {
|
|
228
|
+
name: string;
|
|
229
|
+
scope?: OutputScope;
|
|
230
|
+
refkey?: Refkey;
|
|
231
|
+
flags?: OutputSymbolFlags;
|
|
232
|
+
} & Omit<T, keyof OutputSymbol>;
|
|
233
|
+
|
|
234
|
+
export type CreateScopeOptions<T extends OutputScope = OutputScope> = {
|
|
235
|
+
kind: T["kind"];
|
|
236
|
+
name: string;
|
|
237
|
+
parent?: OutputScope | undefined;
|
|
238
|
+
flags?: OutputScopeFlags;
|
|
239
|
+
owner?: OutputSymbol;
|
|
240
|
+
} & Omit<T, keyof OutputScope>;
|
|
241
|
+
|
|
226
242
|
/**
|
|
227
243
|
* The binder tracks all output scopes and symbols. Scopes are nested containers
|
|
228
244
|
* for symbols.
|
|
@@ -241,28 +257,19 @@ export interface Binder {
|
|
|
241
257
|
* Create a new scope. The scope will be added to the parent scope's children.
|
|
242
258
|
* The returned scope object is reactive.
|
|
243
259
|
*/
|
|
244
|
-
createScope<T extends OutputScope>(
|
|
245
|
-
args: {
|
|
246
|
-
kind: T["kind"];
|
|
247
|
-
name: string;
|
|
248
|
-
parent?: OutputScope | undefined;
|
|
249
|
-
flags?: OutputScopeFlags;
|
|
250
|
-
owner?: OutputSymbol;
|
|
251
|
-
} & Omit<T, keyof OutputScope>,
|
|
252
|
-
): T;
|
|
260
|
+
createScope<T extends OutputScope>(args: CreateScopeOptions<T>): T;
|
|
253
261
|
|
|
254
262
|
/**
|
|
255
263
|
* Create a new symbol. The symbol will be added to the parent scope's symbols.
|
|
256
264
|
* The returned symbol object is reactive.
|
|
257
265
|
*/
|
|
258
|
-
createSymbol<T extends OutputSymbol>(
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
): T;
|
|
266
|
+
createSymbol<T extends OutputSymbol>(args: CreateSymbolOptions<T>): T;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Delete the given symbol. The symbol will be removed from its parent's
|
|
270
|
+
* scope. Any resolutions to this symbol will become undefined.
|
|
271
|
+
*/
|
|
272
|
+
deleteSymbol(symbol: OutputSymbol): void;
|
|
266
273
|
|
|
267
274
|
/**
|
|
268
275
|
* Instantiate the static members of a symbol into the instance members of
|
|
@@ -414,6 +421,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
414
421
|
const binder: Binder = {
|
|
415
422
|
createScope,
|
|
416
423
|
createSymbol,
|
|
424
|
+
deleteSymbol,
|
|
417
425
|
resolveDeclarationByKey,
|
|
418
426
|
addStaticMembersToSymbol,
|
|
419
427
|
addInstanceMembersToSymbol,
|
|
@@ -451,15 +459,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
451
459
|
|
|
452
460
|
return binder;
|
|
453
461
|
|
|
454
|
-
function createScope<T extends OutputScope>(
|
|
455
|
-
args: {
|
|
456
|
-
kind: string;
|
|
457
|
-
name: string;
|
|
458
|
-
parent?: OutputScope;
|
|
459
|
-
flags?: OutputScopeFlags;
|
|
460
|
-
owner?: OutputSymbol;
|
|
461
|
-
} & Omit<T, keyof OutputScope>,
|
|
462
|
-
): T {
|
|
462
|
+
function createScope<T extends OutputScope>(args: CreateScopeOptions<T>): T {
|
|
463
463
|
const {
|
|
464
464
|
kind,
|
|
465
465
|
name,
|
|
@@ -518,12 +518,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
function createSymbol<T extends OutputSymbol>(
|
|
521
|
-
args:
|
|
522
|
-
name: string;
|
|
523
|
-
scope?: OutputScope;
|
|
524
|
-
refkey?: Refkey;
|
|
525
|
-
flags?: OutputSymbolFlags;
|
|
526
|
-
} & Omit<T, keyof OutputSymbol>,
|
|
521
|
+
args: CreateSymbolOptions<T>,
|
|
527
522
|
): T {
|
|
528
523
|
const {
|
|
529
524
|
name,
|
|
@@ -591,11 +586,23 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
591
586
|
scope.symbolsByRefkey.set(symbol.refkey, symbol);
|
|
592
587
|
|
|
593
588
|
deconflict(symbol);
|
|
594
|
-
notifyRefkey(
|
|
589
|
+
notifyRefkey(symbol);
|
|
595
590
|
|
|
596
591
|
return symbol;
|
|
597
592
|
}
|
|
598
593
|
|
|
594
|
+
function deleteSymbol(symbol: OutputSymbol) {
|
|
595
|
+
symbol.scope.symbols.delete(symbol);
|
|
596
|
+
|
|
597
|
+
if (!refkey) {
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
const resolution = waitingDeclarations.get(symbol.refkey);
|
|
602
|
+
if (!resolution) return;
|
|
603
|
+
resolution.value = undefined;
|
|
604
|
+
}
|
|
605
|
+
|
|
599
606
|
function instantiateSymbolInto(source: OutputSymbol, target: OutputSymbol) {
|
|
600
607
|
if (~source.flags & OutputSymbolFlags.InstanceMemberContainer) {
|
|
601
608
|
throw new Error("Can only instantiate symbols with instance members");
|
|
@@ -807,24 +814,27 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
807
814
|
return computed(() => cb(declSignal.value));
|
|
808
815
|
}
|
|
809
816
|
|
|
810
|
-
function notifyRefkey(
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
817
|
+
function notifyRefkey(symbol: OutputSymbol): void {
|
|
818
|
+
effect(() => {
|
|
819
|
+
const refkey = symbol.refkey;
|
|
820
|
+
if (!refkey) return;
|
|
821
|
+
|
|
822
|
+
// notify those waiting for this refkey
|
|
823
|
+
knownDeclarations.set(refkey, symbol);
|
|
824
|
+
if (waitingDeclarations.has(refkey)) {
|
|
825
|
+
const signal = waitingDeclarations.get(refkey)!;
|
|
826
|
+
signal.value = symbol;
|
|
827
|
+
}
|
|
820
828
|
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
waitingName
|
|
829
|
+
// notify those waiting for this symbol name
|
|
830
|
+
const waitingScope = waitingSymbolNames.get(symbol.scope);
|
|
831
|
+
if (waitingScope) {
|
|
832
|
+
const waitingName = waitingScope.get(symbol.name);
|
|
833
|
+
if (waitingName) {
|
|
834
|
+
waitingName.value = symbol;
|
|
835
|
+
}
|
|
826
836
|
}
|
|
827
|
-
}
|
|
837
|
+
});
|
|
828
838
|
}
|
|
829
839
|
|
|
830
840
|
function findSymbolName<TSymbol extends OutputSymbol = OutputSymbol>(
|
|
@@ -949,7 +959,7 @@ export function resolve<
|
|
|
949
959
|
TScope extends OutputScope,
|
|
950
960
|
TSymbol extends OutputSymbol,
|
|
951
961
|
>(refkey: Refkey): Ref<ResolutionResult<TScope, TSymbol>> {
|
|
952
|
-
const scope = useScope();
|
|
962
|
+
const scope = useScope() ?? useBinder().globalScope;
|
|
953
963
|
const memberScope = useMemberScope();
|
|
954
964
|
const binder = scope.binder;
|
|
955
965
|
|
package/src/code.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// this code is split into a tokenizer and a parser of sorts because I feel like
|
|
2
2
|
// it should be psosible to share logic between this and the babel transform, but
|
|
3
3
|
// this is an exercise for the future.
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import { hbr, indent } from "./components/stc/index.js";
|
|
5
|
+
import { Child, Children } from "./jsx-runtime.js";
|
|
6
6
|
interface IndentLevelData {
|
|
7
7
|
kind: "indent";
|
|
8
|
-
children: (string |
|
|
8
|
+
children: (string | Children | IndentLevelData)[];
|
|
9
9
|
pendingLines: string[];
|
|
10
10
|
}
|
|
11
11
|
export function code(
|
|
12
12
|
template: TemplateStringsArray,
|
|
13
|
-
...substitutions:
|
|
13
|
+
...substitutions: Children[]
|
|
14
14
|
) {
|
|
15
15
|
const indentNodes: IndentLevelData[] = [
|
|
16
16
|
{
|
|
@@ -39,6 +39,8 @@ export function code(
|
|
|
39
39
|
popIndent();
|
|
40
40
|
flushLines();
|
|
41
41
|
|
|
42
|
+
return childNodesFor(indentNodes[0]);
|
|
43
|
+
|
|
42
44
|
function childNodesFor(indentNode: IndentLevelData): Child[] {
|
|
43
45
|
return indentNode.children.map((child) => {
|
|
44
46
|
if (
|
|
@@ -46,16 +48,13 @@ export function code(
|
|
|
46
48
|
child !== null &&
|
|
47
49
|
(child as any).kind === "indent"
|
|
48
50
|
) {
|
|
49
|
-
return ()
|
|
50
|
-
Indent({ children: childNodesFor(child as IndentLevelData) });
|
|
51
|
+
return indent({ children: childNodesFor(child as IndentLevelData) });
|
|
51
52
|
} else {
|
|
52
53
|
return child as Child;
|
|
53
54
|
}
|
|
54
55
|
});
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
return childNodesFor(indentNodes[0]);
|
|
58
|
-
|
|
59
58
|
function pushIndent() {
|
|
60
59
|
flushLines();
|
|
61
60
|
const newIndent: IndentLevelData = {
|
|
@@ -63,7 +62,7 @@ export function code(
|
|
|
63
62
|
children: [],
|
|
64
63
|
pendingLines: [""],
|
|
65
64
|
};
|
|
66
|
-
indentNodes.at(-1)!.children.push(newIndent
|
|
65
|
+
indentNodes.at(-1)!.children.push(newIndent);
|
|
67
66
|
indentNodes.push(newIndent);
|
|
68
67
|
}
|
|
69
68
|
|
|
@@ -84,7 +83,13 @@ export function code(
|
|
|
84
83
|
}
|
|
85
84
|
function flushLines() {
|
|
86
85
|
const currentIndent = indentNodes.at(-1)!;
|
|
87
|
-
currentIndent.children.push(
|
|
86
|
+
currentIndent.children.push(
|
|
87
|
+
...currentIndent.pendingLines
|
|
88
|
+
.map((str, index) =>
|
|
89
|
+
index < currentIndent.pendingLines.length - 1 ? [str, hbr()] : [str],
|
|
90
|
+
)
|
|
91
|
+
.flat(),
|
|
92
|
+
);
|
|
88
93
|
currentIndent.pendingLines = [];
|
|
89
94
|
}
|
|
90
95
|
}
|
|
@@ -103,12 +108,12 @@ interface LineToken extends ChildTokenBase {
|
|
|
103
108
|
|
|
104
109
|
interface OtherToken extends ChildTokenBase {
|
|
105
110
|
kind: "other";
|
|
106
|
-
value:
|
|
111
|
+
value: Children;
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
function* childTokens(
|
|
110
115
|
template: TemplateStringsArray,
|
|
111
|
-
substitutions:
|
|
116
|
+
substitutions: Children[],
|
|
112
117
|
): IterableIterator<ChildToken> {
|
|
113
118
|
let newline = false;
|
|
114
119
|
const indentStack: { level: number; literalIndent: string }[] = [
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Children, childrenArray, computed, Indent } from "@alloy-js/core";
|
|
2
|
+
|
|
3
|
+
export interface BlockProps {
|
|
4
|
+
/**
|
|
5
|
+
* The opening punctuation of the block. Defaults to "\{".
|
|
6
|
+
*/
|
|
7
|
+
opener?: string;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The closing punctuation of the block. Defaults to "\}".
|
|
11
|
+
*/
|
|
12
|
+
closer?: string;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Whether the block starts on a new line. When true, a hardline is added
|
|
16
|
+
* prior to the block.
|
|
17
|
+
*/
|
|
18
|
+
newline?: boolean;
|
|
19
|
+
|
|
20
|
+
/** The block's contents */
|
|
21
|
+
children?: Children;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create an indented block of source text. The block has `opener` text which is
|
|
26
|
+
* added prior to the block, which defaults to "\{", and `closer` text which is
|
|
27
|
+
* added after the block, which defaults to "\}".
|
|
28
|
+
*/
|
|
29
|
+
export function Block(props: BlockProps) {
|
|
30
|
+
const childCount = computed(() => childrenArray(() => props.children).length);
|
|
31
|
+
return (
|
|
32
|
+
<group>
|
|
33
|
+
{props.newline && <br />}
|
|
34
|
+
{props.opener ?? "{"}
|
|
35
|
+
<Indent break={childCount.value > 0 ? "hard" : "soft"}>
|
|
36
|
+
{props.children}
|
|
37
|
+
</Indent>
|
|
38
|
+
{childCount.value > 0 ?
|
|
39
|
+
<hbr />
|
|
40
|
+
: <sbr />}
|
|
41
|
+
{props.closer ?? "}"}
|
|
42
|
+
</group>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
@@ -2,7 +2,7 @@ import { OutputSymbol } from "../binder.js";
|
|
|
2
2
|
import { useContext } from "../context.js";
|
|
3
3
|
import { BinderContext } from "../context/binder.js";
|
|
4
4
|
import { DeclarationContext } from "../context/declaration.js";
|
|
5
|
-
import { Children } from "../jsx-runtime.js";
|
|
5
|
+
import { Children, onCleanup } from "../jsx-runtime.js";
|
|
6
6
|
import { Refkey, refkey } from "../refkey.js";
|
|
7
7
|
|
|
8
8
|
export interface DeclarationProps {
|
|
@@ -45,9 +45,15 @@ export function Declaration(props: DeclarationProps) {
|
|
|
45
45
|
name: props.name!,
|
|
46
46
|
refkey: rk,
|
|
47
47
|
});
|
|
48
|
+
|
|
49
|
+
onCleanup(() => {
|
|
50
|
+
binder.deleteSymbol(declaration!);
|
|
51
|
+
});
|
|
48
52
|
}
|
|
49
53
|
|
|
50
|
-
return
|
|
51
|
-
{
|
|
52
|
-
|
|
54
|
+
return (
|
|
55
|
+
<DeclarationContext.Provider value={declaration}>
|
|
56
|
+
{props.children}
|
|
57
|
+
</DeclarationContext.Provider>
|
|
58
|
+
);
|
|
53
59
|
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Children, memo } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { isRef, Ref } from "@vue/reactivity";
|
|
3
|
+
import { mapJoin } from "../utils.js";
|
|
4
|
+
import { BaseListProps, baseListPropsToMapJoinArgs } from "./List.jsx";
|
|
5
|
+
|
|
6
|
+
export type ForCallbackArgs<T> =
|
|
7
|
+
T extends Ref<infer U> ? ForCallbackArgs<U>
|
|
8
|
+
: T extends () => infer U ? ForCallbackArgs<U>
|
|
9
|
+
: T extends (infer U)[] ? [value: U]
|
|
10
|
+
: T extends Map<infer U, infer V> ? [key: U, value: V]
|
|
11
|
+
: T extends Set<infer U> ? [value: U]
|
|
12
|
+
: [];
|
|
13
|
+
|
|
14
|
+
export interface ForProps<
|
|
15
|
+
T extends
|
|
16
|
+
| ForSupportedCollections
|
|
17
|
+
| (() => ForSupportedCollections)
|
|
18
|
+
| Ref<ForSupportedCollections>,
|
|
19
|
+
U extends Children,
|
|
20
|
+
> extends BaseListProps {
|
|
21
|
+
/**
|
|
22
|
+
* The array to iterate over.
|
|
23
|
+
*/
|
|
24
|
+
each: T;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A function to call for each item.
|
|
28
|
+
*/
|
|
29
|
+
children: (...args: [...ForCallbackArgs<T>, index: number]) => U;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type ForSupportedCollections = any[] | Map<any, any> | Set<any>;
|
|
33
|
+
/**
|
|
34
|
+
* The For component iterates over the provided array and invokes the child
|
|
35
|
+
* callback for each item. It can optionally be provided with a `joiner` which
|
|
36
|
+
* is placed between each item, and an `ender` which is placed after the last
|
|
37
|
+
* item when there is at least one item.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
*
|
|
41
|
+
* ```tsx
|
|
42
|
+
* const items = ["apple", "pear", "plum"];
|
|
43
|
+
* return <For each={items}>
|
|
44
|
+
* {(item) => <>Fruit: {item}</>}
|
|
45
|
+
* </For>
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
*
|
|
50
|
+
* When the `each` prop is a reactive (e.g. a reactive array, or ref to an
|
|
51
|
+
* array), `For` will automatically update when the array changes. When doing
|
|
52
|
+
* so, it will attempt to avoid re-rendering items which have not changed. For
|
|
53
|
+
* example, when appending an item to a reactive array, existing items will not
|
|
54
|
+
* be re-rendered. Note that presently the implementation is fairly simple -
|
|
55
|
+
* when making modifications to the middle of an array it likely that every
|
|
56
|
+
* element after the modification will be rerendered.
|
|
57
|
+
*
|
|
58
|
+
* @see {@link (mapJoin:1)} for mapping arrays to elements outside of JSX templates.
|
|
59
|
+
*/
|
|
60
|
+
export function For<
|
|
61
|
+
T extends
|
|
62
|
+
| ForSupportedCollections
|
|
63
|
+
| (() => ForSupportedCollections)
|
|
64
|
+
| Ref<ForSupportedCollections>,
|
|
65
|
+
U extends Children,
|
|
66
|
+
>(props: ForProps<T, U>) {
|
|
67
|
+
const cb = props.children;
|
|
68
|
+
const options = baseListPropsToMapJoinArgs(props);
|
|
69
|
+
options.skipFalsy = true;
|
|
70
|
+
return memo(() => {
|
|
71
|
+
const maybeRef = props.each;
|
|
72
|
+
|
|
73
|
+
return (mapJoin as any)(
|
|
74
|
+
typeof maybeRef === "function" ? maybeRef : (
|
|
75
|
+
() => (isRef(maybeRef) ? maybeRef.value : maybeRef)
|
|
76
|
+
),
|
|
77
|
+
cb,
|
|
78
|
+
options,
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
@@ -1,33 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { IndentContext } from "../context/indent.js";
|
|
3
|
-
import { Children } from "../jsx-runtime.js";
|
|
1
|
+
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
4
2
|
|
|
5
3
|
export interface IndentProps {
|
|
6
|
-
children
|
|
7
|
-
|
|
4
|
+
children: Children;
|
|
5
|
+
nobreak?: boolean;
|
|
6
|
+
break?: "space" | "soft" | "hard";
|
|
7
|
+
trailingBreak?: boolean;
|
|
8
8
|
}
|
|
9
|
-
|
|
10
|
-
export interface IndentState {
|
|
11
|
-
level: number;
|
|
12
|
-
indent: string;
|
|
13
|
-
indentString: string; // awful name
|
|
14
|
-
noLeading?: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
9
|
export function Indent(props: IndentProps) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const level = previousIndent.level + 1;
|
|
25
|
-
|
|
26
|
-
const currentIndent = {
|
|
27
|
-
level,
|
|
28
|
-
indent: props.indent ?? previousIndent.indent,
|
|
29
|
-
indentString: (props.indent ?? previousIndent.indent).repeat(level),
|
|
30
|
-
};
|
|
10
|
+
const breakStyle = props.break ?? "hard";
|
|
11
|
+
const breakElem =
|
|
12
|
+
props.nobreak ? ""
|
|
13
|
+
: breakStyle === "hard" ? <hbr />
|
|
14
|
+
: breakStyle === "soft" ? <sbr />
|
|
15
|
+
: <br />;
|
|
31
16
|
|
|
32
|
-
return
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
<indent>
|
|
20
|
+
{breakElem}
|
|
21
|
+
{props.children}
|
|
22
|
+
</indent>
|
|
23
|
+
{props.trailingBreak && breakElem}
|
|
24
|
+
</>
|
|
25
|
+
);
|
|
33
26
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Children, memo, splitProps } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { childrenArray, JoinOptions } from "../utils.js";
|
|
3
|
+
import { For } from "./For.jsx";
|
|
4
|
+
|
|
5
|
+
export type BreakKind = "none" | "space" | "soft" | "hard" | "literal";
|
|
6
|
+
|
|
7
|
+
export interface BaseListProps {
|
|
8
|
+
/** Text to place between each element */
|
|
9
|
+
joiner?: Children;
|
|
10
|
+
|
|
11
|
+
/** Place a comma between each element */
|
|
12
|
+
comma?: boolean;
|
|
13
|
+
|
|
14
|
+
/** Place a semicolon between each element */
|
|
15
|
+
semicolon?: boolean;
|
|
16
|
+
|
|
17
|
+
line?: boolean;
|
|
18
|
+
softline?: boolean;
|
|
19
|
+
hardline?: boolean;
|
|
20
|
+
literalline?: boolean;
|
|
21
|
+
space?: boolean;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Text to place at the end of the list when there is at least one item. If
|
|
25
|
+
* set to true, the joiner is used.
|
|
26
|
+
**/
|
|
27
|
+
ender?: Children;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Place the join punctuation at the end, but without a line break.
|
|
31
|
+
*/
|
|
32
|
+
enderPunctuation?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function baseListPropsToMapJoinArgs(props: BaseListProps): JoinOptions {
|
|
36
|
+
let joiner, punctuation;
|
|
37
|
+
if ("joiner" in props) {
|
|
38
|
+
joiner = props.joiner;
|
|
39
|
+
} else {
|
|
40
|
+
punctuation =
|
|
41
|
+
props.comma ? ","
|
|
42
|
+
: props.semicolon ? ";"
|
|
43
|
+
: "";
|
|
44
|
+
|
|
45
|
+
joiner = (
|
|
46
|
+
<>
|
|
47
|
+
{punctuation}
|
|
48
|
+
{props.softline ?
|
|
49
|
+
<sbr />
|
|
50
|
+
: props.hardline ?
|
|
51
|
+
<hbr />
|
|
52
|
+
: props.literalline ?
|
|
53
|
+
<lbr />
|
|
54
|
+
: props.line ?
|
|
55
|
+
<br />
|
|
56
|
+
: props.space ?
|
|
57
|
+
<> </>
|
|
58
|
+
: <hbr />}
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const ender =
|
|
64
|
+
"ender" in props ? props.ender
|
|
65
|
+
: props.enderPunctuation ? punctuation
|
|
66
|
+
: undefined;
|
|
67
|
+
|
|
68
|
+
return { joiner, ender };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ListProps extends BaseListProps {
|
|
72
|
+
children?: Children;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Create a list of children with text between each child. The text to join with
|
|
77
|
+
* is specified by providing either `joiner` children, or providing boolean
|
|
78
|
+
* props for the punctuation and line breaks. The default joiner is no
|
|
79
|
+
* punctuation and a hard break. The `ender` prop can provide text to place at
|
|
80
|
+
* the end of the list when there is at least one child.
|
|
81
|
+
*/
|
|
82
|
+
export function List(props: ListProps) {
|
|
83
|
+
const [rest, forProps] = splitProps(props, ["children"]);
|
|
84
|
+
const resolvedChildren = memo(() =>
|
|
85
|
+
childrenArray(() => rest.children, {
|
|
86
|
+
preserveFragments: true,
|
|
87
|
+
}),
|
|
88
|
+
);
|
|
89
|
+
return (
|
|
90
|
+
<For each={resolvedChildren} {...forProps}>
|
|
91
|
+
{(child) => child}
|
|
92
|
+
</For>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -50,13 +50,16 @@ export function MemberDeclaration(props: MemberDeclarationProps) {
|
|
|
50
50
|
declaration = binder.createSymbol({
|
|
51
51
|
name: props.name!,
|
|
52
52
|
refkey: rk,
|
|
53
|
-
flags:
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
flags:
|
|
54
|
+
props.static ?
|
|
55
|
+
OutputSymbolFlags.StaticMember
|
|
56
|
+
: OutputSymbolFlags.InstanceMember,
|
|
56
57
|
});
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
return
|
|
60
|
-
{
|
|
61
|
-
|
|
60
|
+
return (
|
|
61
|
+
<MemberDeclarationContext.Provider value={declaration}>
|
|
62
|
+
{props.children}
|
|
63
|
+
</MemberDeclarationContext.Provider>
|
|
64
|
+
);
|
|
62
65
|
}
|
|
@@ -34,7 +34,9 @@ export function MemberScope(props: MemberScopeProps) {
|
|
|
34
34
|
instanceMembers: props.owner.instanceMemberScope,
|
|
35
35
|
staticMembers: props.owner.staticMemberScope,
|
|
36
36
|
};
|
|
37
|
-
return
|
|
37
|
+
return (
|
|
38
|
+
<MemberScopeContext.Provider value={context}>
|
|
38
39
|
{props.children}
|
|
39
|
-
</MemberScopeContext.Provider
|
|
40
|
+
</MemberScopeContext.Provider>
|
|
41
|
+
);
|
|
40
42
|
}
|