@alloy-js/core 0.1.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.
Files changed (229) hide show
  1. package/LICENSE.txt +7 -0
  2. package/api-extractor.json +11 -0
  3. package/babel.config.cjs +4 -0
  4. package/dist/src/binder.d.ts +333 -0
  5. package/dist/src/binder.d.ts.map +1 -0
  6. package/dist/src/binder.js +444 -0
  7. package/dist/src/binder.js.map +1 -0
  8. package/dist/src/code.d.ts +3 -0
  9. package/dist/src/code.d.ts.map +1 -0
  10. package/dist/src/code.js +156 -0
  11. package/dist/src/code.js.map +1 -0
  12. package/dist/src/components/Declaration.d.ts +29 -0
  13. package/dist/src/components/Declaration.d.ts.map +1 -0
  14. package/dist/src/components/Declaration.js +47 -0
  15. package/dist/src/components/Declaration.js.map +1 -0
  16. package/dist/src/components/Indent.d.ts +13 -0
  17. package/dist/src/components/Indent.d.ts.map +1 -0
  18. package/dist/src/components/Indent.js +23 -0
  19. package/dist/src/components/Indent.js.map +1 -0
  20. package/dist/src/components/MemberDeclaration.d.ts +30 -0
  21. package/dist/src/components/MemberDeclaration.d.ts.map +1 -0
  22. package/dist/src/components/MemberDeclaration.js +52 -0
  23. package/dist/src/components/MemberDeclaration.js.map +1 -0
  24. package/dist/src/components/MemberName.d.ts +2 -0
  25. package/dist/src/components/MemberName.d.ts.map +1 -0
  26. package/dist/src/components/MemberName.js +11 -0
  27. package/dist/src/components/MemberName.js.map +1 -0
  28. package/dist/src/components/MemberScope.d.ts +27 -0
  29. package/dist/src/components/MemberScope.d.ts.map +1 -0
  30. package/dist/src/components/MemberScope.js +28 -0
  31. package/dist/src/components/MemberScope.js.map +1 -0
  32. package/dist/src/components/Name.d.ts +2 -0
  33. package/dist/src/components/Name.d.ts.map +1 -0
  34. package/dist/src/components/Name.js +11 -0
  35. package/dist/src/components/Name.js.map +1 -0
  36. package/dist/src/components/Output.d.ts +31 -0
  37. package/dist/src/components/Output.d.ts.map +1 -0
  38. package/dist/src/components/Output.js +44 -0
  39. package/dist/src/components/Output.js.map +1 -0
  40. package/dist/src/components/Scope.d.ts +10 -0
  41. package/dist/src/components/Scope.d.ts.map +1 -0
  42. package/dist/src/components/Scope.js +25 -0
  43. package/dist/src/components/Scope.js.map +1 -0
  44. package/dist/src/components/SourceDirectory.d.ts +7 -0
  45. package/dist/src/components/SourceDirectory.d.ts.map +1 -0
  46. package/dist/src/components/SourceDirectory.js +38 -0
  47. package/dist/src/components/SourceDirectory.js.map +1 -0
  48. package/dist/src/components/SourceFile.d.ts +12 -0
  49. package/dist/src/components/SourceFile.d.ts.map +1 -0
  50. package/dist/src/components/SourceFile.js +26 -0
  51. package/dist/src/components/SourceFile.js.map +1 -0
  52. package/dist/src/components/index.d.ts +11 -0
  53. package/dist/src/components/index.d.ts.map +1 -0
  54. package/dist/src/components/index.js +11 -0
  55. package/dist/src/components/index.js.map +1 -0
  56. package/dist/src/components/stc/index.d.ts +26 -0
  57. package/dist/src/components/stc/index.d.ts.map +1 -0
  58. package/dist/src/components/stc/index.js +9 -0
  59. package/dist/src/components/stc/index.js.map +1 -0
  60. package/dist/src/context/assignment.d.ts +39 -0
  61. package/dist/src/context/assignment.d.ts.map +1 -0
  62. package/dist/src/context/assignment.js +39 -0
  63. package/dist/src/context/assignment.js.map +1 -0
  64. package/dist/src/context/binder.d.ts +9 -0
  65. package/dist/src/context/binder.d.ts.map +1 -0
  66. package/dist/src/context/binder.js +12 -0
  67. package/dist/src/context/binder.js.map +1 -0
  68. package/dist/src/context/declaration.d.ts +4 -0
  69. package/dist/src/context/declaration.d.ts.map +1 -0
  70. package/dist/src/context/declaration.js +3 -0
  71. package/dist/src/context/declaration.js.map +1 -0
  72. package/dist/src/context/indent.d.ts +5 -0
  73. package/dist/src/context/indent.d.ts.map +1 -0
  74. package/dist/src/context/indent.js +8 -0
  75. package/dist/src/context/indent.js.map +1 -0
  76. package/dist/src/context/index.d.ts +11 -0
  77. package/dist/src/context/index.d.ts.map +1 -0
  78. package/dist/src/context/index.js +11 -0
  79. package/dist/src/context/index.js.map +1 -0
  80. package/dist/src/context/member-declaration.d.ts +9 -0
  81. package/dist/src/context/member-declaration.d.ts.map +1 -0
  82. package/dist/src/context/member-declaration.js +9 -0
  83. package/dist/src/context/member-declaration.js.map +1 -0
  84. package/dist/src/context/member-scope.d.ts +13 -0
  85. package/dist/src/context/member-scope.d.ts.map +1 -0
  86. package/dist/src/context/member-scope.js +12 -0
  87. package/dist/src/context/member-scope.js.map +1 -0
  88. package/dist/src/context/name-policy.d.ts +5 -0
  89. package/dist/src/context/name-policy.d.ts.map +1 -0
  90. package/dist/src/context/name-policy.js +10 -0
  91. package/dist/src/context/name-policy.js.map +1 -0
  92. package/dist/src/context/scope.d.ts +5 -0
  93. package/dist/src/context/scope.d.ts.map +1 -0
  94. package/dist/src/context/scope.js +6 -0
  95. package/dist/src/context/scope.js.map +1 -0
  96. package/dist/src/context/source-directory.d.ts +9 -0
  97. package/dist/src/context/source-directory.d.ts.map +1 -0
  98. package/dist/src/context/source-directory.js +3 -0
  99. package/dist/src/context/source-directory.js.map +1 -0
  100. package/dist/src/context/source-file.d.ts +12 -0
  101. package/dist/src/context/source-file.d.ts.map +1 -0
  102. package/dist/src/context/source-file.js +3 -0
  103. package/dist/src/context/source-file.js.map +1 -0
  104. package/dist/src/context.d.ts +13 -0
  105. package/dist/src/context.d.ts.map +1 -0
  106. package/dist/src/context.js +30 -0
  107. package/dist/src/context.js.map +1 -0
  108. package/dist/src/index.d.ts +13 -0
  109. package/dist/src/index.d.ts.map +1 -0
  110. package/dist/src/index.js +13 -0
  111. package/dist/src/index.js.map +1 -0
  112. package/dist/src/jsx-runtime.d.ts +43 -0
  113. package/dist/src/jsx-runtime.d.ts.map +1 -0
  114. package/dist/src/jsx-runtime.js +172 -0
  115. package/dist/src/jsx-runtime.js.map +1 -0
  116. package/dist/src/name-policy.d.ts +5 -0
  117. package/dist/src/name-policy.d.ts.map +1 -0
  118. package/dist/src/name-policy.js +8 -0
  119. package/dist/src/name-policy.js.map +1 -0
  120. package/dist/src/refkey.d.ts +9 -0
  121. package/dist/src/refkey.d.ts.map +1 -0
  122. package/dist/src/refkey.js +44 -0
  123. package/dist/src/refkey.js.map +1 -0
  124. package/dist/src/render.d.ts +147 -0
  125. package/dist/src/render.d.ts.map +1 -0
  126. package/dist/src/render.js +317 -0
  127. package/dist/src/render.js.map +1 -0
  128. package/dist/src/tsdoc-metadata.json +11 -0
  129. package/dist/src/utils.d.ts +80 -0
  130. package/dist/src/utils.d.ts.map +1 -0
  131. package/dist/src/utils.js +219 -0
  132. package/dist/src/utils.js.map +1 -0
  133. package/dist/test/children.test.d.ts +2 -0
  134. package/dist/test/children.test.d.ts.map +1 -0
  135. package/dist/test/components/source-file.test.d.ts +2 -0
  136. package/dist/test/components/source-file.test.d.ts.map +1 -0
  137. package/dist/test/name-policy.test.d.ts +2 -0
  138. package/dist/test/name-policy.test.d.ts.map +1 -0
  139. package/dist/test/reactivity/ref-rendering.test.d.ts +2 -0
  140. package/dist/test/reactivity/ref-rendering.test.d.ts.map +1 -0
  141. package/dist/test/reactivity/test.test.d.ts +2 -0
  142. package/dist/test/reactivity/test.test.d.ts.map +1 -0
  143. package/dist/test/refkey.test.d.ts +2 -0
  144. package/dist/test/refkey.test.d.ts.map +1 -0
  145. package/dist/test/rendering/basic.test.d.ts +2 -0
  146. package/dist/test/rendering/basic.test.d.ts.map +1 -0
  147. package/dist/test/rendering/code.test.d.ts +2 -0
  148. package/dist/test/rendering/code.test.d.ts.map +1 -0
  149. package/dist/test/rendering/indent.test.d.ts +2 -0
  150. package/dist/test/rendering/indent.test.d.ts.map +1 -0
  151. package/dist/test/rendering/linebreaks.test.d.ts +2 -0
  152. package/dist/test/rendering/linebreaks.test.d.ts.map +1 -0
  153. package/dist/test/rendering/refkeys.test.d.ts +2 -0
  154. package/dist/test/rendering/refkeys.test.d.ts.map +1 -0
  155. package/dist/test/stc.test.d.ts +2 -0
  156. package/dist/test/stc.test.d.ts.map +1 -0
  157. package/dist/test/symbols.test.d.ts +2 -0
  158. package/dist/test/symbols.test.d.ts.map +1 -0
  159. package/dist/test/utils.test.d.ts +2 -0
  160. package/dist/test/utils.test.d.ts.map +1 -0
  161. package/dist/testing/extend-expect.d.ts +2 -0
  162. package/dist/testing/extend-expect.d.ts.map +1 -0
  163. package/dist/testing/extend-expect.js +22 -0
  164. package/dist/testing/extend-expect.js.map +1 -0
  165. package/dist/testing/index.d.ts +3 -0
  166. package/dist/testing/index.d.ts.map +1 -0
  167. package/dist/testing/index.js +3 -0
  168. package/dist/testing/index.js.map +1 -0
  169. package/dist/testing/render.d.ts +7 -0
  170. package/dist/testing/render.d.ts.map +1 -0
  171. package/dist/testing/render.js +25 -0
  172. package/dist/testing/render.js.map +1 -0
  173. package/dist/testing/vitest.d.js +1 -0
  174. package/dist/testing/vitest.d.js.map +1 -0
  175. package/dist/tsconfig.tsbuildinfo +1 -0
  176. package/package.json +64 -0
  177. package/src/binder.ts +838 -0
  178. package/src/code.ts +220 -0
  179. package/src/components/Declaration.tsx +53 -0
  180. package/src/components/Indent.tsx +33 -0
  181. package/src/components/MemberDeclaration.tsx +62 -0
  182. package/src/components/MemberName.tsx +11 -0
  183. package/src/components/MemberScope.tsx +40 -0
  184. package/src/components/Name.tsx +11 -0
  185. package/src/components/Output.tsx +69 -0
  186. package/src/components/Scope.tsx +27 -0
  187. package/src/components/SourceDirectory.tsx +43 -0
  188. package/src/components/SourceFile.tsx +33 -0
  189. package/src/components/index.tsx +10 -0
  190. package/src/components/stc/index.ts +9 -0
  191. package/src/context/assignment.ts +57 -0
  192. package/src/context/binder.ts +14 -0
  193. package/src/context/declaration.ts +5 -0
  194. package/src/context/indent.ts +10 -0
  195. package/src/context/index.ts +10 -0
  196. package/src/context/member-declaration.ts +10 -0
  197. package/src/context/member-scope.ts +17 -0
  198. package/src/context/name-policy.ts +13 -0
  199. package/src/context/scope.ts +8 -0
  200. package/src/context/source-directory.ts +11 -0
  201. package/src/context/source-file.ts +12 -0
  202. package/src/context.ts +53 -0
  203. package/src/index.ts +21 -0
  204. package/src/jsx-runtime.ts +266 -0
  205. package/src/name-policy.ts +13 -0
  206. package/src/refkey.ts +62 -0
  207. package/src/render.ts +389 -0
  208. package/src/utils.ts +288 -0
  209. package/temp/api.json +8840 -0
  210. package/test/children.test.tsx +33 -0
  211. package/test/components/source-file.test.tsx +45 -0
  212. package/test/name-policy.test.tsx +19 -0
  213. package/test/reactivity/ref-rendering.test.tsx +50 -0
  214. package/test/reactivity/test.test.tsx +83 -0
  215. package/test/refkey.test.ts +32 -0
  216. package/test/rendering/basic.test.tsx +156 -0
  217. package/test/rendering/code.test.tsx +62 -0
  218. package/test/rendering/indent.test.tsx +608 -0
  219. package/test/rendering/linebreaks.test.tsx +72 -0
  220. package/test/rendering/refkeys.test.tsx +35 -0
  221. package/test/stc.test.tsx +21 -0
  222. package/test/symbols.test.ts +406 -0
  223. package/test/utils.test.tsx +150 -0
  224. package/testing/extend-expect.ts +20 -0
  225. package/testing/index.ts +2 -0
  226. package/testing/render.ts +37 -0
  227. package/testing/vitest.d.ts +10 -0
  228. package/tsconfig.json +17 -0
  229. package/vitest.config.ts +18 -0
@@ -0,0 +1,33 @@
1
+ import { children, Children, renderTree } from "@alloy-js/core";
2
+ import { expect, it } from "vitest";
3
+ import { d, printTree } from "../testing/render.js";
4
+
5
+ it("handles a single element", () => {
6
+ function Foo(props: { children?: Children }) {
7
+ return children(() => props.children);
8
+ }
9
+
10
+ const res = renderTree(<Foo>a b c</Foo>);
11
+ expect(printTree(res)).toBe("a b c");
12
+ });
13
+
14
+ it("handles a multiple elements", () => {
15
+ function Foo(props: { children?: Children }) {
16
+ const c = children(() => props.children);
17
+ return c;
18
+ }
19
+
20
+ function Bar() {
21
+ return "Bar";
22
+ }
23
+
24
+ const res = renderTree(<Foo>
25
+ <Bar />
26
+ <Bar />
27
+ </Foo>);
28
+
29
+ expect(printTree(res)).toBe(d`
30
+ Bar
31
+ Bar
32
+ `);
33
+ });
@@ -0,0 +1,45 @@
1
+ import {
2
+ computed,
3
+ Output,
4
+ render,
5
+ renderTree,
6
+ SourceFile,
7
+ useContext,
8
+ } from "@alloy-js/core";
9
+ import { expect, it } from "vitest";
10
+ import { SourceDirectoryContext } from "../../src/context/source-directory.js";
11
+ import "../../testing/extend-expect.js";
12
+
13
+ it("tracks its content", () => {
14
+ let context;
15
+ function Test() {
16
+ context = useContext(SourceDirectoryContext);
17
+ }
18
+ const _ = renderTree(
19
+ <Output>
20
+ <Test />
21
+ <SourceFile path="hi.txt" filetype="text">hello!</SourceFile>
22
+ </Output>,
23
+ );
24
+ expect(context!.contents.length).toEqual(1);
25
+ });
26
+
27
+ it("has reactive context", () => {
28
+ function TrackContents() {
29
+ const sdContext = useContext(SourceDirectoryContext)!;
30
+ const allFiles = computed(() => {
31
+ return sdContext.contents.map((v) => v.path).join(" ");
32
+ });
33
+
34
+ return <SourceFile path="contents.txt" filetype="text">{allFiles.value}</SourceFile>;
35
+ }
36
+
37
+ const tree = render(
38
+ <Output>
39
+ <SourceFile path="hi.txt" filetype="text">hello!</SourceFile>
40
+ <TrackContents />
41
+ </Output>,
42
+ );
43
+
44
+ expect(tree.contents[1].contents).toEqual("hi.txt contents.txt");
45
+ });
@@ -0,0 +1,19 @@
1
+ import { createNamePolicy, Output, useNamePolicy } from "@alloy-js/core";
2
+ import { expect, it } from "vitest";
3
+ import "../testing/extend-expect.js";
4
+
5
+ it("is applied by output", () => {
6
+ const policy = createNamePolicy((name) => {
7
+ return "name" + name;
8
+ });
9
+
10
+ function Foo() {
11
+ const namer = useNamePolicy();
12
+ return namer!.getName("hi", "name");
13
+ }
14
+ expect(<Output namePolicy={policy}>
15
+ <Foo />
16
+ </Output>).toRenderTo(
17
+ "namehi",
18
+ );
19
+ });
@@ -0,0 +1,50 @@
1
+ import { code, memo, renderTree } from "@alloy-js/core";
2
+ import { ref } from "@vue/reactivity";
3
+ import { expect, it } from "vitest";
4
+ import { printTree } from "../../testing/render.js";
5
+
6
+ it("handles refs in the tree", () => {
7
+ const r = ref(42);
8
+ const tree = renderTree(<>
9
+ The number is {r}
10
+ </>);
11
+
12
+ expect(printTree(tree)).toBe("The number is 42");
13
+ r.value = 12;
14
+ expect(printTree(tree)).toBe("The number is 12");
15
+ });
16
+
17
+ it("handles refs in the tree with code", () => {
18
+ const r = ref(42);
19
+ const tree = renderTree(code`
20
+ The number is ${r}
21
+ `);
22
+
23
+ expect(printTree(tree)).toBe("The number is 42");
24
+ r.value = 12;
25
+ expect(printTree(tree)).toBe("The number is 12");
26
+ });
27
+
28
+ it("handles memos in the tree", () => {
29
+ const r = ref(42);
30
+ const m = memo(() => r.value + 10);
31
+ const tree = renderTree(<>
32
+ The number is {m}
33
+ </>);
34
+
35
+ expect(printTree(tree)).toBe("The number is 52");
36
+ r.value = 12;
37
+ expect(printTree(tree)).toBe("The number is 22");
38
+ });
39
+
40
+ it("handles memos in the tree with code", () => {
41
+ const r = ref(42);
42
+ const m = memo(() => r.value + 10);
43
+ const tree = renderTree(code`
44
+ The number is ${m}
45
+ `);
46
+
47
+ expect(printTree(tree)).toBe("The number is 52");
48
+ r.value = 12;
49
+ expect(printTree(tree)).toBe("The number is 22");
50
+ });
@@ -0,0 +1,83 @@
1
+ import { memo, renderTree } from "@alloy-js/core";
2
+ import { computed, reactive, ref } from "@vue/reactivity";
3
+ import { expect, it } from "vitest";
4
+ import { mapJoin } from "../../src/utils.js";
5
+ import { d, printTree } from "../../testing/render.js";
6
+
7
+ it("splices in new nodes", () => {
8
+ const r = ref(["one"]);
9
+ const mapped = computed(() => {
10
+ return r.value.map((v) => `mapped ${v}`).join(" ");
11
+ });
12
+
13
+ function Foo() {
14
+ return <>{mapped.value} done</>;
15
+ }
16
+
17
+ const tree = renderTree(<Foo />);
18
+ expect(printTree(tree)).toEqual("mapped one done");
19
+ r.value = [...r.value, "two"];
20
+
21
+ expect(printTree(tree)).toEqual("mapped one mapped two done");
22
+ });
23
+
24
+ it("works with a complex case", () => {
25
+ const importRecords: Map<string, Set<string>> = reactive(new Map());
26
+
27
+ function addImport(path: string, type: string) {
28
+ if (!importRecords.has(path)) {
29
+ importRecords.set(path, new Set());
30
+ }
31
+
32
+ importRecords.get(path)!.add(type);
33
+ }
34
+
35
+ interface ImportStatementsProps {
36
+ records: Map<string, Set<string>>;
37
+ }
38
+
39
+ function ImportStatements(props: ImportStatementsProps) {
40
+ return memo(() =>
41
+ mapJoin(props.records, (
42
+ path,
43
+ types,
44
+ ) => <ImportStatement path={path} types={types} />));
45
+ }
46
+
47
+ interface ImportStatementProps {
48
+ path: string;
49
+ types: Set<string>;
50
+ }
51
+
52
+ function ImportStatement(props: ImportStatementProps) {
53
+ // when the `code` template tag is implemented, the lambda won't be needed.
54
+ return () =>
55
+ `import { ${[...props.types.values()].join(", ")} } from "${props.path}";`;
56
+ }
57
+
58
+ const tree = renderTree(<ImportStatements records={importRecords} />);
59
+ // the tree is empty.
60
+
61
+ expect(printTree(tree)).toEqual("");
62
+
63
+ addImport("./foo.js", "hi");
64
+ printTree(tree);
65
+ expect(printTree(tree)).toEqual('import { hi } from "./foo.js";');
66
+
67
+ addImport("./foo.js", "bye");
68
+ expect(printTree(tree)).toEqual('import { hi, bye } from "./foo.js";');
69
+
70
+ addImport("node:assert", "strictEqual");
71
+ expect(printTree(tree)).toEqual(d`
72
+ import { hi, bye } from "./foo.js";
73
+ import { strictEqual } from "node:assert";
74
+ `);
75
+ });
76
+
77
+ it("works with memos of memos", () => {
78
+ const test = ref(1);
79
+ const tree = renderTree(memo(() => memo(() => test.value)));
80
+ expect(printTree(tree)).toEqual("1");
81
+ test.value = 2;
82
+ expect(printTree(tree)).toEqual("2");
83
+ });
@@ -0,0 +1,32 @@
1
+ import { expect, it } from "vitest";
2
+ import { refkey } from "../src/refkey.js";
3
+
4
+ it("is stable when called with same values", () => {
5
+ const obj = {};
6
+
7
+ const key1 = refkey(obj);
8
+ const key2 = refkey(obj);
9
+ expect(key1).toBe(key2);
10
+ });
11
+
12
+ it("supports primitive values", () => {
13
+ const key1 = refkey("hi");
14
+ const key2 = refkey("hi");
15
+ expect(key1).toBe(key2);
16
+ });
17
+
18
+ it("composes multiple keys", () => {
19
+ const obj1 = {};
20
+ const obj2 = {};
21
+
22
+ const key1 = refkey(obj1, obj2, "hi");
23
+ const key2 = refkey(obj1, obj2, "hi");
24
+
25
+ expect(key1).toBe(key2);
26
+ });
27
+
28
+ it("can be called with no args and returns a fresh key", () => {
29
+ const key1 = refkey();
30
+ const key2 = refkey();
31
+ expect(key1).not.toBe(key2);
32
+ });
@@ -0,0 +1,156 @@
1
+ import { Children } from "@alloy-js/core/jsx-runtime";
2
+ import { describe, expect, it } from "vitest";
3
+ import "../../testing/extend-expect.js";
4
+ describe("string nodes", () => {
5
+ it("renders string nodes", () => {
6
+ expect(<>
7
+ a
8
+ b
9
+ c
10
+ </>).toRenderTo(`
11
+ a
12
+ b
13
+ c
14
+ `);
15
+ });
16
+
17
+ it("renders string nodes with substitutions", () => {
18
+ const str = "hi";
19
+ expect(<>
20
+ a {str}
21
+ {str}
22
+ </>).toRenderTo(`
23
+ a hi
24
+ hi
25
+ `);
26
+ });
27
+ });
28
+
29
+ describe("component nodes", () => {
30
+ function Str() {
31
+ return "Str";
32
+ }
33
+
34
+ function Arr() {
35
+ return ["Item 1", "\n" + "Item 2"];
36
+ }
37
+
38
+ function Nested() {
39
+ return <Str />;
40
+ }
41
+
42
+ it("renders basic component", () => {
43
+ expect(<Str />).toRenderTo("Str");
44
+ });
45
+
46
+ it("renders array components", () => {
47
+ expect(<Arr />).toRenderTo("Item 1\nItem 2");
48
+ });
49
+
50
+ it("renders nested components", () => {
51
+ expect(<Nested />).toRenderTo("Str");
52
+ });
53
+
54
+ it("renders components on same line", () => {
55
+ expect(<>
56
+ <Str /> <Str />
57
+ </>).toRenderTo("Str Str");
58
+ });
59
+
60
+ it("renders components on multiple lines", () => {
61
+ expect(<>
62
+ <Str /> <Str />
63
+ <Arr /> <Arr />
64
+ </>).toRenderTo(`
65
+ Str Str
66
+ Item 1
67
+ Item 2 Item 1
68
+ Item 2
69
+ `);
70
+ });
71
+ });
72
+
73
+ describe("memo nodes", () => {
74
+ function getStr() {
75
+ return "Str";
76
+ }
77
+ function Foo() {
78
+ return "Foo";
79
+ }
80
+ function getFoo() {
81
+ return <Foo />;
82
+ }
83
+ function getArr() {
84
+ return [<Foo />, "\n", <Foo />];
85
+ }
86
+
87
+ it("renders basic memos", () => {
88
+ expect(<>
89
+ {getStr()}
90
+ </>).toRenderTo("Str");
91
+ });
92
+
93
+ it("renders component memos", () => {
94
+ expect(<>
95
+ {getFoo()}
96
+ </>).toRenderTo("Foo");
97
+ });
98
+
99
+ it("renders array memos", () => {
100
+ expect(<>
101
+ {getArr()}
102
+ </>).toRenderTo("Foo\nFoo");
103
+ });
104
+ });
105
+
106
+ describe("array nodes", () => {
107
+ it("renders basic arrays", () => {
108
+ expect([["hi", " ", "hi"]]).toRenderTo("hi hi");
109
+ });
110
+ });
111
+
112
+ it("renders text fragments", () => {
113
+ function Foo() {
114
+ return "bye";
115
+ }
116
+
117
+ expect(<>
118
+ hi
119
+ <Foo />
120
+ </>).toRenderTo(`
121
+ hi
122
+ bye
123
+ `);
124
+ });
125
+
126
+ it("renders basic components", () => {
127
+ function Bar(props: { children?: Children }) {
128
+ return props.children;
129
+ }
130
+
131
+ function Foo() {
132
+ return <Bar>hello</Bar>;
133
+ }
134
+
135
+ expect(<Foo />).toRenderTo("hello");
136
+ });
137
+
138
+ it("renders booleans appropriately", () => {
139
+ function Foo() {
140
+ return false;
141
+ }
142
+
143
+ expect(<Foo />).toRenderTo("");
144
+ });
145
+
146
+ it("keeps spaces between expressions", () => {
147
+ const str = "str";
148
+ function getStr() {
149
+ return "getStr";
150
+ }
151
+ expect(<>
152
+ a {str} {str} {getStr()} {getStr()} c
153
+ </>).toRenderTo(
154
+ "a str str getStr getStr c",
155
+ );
156
+ });
@@ -0,0 +1,62 @@
1
+ import { code } from "@alloy-js/core";
2
+ import { expect, it } from "vitest";
3
+ import "../../testing/extend-expect.js";
4
+
5
+ it("renders simple strings", () => {
6
+ expect(code`foo`).toRenderTo("foo");
7
+ });
8
+
9
+ it("renders removes indents", () => {
10
+ expect(code`
11
+ foo
12
+ `).toRenderTo("foo");
13
+ });
14
+
15
+ it("renders allows substitutions of elements", () => {
16
+ function Foo() {
17
+ return "hi";
18
+ }
19
+ expect(code`
20
+ foo ${<Foo />} bar
21
+ `).toRenderTo("foo hi bar");
22
+ });
23
+
24
+ it("renders has auto-indentation", () => {
25
+ function Foo() {
26
+ return code`
27
+ hi
28
+ bye
29
+ `;
30
+ }
31
+
32
+ const template = code`
33
+ if (x === 1) {
34
+ ${<Foo />}
35
+ }
36
+ `;
37
+
38
+ expect(template).toRenderTo(`
39
+ if (x === 1) {
40
+ hi
41
+ bye
42
+ }
43
+ `);
44
+ });
45
+
46
+ it("handles blank lines", () => {
47
+ const template = code`
48
+ {
49
+ a
50
+
51
+ x
52
+ }
53
+ `;
54
+
55
+ expect(template).toRenderTo(`
56
+ {
57
+ a
58
+
59
+ x
60
+ }
61
+ `);
62
+ });