@sigil-dev/compiler 0.9.10 → 0.9.12
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/package.json +3 -1
- package/src/babel/handlers/dom/state.ts +4 -5
- package/src/babel/index.ts +75 -26
- package/src/babel/jsx/children.ts +10 -2
- package/src/babel/jsx/element.ts +205 -110
- package/src/babel/jsx/fragment.ts +15 -3
- package/src/babel/jsx/keyed-list.ts +10 -2
- package/src/babel/jsx/ssr.ts +136 -253
- package/src/babel/jsx/utils.ts +47 -1
- package/src/babel/util/bind.ts +4 -0
- package/src/babel/util/css.ts +170 -113
- package/src/babel/util/props.ts +256 -0
- package/src/bun-plugin.ts +28 -17
- package/src/vite/index.ts +4 -1
- package/test/bun-plugin.test.ts +45 -0
- package/test/hydration.test.ts +3 -2
- package/test/jsx.test.ts +26 -4
- package/test/render-parity.test.ts +639 -0
- package/test/scoped-css.test.ts +39 -2
- package/test/ssr.test.ts +1 -1
- package/test/style-object.test.ts +29 -6
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { afterAll, beforeAll, expect, test } from "bun:test";
|
|
2
|
+
import { mkdir, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { sigil } from "../src/bun-plugin.ts";
|
|
6
|
+
|
|
7
|
+
const dir = join(tmpdir(), `sigil-bun-plugin-${Date.now()}`);
|
|
8
|
+
|
|
9
|
+
beforeAll(async () => {
|
|
10
|
+
await mkdir(dir, { recursive: true });
|
|
11
|
+
await writeFile(
|
|
12
|
+
join(dir, "theme.ts"),
|
|
13
|
+
'export let theme = $store<"light" | "dark">("light");\nexport function toggle() { theme = theme === "light" ? "dark" : "light"; }',
|
|
14
|
+
);
|
|
15
|
+
await writeFile(
|
|
16
|
+
join(dir, "raw.ts"),
|
|
17
|
+
"export let rows = $state.raw([1, 2]);\nexport const first = () => rows[0];",
|
|
18
|
+
);
|
|
19
|
+
await writeFile(
|
|
20
|
+
join(dir, "label.ts"),
|
|
21
|
+
'import { theme } from "./theme";\nexport const label = () => "theme: " + theme;',
|
|
22
|
+
);
|
|
23
|
+
await writeFile(
|
|
24
|
+
join(dir, "entry.ts"),
|
|
25
|
+
'import { toggle } from "./theme";\nimport { first } from "./raw";\nimport { label } from "./label";\nconsole.log(toggle, first, label);',
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterAll(() => rm(dir, { recursive: true, force: true }));
|
|
30
|
+
|
|
31
|
+
test("plain .ts modules with any macro or a store import are compiled", async () => {
|
|
32
|
+
const result = await Bun.build({
|
|
33
|
+
entrypoints: [join(dir, "entry.ts")],
|
|
34
|
+
plugins: [sigil({ mode: "dom" })],
|
|
35
|
+
external: ["@sigil-dev/runtime"],
|
|
36
|
+
throw: false,
|
|
37
|
+
});
|
|
38
|
+
expect(result.success).toBe(true);
|
|
39
|
+
const code = await result.outputs[0]!.text();
|
|
40
|
+
// $store<T>(…) with a type argument, and $state.raw(…)
|
|
41
|
+
expect(code).not.toMatch(/\$store|\$state/);
|
|
42
|
+
expect(code).toContain("createRawSignal");
|
|
43
|
+
// label.ts has no macro, but reads an imported store
|
|
44
|
+
expect(code).toMatch(/readStore\d*\(theme\)/);
|
|
45
|
+
});
|
package/test/hydration.test.ts
CHANGED
|
@@ -172,8 +172,9 @@ describe("Hydration", () => {
|
|
|
172
172
|
// children must not be evaluated at the call site — they claim from the
|
|
173
173
|
// component's own slot, which the caller cannot see
|
|
174
174
|
expect(code).toMatch(/children:\s*\[\(\)\s*=>\s*\{/);
|
|
175
|
-
// the {children} site consumes the SSR slot and hydrates against it
|
|
176
|
-
|
|
175
|
+
// the {children} site consumes the SSR slot and hydrates against it;
|
|
176
|
+
// it's a live slot because props are read through the props object
|
|
177
|
+
expect(code).toContain("liveSlot(_el1, _el0, () => _props.children)");
|
|
177
178
|
});
|
|
178
179
|
|
|
179
180
|
test("dom mode still evaluates component children eagerly", () => {
|
package/test/jsx.test.ts
CHANGED
|
@@ -57,8 +57,8 @@ describe("JSX", () => {
|
|
|
57
57
|
const code = transform(`
|
|
58
58
|
const el = <div style={{ color: "red", fontSize: "16px" }} />;
|
|
59
59
|
`);
|
|
60
|
-
expect(code).toContain('
|
|
61
|
-
expect(code).toContain('
|
|
60
|
+
expect(code).toContain('setStyleProp(_el0, "color", "red")');
|
|
61
|
+
expect(code).toContain('setStyleProp(_el0, "fontSize", "16px")');
|
|
62
62
|
expect(code).not.toContain("[object Object]");
|
|
63
63
|
});
|
|
64
64
|
|
|
@@ -68,8 +68,10 @@ describe("JSX", () => {
|
|
|
68
68
|
const el = <div style={{ fontSize: size + "px", color: "red" }} />;
|
|
69
69
|
`);
|
|
70
70
|
expect(code).toContain("createEffect");
|
|
71
|
-
expect(code).
|
|
72
|
-
|
|
71
|
+
expect(code).toMatch(
|
|
72
|
+
/createEffect\(\(\) => \{\s*setStyleProp\(_el0, "fontSize"/,
|
|
73
|
+
);
|
|
74
|
+
expect(code).toContain('setStyleProp(_el0, "color", "red")');
|
|
73
75
|
});
|
|
74
76
|
});
|
|
75
77
|
|
|
@@ -156,6 +158,26 @@ describe("JSX", () => {
|
|
|
156
158
|
expect(code).toContain("text.set(e.target.value)");
|
|
157
159
|
});
|
|
158
160
|
|
|
161
|
+
test("camelCase bind keeps the property's casing", () => {
|
|
162
|
+
const code = transform(`
|
|
163
|
+
let top = $state(0);
|
|
164
|
+
const el = <div bindScrollTop={top} />;
|
|
165
|
+
`);
|
|
166
|
+
expect(code).toContain(".scrollTop = top()");
|
|
167
|
+
expect(code).not.toContain("scrolltop");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("scroll and details bindings listen for their own events", () => {
|
|
171
|
+
const code = transform(`
|
|
172
|
+
let top = $state(0);
|
|
173
|
+
let open = $state(false);
|
|
174
|
+
const a = <div bind:scrollTop={top} />;
|
|
175
|
+
const b = <details bind:open={open} />;
|
|
176
|
+
`);
|
|
177
|
+
expect(code).toContain('"scroll"');
|
|
178
|
+
expect(code).toContain('"toggle"');
|
|
179
|
+
});
|
|
180
|
+
|
|
159
181
|
test("bindChecked compiles to change event", () => {
|
|
160
182
|
const code = transform(`
|
|
161
183
|
let checked = $state(false);
|