@alloy-js/core 0.5.0 → 0.7.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 +55 -0
- package/babel.config.cjs +4 -1
- package/dist/src/binder.d.ts +8 -2
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +41 -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.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 +5 -9
- 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.map +1 -1
- package/dist/src/components/MemberDeclaration.js.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.map +1 -1
- package/dist/src/components/MemberScope.js.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 +2 -1
- package/dist/src/components/Output.d.ts.map +1 -1
- package/dist/src/components/Output.js +9 -1
- package/dist/src/components/Output.js.map +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.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 +2 -6
- 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 +77 -6
- 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.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 +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/jsx-runtime.d.ts +139 -8
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +102 -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 +281 -177
- 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/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/src/write-output.js +3 -3
- package/dist/src/write-output.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 +6 -8
- package/src/binder.ts +54 -18
- 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 +25 -13
- package/src/components/Scope.tsx +4 -2
- package/src/components/Show.tsx +11 -0
- package/src/components/SourceDirectory.tsx +5 -1
- package/src/components/SourceFile.tsx +12 -16
- 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.ts +2 -3
- package/src/index.browser.ts +2 -0
- package/src/index.ts +1 -0
- package/src/jsx-runtime.ts +245 -23
- package/src/render.ts +392 -198
- package/src/stc.ts +95 -0
- package/src/utils.ts +162 -95
- package/src/write-output.ts +3 -3
- package/temp/api.json +8407 -3301
- 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 +87 -8
- 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,28 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alloy-js/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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
|
-
"development": "./src/jsx-runtime.ts",
|
|
14
13
|
"import": "./dist/src/jsx-runtime.js"
|
|
15
14
|
},
|
|
16
15
|
"./testing": {
|
|
17
|
-
"development": "./testing/index.ts",
|
|
18
16
|
"import": "./dist/testing/index.js"
|
|
19
17
|
},
|
|
20
18
|
"./stc": {
|
|
21
|
-
"development": "./src/components/stc/index.ts",
|
|
22
19
|
"import": "./dist/src/components/stc/index.js"
|
|
23
20
|
},
|
|
24
21
|
"./components": {
|
|
25
|
-
"development": "./src/components/index.ts",
|
|
26
22
|
"import": "./dist/src/components/index.js"
|
|
27
23
|
}
|
|
28
24
|
},
|
|
@@ -40,7 +36,8 @@
|
|
|
40
36
|
"chalk": "^5.3.0",
|
|
41
37
|
"cli-table3": "^0.6.5",
|
|
42
38
|
"pathe": "^1.1.2",
|
|
43
|
-
"
|
|
39
|
+
"prettier": "^3.5.1",
|
|
40
|
+
"@alloy-js/babel-preset": "~0.2.0"
|
|
44
41
|
},
|
|
45
42
|
"devDependencies": {
|
|
46
43
|
"@babel/cli": "^7.24.7",
|
|
@@ -49,7 +46,8 @@
|
|
|
49
46
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
50
47
|
"concurrently": "^8.2.2",
|
|
51
48
|
"typescript": "^5.7.3",
|
|
52
|
-
"vitest": "^3.0.4"
|
|
49
|
+
"vitest": "^3.0.4",
|
|
50
|
+
"vite": "^6.0.1"
|
|
53
51
|
},
|
|
54
52
|
"type": "module",
|
|
55
53
|
"scripts": {
|
package/src/binder.ts
CHANGED
|
@@ -99,9 +99,9 @@ export interface OutputSymbol {
|
|
|
99
99
|
binder: Binder;
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
*
|
|
102
|
+
* The unique values that reference this symbol.
|
|
103
103
|
*/
|
|
104
|
-
|
|
104
|
+
refkeys: Refkey[];
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* The instance members available on this symbol.
|
|
@@ -228,6 +228,7 @@ export type CreateSymbolOptions<T extends OutputSymbol = OutputSymbol> = {
|
|
|
228
228
|
name: string;
|
|
229
229
|
scope?: OutputScope;
|
|
230
230
|
refkey?: Refkey;
|
|
231
|
+
refkeys?: Refkey[];
|
|
231
232
|
flags?: OutputSymbolFlags;
|
|
232
233
|
} & Omit<T, keyof OutputSymbol>;
|
|
233
234
|
|
|
@@ -265,6 +266,12 @@ export interface Binder {
|
|
|
265
266
|
*/
|
|
266
267
|
createSymbol<T extends OutputSymbol>(args: CreateSymbolOptions<T>): T;
|
|
267
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Delete the given symbol. The symbol will be removed from its parent's
|
|
271
|
+
* scope. Any resolutions to this symbol will become undefined.
|
|
272
|
+
*/
|
|
273
|
+
deleteSymbol(symbol: OutputSymbol): void;
|
|
274
|
+
|
|
268
275
|
/**
|
|
269
276
|
* Instantiate the static members of a symbol into the instance members of
|
|
270
277
|
* another symbol.
|
|
@@ -415,6 +422,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
415
422
|
const binder: Binder = {
|
|
416
423
|
createScope,
|
|
417
424
|
createSymbol,
|
|
425
|
+
deleteSymbol,
|
|
418
426
|
resolveDeclarationByKey,
|
|
419
427
|
addStaticMembersToSymbol,
|
|
420
428
|
addInstanceMembersToSymbol,
|
|
@@ -517,10 +525,20 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
517
525
|
name,
|
|
518
526
|
scope = useDefaultScope(args.flags),
|
|
519
527
|
refkey,
|
|
528
|
+
refkeys,
|
|
520
529
|
flags = OutputSymbolFlags.None,
|
|
521
530
|
...rest
|
|
522
531
|
} = args;
|
|
523
532
|
|
|
533
|
+
const allRefkeys = [];
|
|
534
|
+
if (refkey) {
|
|
535
|
+
allRefkeys.push(refkey);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (refkeys) {
|
|
539
|
+
allRefkeys.push(...refkeys);
|
|
540
|
+
}
|
|
541
|
+
|
|
524
542
|
if (!scope) {
|
|
525
543
|
throw new Error(
|
|
526
544
|
"No scope was provided and no scope could be found in context",
|
|
@@ -549,7 +567,7 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
549
567
|
originalName: name,
|
|
550
568
|
name: name,
|
|
551
569
|
scope,
|
|
552
|
-
|
|
570
|
+
refkeys: allRefkeys,
|
|
553
571
|
binder,
|
|
554
572
|
flags,
|
|
555
573
|
...rest,
|
|
@@ -576,7 +594,9 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
576
594
|
}
|
|
577
595
|
|
|
578
596
|
scope.symbols.add(symbol);
|
|
579
|
-
|
|
597
|
+
for (const refkey of allRefkeys) {
|
|
598
|
+
scope.symbolsByRefkey.set(refkey, symbol);
|
|
599
|
+
}
|
|
580
600
|
|
|
581
601
|
deconflict(symbol);
|
|
582
602
|
notifyRefkey(symbol);
|
|
@@ -584,6 +604,20 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
584
604
|
return symbol;
|
|
585
605
|
}
|
|
586
606
|
|
|
607
|
+
function deleteSymbol(symbol: OutputSymbol) {
|
|
608
|
+
symbol.scope.symbols.delete(symbol);
|
|
609
|
+
|
|
610
|
+
if (!refkey) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
for (const refkey of symbol.refkeys) {
|
|
615
|
+
const resolution = waitingDeclarations.get(refkey);
|
|
616
|
+
if (!resolution) return;
|
|
617
|
+
resolution.value = undefined;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
587
621
|
function instantiateSymbolInto(source: OutputSymbol, target: OutputSymbol) {
|
|
588
622
|
if (~source.flags & OutputSymbolFlags.InstanceMemberContainer) {
|
|
589
623
|
throw new Error("Can only instantiate symbols with instance members");
|
|
@@ -600,7 +634,8 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
600
634
|
createSymbol({
|
|
601
635
|
name: sym.name,
|
|
602
636
|
scope: target.instanceMemberScope!,
|
|
603
|
-
|
|
637
|
+
// todo: fix this or change this or something??
|
|
638
|
+
refkeys: [refkey(target.refkeys[0], sym.refkeys[0])],
|
|
604
639
|
flags: sym.flags | OutputSymbolFlags.InstanceMember,
|
|
605
640
|
});
|
|
606
641
|
}
|
|
@@ -797,20 +832,21 @@ export function createOutputBinder(options: BinderOptions = {}): Binder {
|
|
|
797
832
|
|
|
798
833
|
function notifyRefkey(symbol: OutputSymbol): void {
|
|
799
834
|
effect(() => {
|
|
800
|
-
const refkey
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
835
|
+
for (const refkey of symbol.refkeys) {
|
|
836
|
+
// notify those waiting for this refkey
|
|
837
|
+
knownDeclarations.set(refkey, symbol);
|
|
838
|
+
if (waitingDeclarations.has(refkey)) {
|
|
839
|
+
const signal = waitingDeclarations.get(refkey)!;
|
|
840
|
+
signal.value = symbol;
|
|
841
|
+
}
|
|
808
842
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
waitingName
|
|
843
|
+
// notify those waiting for this symbol name
|
|
844
|
+
const waitingScope = waitingSymbolNames.get(symbol.scope);
|
|
845
|
+
if (waitingScope) {
|
|
846
|
+
const waitingName = waitingScope.get(symbol.name);
|
|
847
|
+
if (waitingName) {
|
|
848
|
+
waitingName.value = symbol;
|
|
849
|
+
}
|
|
814
850
|
}
|
|
815
851
|
}
|
|
816
852
|
});
|
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
|
}
|
|
@@ -5,15 +5,16 @@ import {
|
|
|
5
5
|
} from "../binder.js";
|
|
6
6
|
import { BinderContext } from "../context/binder.js";
|
|
7
7
|
import { NamePolicyContext } from "../context/name-policy.js";
|
|
8
|
-
import { Children } from "../jsx-runtime.js";
|
|
8
|
+
import { Children, getContext } from "../jsx-runtime.js";
|
|
9
9
|
import { NamePolicy } from "../name-policy.js";
|
|
10
|
+
import { PrintTreeOptions } from "../render.js";
|
|
10
11
|
import { extensionEffects } from "../slot.js";
|
|
11
12
|
import { SourceDirectory } from "./SourceDirectory.js";
|
|
12
13
|
|
|
13
14
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
15
|
import { SourceFile } from "./SourceFile.js";
|
|
15
16
|
|
|
16
|
-
export interface OutputProps {
|
|
17
|
+
export interface OutputProps extends PrintTreeOptions {
|
|
17
18
|
children?: Children;
|
|
18
19
|
/**
|
|
19
20
|
* External libraries whose symbols should be available for reference.
|
|
@@ -48,10 +49,18 @@ export function Output(props: OutputProps) {
|
|
|
48
49
|
const binder = createOutputBinder({
|
|
49
50
|
nameConflictResolver: props.nameConflictResolver,
|
|
50
51
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
|
|
53
|
+
const nodeContext = getContext()!;
|
|
54
|
+
nodeContext.meta ??= {};
|
|
55
|
+
nodeContext.meta.printOptions = {
|
|
56
|
+
printWidth: props.printWidth,
|
|
57
|
+
tabWidth: props.tabWidth,
|
|
58
|
+
useTabs: props.useTabs,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const dir = (
|
|
62
|
+
<SourceDirectory path={basePath}>{props.children}</SourceDirectory>
|
|
63
|
+
);
|
|
55
64
|
|
|
56
65
|
if (props.externals) {
|
|
57
66
|
for (const global of props.externals) {
|
|
@@ -59,13 +68,16 @@ export function Output(props: OutputProps) {
|
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
return (
|
|
72
|
+
<BinderContext.Provider value={binder}>
|
|
73
|
+
{() => {
|
|
74
|
+
extensionEffects.forEach((e) => e());
|
|
75
|
+
}}
|
|
76
|
+
{props.namePolicy ?
|
|
65
77
|
<NamePolicyContext.Provider value={props.namePolicy}>
|
|
66
78
|
{dir}
|
|
67
|
-
</NamePolicyContext.Provider>
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
79
|
+
</NamePolicyContext.Provider>
|
|
80
|
+
: dir}
|
|
81
|
+
</BinderContext.Provider>
|
|
82
|
+
);
|
|
71
83
|
}
|