@alloy-js/core 0.6.0 → 0.8.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 +37 -0
- package/babel.config.cjs +1 -4
- package/dist/src/binder.d.ts +15 -13
- package/dist/src/binder.d.ts.map +1 -1
- package/dist/src/binder.js +34 -34
- package/dist/src/binder.js.map +1 -1
- package/dist/src/code.d.ts +11 -2
- package/dist/src/code.d.ts.map +1 -1
- package/dist/src/code.js +27 -2
- package/dist/src/code.js.map +1 -1
- package/dist/src/components/Block.d.ts +2 -2
- package/dist/src/components/Block.d.ts.map +1 -1
- package/dist/src/components/Block.js +6 -5
- package/dist/src/components/Block.js.map +1 -1
- package/dist/src/components/Declaration.d.ts +31 -7
- package/dist/src/components/Declaration.d.ts.map +1 -1
- package/dist/src/components/Declaration.js +15 -7
- package/dist/src/components/Declaration.js.map +1 -1
- package/dist/src/components/For.d.ts +6 -0
- package/dist/src/components/For.d.ts.map +1 -1
- package/dist/src/components/For.js +2 -3
- package/dist/src/components/For.js.map +1 -1
- package/dist/src/components/Indent.d.ts +29 -1
- package/dist/src/components/Indent.d.ts.map +1 -1
- package/dist/src/components/Indent.js +7 -2
- package/dist/src/components/Indent.js.map +1 -1
- package/dist/src/components/List.d.ts +7 -3
- package/dist/src/components/List.d.ts.map +1 -1
- package/dist/src/components/List.js +1 -16
- package/dist/src/components/List.js.map +1 -1
- package/dist/src/components/MemberDeclaration.d.ts +35 -5
- package/dist/src/components/MemberDeclaration.d.ts.map +1 -1
- package/dist/src/components/MemberDeclaration.js +18 -7
- package/dist/src/components/MemberDeclaration.js.map +1 -1
- package/dist/src/components/MemberScope.d.ts +2 -0
- package/dist/src/components/MemberScope.d.ts.map +1 -1
- package/dist/src/components/MemberScope.js +2 -0
- package/dist/src/components/MemberScope.js.map +1 -1
- package/dist/src/components/Prose.d.ts +10 -0
- package/dist/src/components/Prose.d.ts.map +1 -0
- package/dist/src/components/Prose.js +23 -0
- package/dist/src/components/Prose.js.map +1 -0
- package/dist/src/components/Scope.d.ts +33 -2
- package/dist/src/components/Scope.d.ts.map +1 -1
- package/dist/src/components/Scope.js +20 -4
- package/dist/src/components/Scope.js.map +1 -1
- package/dist/src/components/SourceFile.d.ts +5 -0
- package/dist/src/components/SourceFile.d.ts.map +1 -1
- package/dist/src/components/SourceFile.js +10 -1
- package/dist/src/components/SourceFile.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/src/components/stc/index.d.ts +19 -95
- package/dist/src/components/stc/index.d.ts.map +1 -1
- package/dist/src/components/stc/index.js +3 -6
- package/dist/src/components/stc/index.js.map +1 -1
- package/dist/src/components/stc/sti.d.ts +9 -0
- package/dist/src/components/stc/sti.d.ts.map +1 -0
- package/dist/src/components/stc/sti.js +10 -0
- package/dist/src/components/stc/sti.js.map +1 -0
- package/dist/src/context/assignment.d.ts +6 -0
- package/dist/src/context/assignment.d.ts.map +1 -1
- package/dist/src/context/assignment.js +7 -0
- package/dist/src/context/assignment.js.map +1 -1
- package/dist/src/context.d.ts +2 -0
- package/dist/src/context.d.ts.map +1 -1
- package/dist/src/context.js +12 -9
- package/dist/src/context.js.map +1 -1
- 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 +98 -1
- package/dist/src/jsx-runtime.d.ts.map +1 -1
- package/dist/src/jsx-runtime.js +46 -1
- package/dist/src/jsx-runtime.js.map +1 -1
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +12 -0
- package/dist/src/render.js.map +1 -1
- package/dist/src/stc.d.ts +5 -7
- package/dist/src/stc.d.ts.map +1 -1
- package/dist/src/stc.js +11 -23
- package/dist/src/stc.js.map +1 -1
- package/dist/src/sti.d.ts +11 -0
- package/dist/src/sti.d.ts.map +1 -0
- package/dist/src/sti.js +31 -0
- package/dist/src/sti.js.map +1 -0
- package/dist/src/tap.d.ts +69 -6
- package/dist/src/tap.d.ts.map +1 -1
- package/dist/src/tap.js +70 -0
- package/dist/src/tap.js.map +1 -1
- package/dist/src/utils.d.ts +5 -0
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +20 -0
- 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/components/prose.test.d.ts +2 -0
- package/dist/test/components/prose.test.d.ts.map +1 -0
- package/dist/test/props-with-defaults.test.d.ts +2 -0
- package/dist/test/props-with-defaults.test.d.ts.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/binder.ts +46 -40
- package/src/code.ts +37 -3
- package/src/components/Block.tsx +3 -6
- package/src/components/Declaration.tsx +43 -11
- package/src/components/For.tsx +10 -3
- package/src/components/Indent.tsx +38 -5
- package/src/components/List.tsx +14 -40
- package/src/components/MemberDeclaration.tsx +51 -12
- package/src/components/MemberScope.tsx +2 -0
- package/src/components/Prose.tsx +35 -0
- package/src/components/Scope.tsx +45 -5
- package/src/components/SourceFile.tsx +10 -0
- package/src/components/index.tsx +1 -0
- package/src/components/stc/index.ts +3 -6
- package/src/components/stc/sti.ts +10 -0
- package/src/context/assignment.ts +7 -1
- package/src/context.ts +15 -11
- package/src/index.ts +1 -0
- package/src/jsx-runtime.ts +162 -0
- package/src/render.ts +14 -0
- package/src/stc.ts +35 -56
- package/src/sti.ts +63 -0
- package/src/tap.ts +69 -6
- package/src/{utils.ts → utils.tsx} +45 -0
- package/src/write-output.ts +3 -3
- package/temp/api.json +1563 -393
- package/test/components/declaration.test.tsx +1 -1
- package/test/components/prose.test.tsx +36 -0
- package/test/components/source-file.test.tsx +17 -0
- package/test/props-with-defaults.test.ts +97 -0
- package/test/symbols.test.ts +14 -33
- package/vitest.config.ts +2 -10
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { childrenArray, computed } from "@alloy-js/core";
|
|
2
|
+
import { Children } from "@alloy-js/core/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
export interface Prose {
|
|
5
|
+
children: Children;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a block of text which will break once a word exceeds the configured line width.
|
|
10
|
+
* The children are expected to be strings, and a <br /> is added between each word.
|
|
11
|
+
*/
|
|
12
|
+
export function Prose(props: Prose) {
|
|
13
|
+
const brokenChildren = computed(() => {
|
|
14
|
+
const children = childrenArray(() => props.children);
|
|
15
|
+
return children
|
|
16
|
+
.map((child) => {
|
|
17
|
+
if (typeof child === "string") {
|
|
18
|
+
return child
|
|
19
|
+
.trim()
|
|
20
|
+
.split(/\s+/)
|
|
21
|
+
.map((word) => (
|
|
22
|
+
<>
|
|
23
|
+
{word}
|
|
24
|
+
<br />
|
|
25
|
+
</>
|
|
26
|
+
));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return child;
|
|
30
|
+
})
|
|
31
|
+
.flat(2);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return <fill>{brokenChildren.value}</fill>;
|
|
35
|
+
}
|
package/src/components/Scope.tsx
CHANGED
|
@@ -4,21 +4,61 @@ import { BinderContext } from "../context/binder.js";
|
|
|
4
4
|
import { ScopeContext } from "../context/scope.js";
|
|
5
5
|
import { Children } from "../jsx-runtime.js";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Declare a scope by providing an already created scope. The scope is merely
|
|
9
|
+
* exposed via {@link ScopeContext}.
|
|
10
|
+
*/
|
|
11
|
+
export interface ScopePropsWithValue {
|
|
12
|
+
/**
|
|
13
|
+
* The scope to use. If not provided, a new scope will be created.
|
|
14
|
+
*/
|
|
15
|
+
value: OutputScope;
|
|
16
|
+
|
|
17
|
+
children?: Children;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a scope by providing a name and optional metadata.
|
|
22
|
+
*/
|
|
23
|
+
export interface ScopePropsWithInfo {
|
|
24
|
+
/**
|
|
25
|
+
* The kind of scope. This may be used by application code to determine how
|
|
26
|
+
* to handle symbols in this scope. It is not used by the core framework.
|
|
27
|
+
*/
|
|
8
28
|
kind?: string;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The name of this scope.
|
|
32
|
+
*/
|
|
9
33
|
name?: string;
|
|
10
|
-
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Additional metadata for the scope.
|
|
37
|
+
*/
|
|
38
|
+
metadata?: Record<string, unknown>;
|
|
39
|
+
|
|
11
40
|
children?: Children;
|
|
12
41
|
}
|
|
13
42
|
|
|
43
|
+
export type ScopeProps = ScopePropsWithValue | ScopePropsWithInfo;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Declare a scope for this component's children. Any symbols and scopes
|
|
47
|
+
* declared in the children of this component will be in this scope.
|
|
48
|
+
*
|
|
49
|
+
* @see {@link ScopeContext}
|
|
50
|
+
*/
|
|
14
51
|
export function Scope(props: ScopeProps) {
|
|
15
52
|
let scope: OutputScope;
|
|
16
|
-
if (props
|
|
53
|
+
if ("value" in props) {
|
|
17
54
|
scope = props.value;
|
|
18
55
|
} else {
|
|
19
|
-
const kind = props.kind ?? "file";
|
|
20
56
|
const binder = useContext(BinderContext)!;
|
|
21
|
-
scope = binder.createScope({
|
|
57
|
+
scope = binder.createScope({
|
|
58
|
+
kind: props.kind,
|
|
59
|
+
metadata: props.metadata,
|
|
60
|
+
name: props.name ?? "",
|
|
61
|
+
});
|
|
22
62
|
}
|
|
23
63
|
|
|
24
64
|
return (
|
|
@@ -5,6 +5,7 @@ import { SourceFileContext } from "../context/source-file.js";
|
|
|
5
5
|
import { Children, ComponentDefinition, getContext } from "../jsx-runtime.js";
|
|
6
6
|
import { Refkey } from "../refkey.js";
|
|
7
7
|
import { PrintTreeOptions } from "../render.js";
|
|
8
|
+
import { Show } from "./Show.jsx";
|
|
8
9
|
|
|
9
10
|
export interface SourceFileProps extends PrintTreeOptions {
|
|
10
11
|
/**
|
|
@@ -24,6 +25,11 @@ export interface SourceFileProps extends PrintTreeOptions {
|
|
|
24
25
|
* contents.
|
|
25
26
|
*/
|
|
26
27
|
reference?: ComponentDefinition<{ refkey: Refkey }>;
|
|
28
|
+
/**
|
|
29
|
+
* The header of the file. This is rendered before the contents of the file.
|
|
30
|
+
* This is useful for adding license headers or other metadata to the file.
|
|
31
|
+
*/
|
|
32
|
+
header?: Children;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
export function SourceFile(props: SourceFileProps) {
|
|
@@ -45,6 +51,10 @@ export function SourceFile(props: SourceFileProps) {
|
|
|
45
51
|
|
|
46
52
|
return (
|
|
47
53
|
<SourceFileContext.Provider value={context}>
|
|
54
|
+
<Show when={props.header !== undefined}>
|
|
55
|
+
{props.header}
|
|
56
|
+
<hbr />
|
|
57
|
+
</Show>
|
|
48
58
|
{props.children}
|
|
49
59
|
</SourceFileContext.Provider>
|
|
50
60
|
);
|
package/src/components/index.tsx
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./MemberName.jsx";
|
|
|
8
8
|
export * from "./MemberScope.jsx";
|
|
9
9
|
export * from "./Name.jsx";
|
|
10
10
|
export * from "./Output.js";
|
|
11
|
+
export * from "./Prose.jsx";
|
|
11
12
|
export * from "./Scope.js";
|
|
12
13
|
export * from "./Show.jsx";
|
|
13
14
|
export * from "./SourceDirectory.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { stc
|
|
1
|
+
import { stc } from "../../stc.js";
|
|
2
2
|
import * as base from "../index.js";
|
|
3
3
|
|
|
4
4
|
export const Block = stc(base.Block);
|
|
@@ -11,6 +11,7 @@ export const MemberName = stc(base.MemberName);
|
|
|
11
11
|
export const MemberScope = stc(base.MemberScope);
|
|
12
12
|
export const Name = stc(base.Name);
|
|
13
13
|
export const Output = stc(base.Output);
|
|
14
|
+
export const Prose = stc(base.Prose);
|
|
14
15
|
export const Scope = stc(base.Scope);
|
|
15
16
|
export const Show = stc(base.Show);
|
|
16
17
|
export const StatementList = stc(base.StatementList);
|
|
@@ -19,8 +20,4 @@ export const SourceFile = stc(base.SourceFile);
|
|
|
19
20
|
export const Switch = stc(base.Switch);
|
|
20
21
|
export const Wrap = stc(base.Wrap);
|
|
21
22
|
|
|
22
|
-
export
|
|
23
|
-
export const hbr = sti("hbr");
|
|
24
|
-
export const sbr = sti("sbr");
|
|
25
|
-
export const lbr = sti("lbr");
|
|
26
|
-
export const br = sti("br");
|
|
23
|
+
export * from "./sti.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { sti } from "../../sti.js";
|
|
2
|
+
|
|
3
|
+
export const indent = sti("indent");
|
|
4
|
+
export const group = sti("group");
|
|
5
|
+
export const ifBreak = sti("ifBreak");
|
|
6
|
+
export const hbr = sti("hbr");
|
|
7
|
+
export const sbr = sti("sbr");
|
|
8
|
+
export const lbr = sti("lbr");
|
|
9
|
+
export const br = sti("br");
|
|
10
|
+
export const dedentToRoot = sti("dedentToRoot");
|
|
@@ -52,7 +52,13 @@ export function createAssignmentContext(
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Get the symbol being defined.
|
|
57
|
+
*
|
|
58
|
+
* @returns The symbol currently being defined, or `undefined` if no symbol is
|
|
59
|
+
* being defined.
|
|
60
|
+
*/
|
|
61
|
+
export function getAssignmentSymbol(): OutputSymbol | undefined {
|
|
56
62
|
const assignmentContext = useContext(AssignmentContext);
|
|
57
63
|
if (assignmentContext) {
|
|
58
64
|
return assignmentContext.target;
|
package/src/context.ts
CHANGED
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
effect,
|
|
6
6
|
getContext,
|
|
7
7
|
} from "./jsx-runtime.js";
|
|
8
|
+
import { stc, StcSignature } from "./stc.js";
|
|
8
9
|
|
|
9
10
|
export interface ComponentContext<T> {
|
|
10
11
|
id: symbol;
|
|
11
12
|
default: T | undefined;
|
|
12
13
|
Provider: ComponentDefinition<ContextProviderProps<T>>;
|
|
14
|
+
ProviderStc: StcSignature<ContextProviderProps<T>>;
|
|
13
15
|
name?: string;
|
|
14
16
|
}
|
|
15
17
|
|
|
@@ -38,21 +40,23 @@ export function createContext<T = unknown>(
|
|
|
38
40
|
name?: string,
|
|
39
41
|
): ComponentContext<T> {
|
|
40
42
|
const id = Symbol(name ?? "context");
|
|
43
|
+
function Provider(props: ContextProviderProps<T>) {
|
|
44
|
+
const context = getContext();
|
|
45
|
+
|
|
46
|
+
const rendered = shallowRef();
|
|
47
|
+
effect(() => {
|
|
48
|
+
context!.context![id] = props.value;
|
|
49
|
+
rendered.value = () => props.children;
|
|
50
|
+
}, undefined);
|
|
51
|
+
|
|
52
|
+
return rendered.value;
|
|
53
|
+
}
|
|
41
54
|
const ctx = {
|
|
42
55
|
id,
|
|
43
56
|
default: defaultValue,
|
|
44
57
|
name,
|
|
45
|
-
Provider
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const rendered = shallowRef();
|
|
49
|
-
effect(() => {
|
|
50
|
-
context!.context![id] = props.value;
|
|
51
|
-
rendered.value = () => props.children;
|
|
52
|
-
}, undefined);
|
|
53
|
-
|
|
54
|
-
return rendered.value;
|
|
55
|
-
},
|
|
58
|
+
Provider,
|
|
59
|
+
ProviderStc: stc(Provider),
|
|
56
60
|
};
|
|
57
61
|
contextsByKey.set(id, ctx);
|
|
58
62
|
return ctx;
|
package/src/index.ts
CHANGED
package/src/jsx-runtime.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Much of the implementations in this file are inspired by vuerx-js
|
|
2
2
|
// See: https://github.com/ryansolid/vuerx-jsx.
|
|
3
3
|
import {
|
|
4
|
+
computed,
|
|
4
5
|
isReactive,
|
|
5
6
|
pauseTracking,
|
|
6
7
|
proxyRefs,
|
|
@@ -294,26 +295,131 @@ export function isComponentCreator(item: unknown): item is ComponentCreator {
|
|
|
294
295
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
295
296
|
export namespace JSX {
|
|
296
297
|
export interface IntrinsicElements {
|
|
298
|
+
/**
|
|
299
|
+
* Attempt to render the children on a single line if possible. If a group
|
|
300
|
+
* contains `<breakParent />` or a hard line, or if the group exceeds the
|
|
301
|
+
* print width, all linebreaks in the group will be broken.
|
|
302
|
+
*/
|
|
297
303
|
group: { shouldBreak?: boolean; id?: symbol; children: Children };
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* A regular line break. This will break if the line exceeds the print
|
|
307
|
+
* width, otherwise it will be a space.
|
|
308
|
+
*/
|
|
298
309
|
line: {};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* A regular line break. This will break if the line exceeds the print
|
|
313
|
+
* width, otherwise it will be a space.
|
|
314
|
+
*/
|
|
299
315
|
br: {};
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* A hard line break. This is a line that will always break, even if the
|
|
319
|
+
* group does not exceed print width.
|
|
320
|
+
*/
|
|
300
321
|
hardline: {};
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* A hard line break. This is a line that will always break, even if the
|
|
325
|
+
* group does not exceed print width.
|
|
326
|
+
*/
|
|
301
327
|
hbr: {};
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* A soft line break. This will break if the line exceeds the print width,
|
|
331
|
+
* otherwise it will be be nothing.
|
|
332
|
+
*/
|
|
302
333
|
softline: {};
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* A soft line break. This will break if the line exceeds the print width,
|
|
337
|
+
* otherwise it will be be nothing.
|
|
338
|
+
*/
|
|
303
339
|
sbr: {};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* A literal line break. This will always break, even if the group does not
|
|
343
|
+
* exceed print width. The new line will ignore indentation.
|
|
344
|
+
*/
|
|
304
345
|
literalline: {};
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* A literal line break. This will always break, even if the group does not
|
|
349
|
+
* exceed print width. The new line will ignore indentation.
|
|
350
|
+
*/
|
|
305
351
|
lbr: {};
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Increase the indentation level of the children of this component.
|
|
355
|
+
* Indentation is determined by the print options provided to the Output
|
|
356
|
+
* component or source file.
|
|
357
|
+
*/
|
|
306
358
|
indent: { children: Children };
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Indent the children of this component if the group specified by `groupId`
|
|
362
|
+
* is broken (or not broken if `negate` is passed). The specified group must
|
|
363
|
+
* already be printed.
|
|
364
|
+
*/
|
|
365
|
+
indentIfBreak: { children: Children; groupId: symbol; negate?: boolean };
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Similar to `group`, but will only place a line break before the last
|
|
369
|
+
* segment to exceed the print width. This is useful for formatting
|
|
370
|
+
* paragraphs of text where breaks are inserted prior to words which would
|
|
371
|
+
* otherwise exceed the print width.
|
|
372
|
+
*/
|
|
307
373
|
fill: { children: Children };
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Force the parent group to break.
|
|
377
|
+
*/
|
|
308
378
|
breakParent: {};
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Print children if the current group or already printed group specified by
|
|
382
|
+
* `groupId` is broken. Otherwise, `flatContents` is printed instead.
|
|
383
|
+
*/
|
|
309
384
|
ifBreak: { children: Children; flatContents?: Children; groupId?: symbol };
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Print this content at the end of the line. Useful for things like line
|
|
388
|
+
* comments.
|
|
389
|
+
*/
|
|
310
390
|
lineSuffix: { children: Children };
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Force any line suffixes to print at this point.
|
|
394
|
+
*/
|
|
311
395
|
lineSuffixBoundary: {};
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Decrease the indentation level of the children of this component.
|
|
399
|
+
* Indentation is determined by the print options provided to the Output
|
|
400
|
+
* component or source file.
|
|
401
|
+
*/
|
|
312
402
|
dedent: { children: Children };
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Indent the children of this component by either the number of characters
|
|
406
|
+
* indicated by the `width` prop, or by the provided string indicated by the
|
|
407
|
+
* `string` prop.
|
|
408
|
+
*/
|
|
313
409
|
align:
|
|
314
410
|
| { children: Children; width: number }
|
|
315
411
|
| { children: Children; string: string };
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Mark the current indentation level as "root" for the purposes of literal
|
|
415
|
+
* line breaks and `dedentToRoot`.
|
|
416
|
+
*/
|
|
316
417
|
markAsRoot: { children: Children };
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Decrease the indentation level to the root level specified by
|
|
421
|
+
* `<markAsRoot />`, or else to no indentation.
|
|
422
|
+
*/
|
|
317
423
|
dedentToRoot: { children: Children };
|
|
318
424
|
}
|
|
319
425
|
export type ElementType = string | ComponentDefinition<any>;
|
|
@@ -357,6 +463,8 @@ export function taggedComponent<TProps = Props>(
|
|
|
357
463
|
export const intrinsicElementKey = Symbol();
|
|
358
464
|
|
|
359
465
|
export type IndentIntrinsicElement = IntrinsicElementBase<"indent">;
|
|
466
|
+
export type IndentIfBreakIntrinsicElement =
|
|
467
|
+
IntrinsicElementBase<"indentIfBreak">;
|
|
360
468
|
export type BrIntrinsicElement = IntrinsicElementBase<"br">;
|
|
361
469
|
export type LineIntrinsicElement = IntrinsicElementBase<"line">;
|
|
362
470
|
export type HbrIntrinsicElement = IntrinsicElementBase<"hbr">;
|
|
@@ -379,6 +487,7 @@ export type IfBreakIntrinsicElement = IntrinsicElementBase<"ifBreak">;
|
|
|
379
487
|
|
|
380
488
|
export type IntrinsicElement =
|
|
381
489
|
| IndentIntrinsicElement
|
|
490
|
+
| IndentIfBreakIntrinsicElement
|
|
382
491
|
| BrIntrinsicElement
|
|
383
492
|
| LineIntrinsicElement
|
|
384
493
|
| HbrIntrinsicElement
|
|
@@ -514,6 +623,59 @@ export function splitProps<
|
|
|
514
623
|
return [...result, remaining] as any;
|
|
515
624
|
}
|
|
516
625
|
|
|
626
|
+
/**
|
|
627
|
+
* Applies default values to a props object. Reactive props are handled properly
|
|
628
|
+
* by ensuring that their value is not accessed by `defaultProps`, avoiding any
|
|
629
|
+
* unintended side effects.
|
|
630
|
+
*/
|
|
631
|
+
export function defaultProps<T extends {}>(props: T, defaults: Partial<T>): T {
|
|
632
|
+
if (isReactive(props)) {
|
|
633
|
+
const refs = untrack(() => toRefs(props));
|
|
634
|
+
for (const key in defaults) {
|
|
635
|
+
const originalRef = refs[key];
|
|
636
|
+
refs[key] = computed(() =>
|
|
637
|
+
originalRef.value === undefined ? defaults[key] : originalRef.value,
|
|
638
|
+
) as any;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return proxyRefs(refs);
|
|
642
|
+
}
|
|
643
|
+
const withDefaults = {} as T;
|
|
644
|
+
const copied = new Set<string>();
|
|
645
|
+
for (const key in defaults) {
|
|
646
|
+
copied.add(key);
|
|
647
|
+
const desc = Object.getOwnPropertyDescriptor(props, key);
|
|
648
|
+
if (!desc) {
|
|
649
|
+
withDefaults[key] = defaults[key]!;
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (desc.get) {
|
|
654
|
+
const originalGet = desc.get;
|
|
655
|
+
desc.get = function () {
|
|
656
|
+
const value = originalGet.call(this);
|
|
657
|
+
return value === undefined ? defaults[key as keyof T] : value;
|
|
658
|
+
};
|
|
659
|
+
Object.defineProperty(withDefaults, key, desc);
|
|
660
|
+
} else {
|
|
661
|
+
desc.value =
|
|
662
|
+
desc.value === undefined ? defaults[key as keyof T] : desc.value;
|
|
663
|
+
Object.defineProperty(withDefaults, key, desc);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const descriptors = Object.getOwnPropertyDescriptors(props);
|
|
668
|
+
for (const key in descriptors) {
|
|
669
|
+
if (copied.has(key)) {
|
|
670
|
+
continue;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
Object.defineProperty(withDefaults, key, descriptors[key]);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return withDefaults;
|
|
677
|
+
}
|
|
678
|
+
|
|
517
679
|
function shouldDebug() {
|
|
518
680
|
return typeof process !== "undefined" && !!process.env?.ALLOY_DEBUG;
|
|
519
681
|
}
|
package/src/render.ts
CHANGED
|
@@ -32,6 +32,7 @@ const {
|
|
|
32
32
|
group,
|
|
33
33
|
hardline,
|
|
34
34
|
indent,
|
|
35
|
+
indentIfBreak,
|
|
35
36
|
line,
|
|
36
37
|
lineSuffix,
|
|
37
38
|
lineSuffixBoundary,
|
|
@@ -348,6 +349,19 @@ function appendChild(node: RenderedTextTree, rawChild: Child) {
|
|
|
348
349
|
switch (child.name) {
|
|
349
350
|
case "indent":
|
|
350
351
|
return formatHookWithChildren(indent);
|
|
352
|
+
case "indentIfBreak":
|
|
353
|
+
node.push(
|
|
354
|
+
createRenderTreeHook(newNode, {
|
|
355
|
+
print(tree, print) {
|
|
356
|
+
return indentIfBreak(print(tree), {
|
|
357
|
+
groupId: child.props.groupId,
|
|
358
|
+
negate: child.props.negate,
|
|
359
|
+
});
|
|
360
|
+
},
|
|
361
|
+
}),
|
|
362
|
+
);
|
|
363
|
+
renderWorker(newNode, child.props.children);
|
|
364
|
+
return;
|
|
351
365
|
case "fill":
|
|
352
366
|
return formatHookWithChildren(fill as any);
|
|
353
367
|
case "group":
|
package/src/stc.ts
CHANGED
|
@@ -2,71 +2,40 @@ import {
|
|
|
2
2
|
Children,
|
|
3
3
|
ComponentCreator,
|
|
4
4
|
ComponentDefinition,
|
|
5
|
-
createIntrinsic,
|
|
6
|
-
IntrinsicElementBase,
|
|
7
|
-
JSX,
|
|
8
5
|
} from "@alloy-js/core/jsx-runtime";
|
|
9
|
-
import { code } from "./code.js";
|
|
10
|
-
|
|
11
|
-
export function sti<T extends keyof JSX.IntrinsicElements>(name: T) {
|
|
12
|
-
return (
|
|
13
|
-
...args: unknown extends T ? []
|
|
14
|
-
: {} extends Omit<JSX.IntrinsicElements[T], "children"> ?
|
|
15
|
-
[props?: JSX.IntrinsicElements[T]]
|
|
16
|
-
: [props: JSX.IntrinsicElements[T]]
|
|
17
|
-
) => {
|
|
18
|
-
const props: JSX.IntrinsicElements[T] | undefined = args[0];
|
|
19
|
-
const fn = () => createIntrinsic(name, props!);
|
|
20
|
-
fn.children = (
|
|
21
|
-
...children: Children[]
|
|
22
|
-
): (() => IntrinsicElementBase<T>) => {
|
|
23
|
-
const propsWithChildren = {
|
|
24
|
-
...(props ?? {}),
|
|
25
|
-
children,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
return () => createIntrinsic(name, propsWithChildren as any);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
fn.code = (
|
|
32
|
-
template: TemplateStringsArray,
|
|
33
|
-
...substitutions: Children[]
|
|
34
|
-
): (() => IntrinsicElementBase<T>) => {
|
|
35
|
-
const propsWithChildren = {
|
|
36
|
-
...(args[0] ?? {}),
|
|
37
|
-
children: code(template, ...substitutions),
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
return () => createIntrinsic(name, propsWithChildren as any);
|
|
41
|
-
};
|
|
42
|
-
return fn;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
6
|
+
import { code, text } from "./code.js";
|
|
45
7
|
|
|
46
8
|
export type MakeChildrenOptional<T extends object> =
|
|
47
9
|
T extends { children?: any } ?
|
|
48
10
|
Omit<T, "children"> & Partial<Pick<T, "children">>
|
|
49
11
|
: T;
|
|
50
12
|
|
|
51
|
-
export
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
13
|
+
export type StcSignature<T extends {}> = (
|
|
14
|
+
...args: unknown extends T ? []
|
|
15
|
+
: {} extends Omit<T, "children"> ? [props?: MakeChildrenOptional<T>]
|
|
16
|
+
: [props: MakeChildrenOptional<T>]
|
|
17
|
+
) => StcComponentCreator<T>;
|
|
18
|
+
|
|
19
|
+
export type StcComponentCreator<T> = ComponentCreator<T> & {
|
|
20
|
+
code(
|
|
21
|
+
template: TemplateStringsArray,
|
|
22
|
+
...substitutions: Children[]
|
|
23
|
+
): ComponentCreator<T>;
|
|
24
|
+
text(
|
|
25
|
+
template: TemplateStringsArray,
|
|
26
|
+
...substitutions: Children[]
|
|
27
|
+
): ComponentCreator<T>;
|
|
28
|
+
children(...children: Children[]): ComponentCreator<T>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function stc<T extends {}>(
|
|
32
|
+
Component: ComponentDefinition<T>,
|
|
33
|
+
): StcSignature<T> {
|
|
34
|
+
return (...args) => {
|
|
35
|
+
const fn: StcComponentCreator<T> = () => Component(args[0] as any);
|
|
64
36
|
fn.component = Component;
|
|
65
37
|
fn.props = args[0]!;
|
|
66
|
-
fn.code = (
|
|
67
|
-
template: TemplateStringsArray,
|
|
68
|
-
...substitutions: Children[]
|
|
69
|
-
): ComponentCreator<T> => {
|
|
38
|
+
fn.code = (template, ...substitutions): ComponentCreator<T> => {
|
|
70
39
|
const propsWithChildren = {
|
|
71
40
|
...(args[0] ?? {}),
|
|
72
41
|
children: code(template, ...substitutions),
|
|
@@ -77,7 +46,17 @@ export function stc<T extends {}>(Component: ComponentDefinition<T>) {
|
|
|
77
46
|
fn.props = args[0]!;
|
|
78
47
|
return fn;
|
|
79
48
|
};
|
|
49
|
+
fn.text = (template, ...substitutions) => {
|
|
50
|
+
const propsWithChildren = {
|
|
51
|
+
...(args[0] ?? {}),
|
|
52
|
+
children: text(template, ...substitutions),
|
|
53
|
+
};
|
|
80
54
|
|
|
55
|
+
const fn = () => Component(propsWithChildren as any);
|
|
56
|
+
fn.component = Component;
|
|
57
|
+
fn.props = args[0]!;
|
|
58
|
+
return fn;
|
|
59
|
+
};
|
|
81
60
|
fn.children = (...children: Children[]): ComponentCreator<T> => {
|
|
82
61
|
const propsWithChildren = {
|
|
83
62
|
...(args[0] ?? {}),
|
package/src/sti.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Children,
|
|
3
|
+
createIntrinsic,
|
|
4
|
+
IntrinsicElementBase,
|
|
5
|
+
JSX,
|
|
6
|
+
} from "@alloy-js/core/jsx-runtime";
|
|
7
|
+
import { code, text } from "./code.js";
|
|
8
|
+
|
|
9
|
+
export type StiSignature<T extends keyof JSX.IntrinsicElements> = (
|
|
10
|
+
...args: unknown extends T ? []
|
|
11
|
+
: {} extends Omit<JSX.IntrinsicElements[T], "children"> ?
|
|
12
|
+
[props?: JSX.IntrinsicElements[T]]
|
|
13
|
+
: [props: JSX.IntrinsicElements[T]]
|
|
14
|
+
) => StiComponentCreator<T>;
|
|
15
|
+
|
|
16
|
+
export type StiComponentCreator<T extends keyof JSX.IntrinsicElements> =
|
|
17
|
+
(() => IntrinsicElementBase<T>) & {
|
|
18
|
+
code(
|
|
19
|
+
template: TemplateStringsArray,
|
|
20
|
+
...substitutions: Children[]
|
|
21
|
+
): () => IntrinsicElementBase<T>;
|
|
22
|
+
text(
|
|
23
|
+
template: TemplateStringsArray,
|
|
24
|
+
...substitutions: Children[]
|
|
25
|
+
): () => IntrinsicElementBase<T>;
|
|
26
|
+
children(...children: Children[]): () => IntrinsicElementBase<T>;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function sti<T extends keyof JSX.IntrinsicElements>(
|
|
30
|
+
name: T,
|
|
31
|
+
): StiSignature<T> {
|
|
32
|
+
return (...args) => {
|
|
33
|
+
const props: JSX.IntrinsicElements[T] | undefined = args[0];
|
|
34
|
+
const fn: StiComponentCreator<T> = () => createIntrinsic(name, props!);
|
|
35
|
+
fn.children = (...children: Children[]) => {
|
|
36
|
+
const propsWithChildren = {
|
|
37
|
+
...(props ?? {}),
|
|
38
|
+
children,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return () => createIntrinsic(name, propsWithChildren as any);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
fn.code = (template, ...substitutions) => {
|
|
45
|
+
const propsWithChildren = {
|
|
46
|
+
...(args[0] ?? {}),
|
|
47
|
+
children: code(template, ...substitutions),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return () => createIntrinsic(name, propsWithChildren as any);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
fn.text = (template, ...substitutions) => {
|
|
54
|
+
const propsWithChildren = {
|
|
55
|
+
...(args[0] ?? {}),
|
|
56
|
+
children: text(template, ...substitutions),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return () => createIntrinsic(name, propsWithChildren as any);
|
|
60
|
+
};
|
|
61
|
+
return fn;
|
|
62
|
+
};
|
|
63
|
+
}
|