ripple 0.3.10 → 0.3.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +2 -2
  3. package/src/compiler/errors.js +1 -1
  4. package/src/compiler/index.d.ts +3 -1
  5. package/src/compiler/phases/1-parse/index.js +170 -8
  6. package/src/compiler/phases/2-analyze/index.js +231 -20
  7. package/src/compiler/phases/3-transform/client/index.js +169 -77
  8. package/src/compiler/phases/3-transform/server/index.js +46 -3
  9. package/src/compiler/types/index.d.ts +19 -2
  10. package/src/compiler/types/parse.d.ts +1 -1
  11. package/src/compiler/utils.js +174 -0
  12. package/src/runtime/index-client.js +14 -4
  13. package/src/runtime/internal/client/composite.js +2 -2
  14. package/src/runtime/internal/client/expression.js +64 -2
  15. package/src/runtime/internal/client/portal.js +1 -1
  16. package/src/utils/builders.js +30 -0
  17. package/tests/client/basic/__snapshots__/basic.rendering.test.ripple.snap +1 -0
  18. package/tests/client/basic/basic.rendering.test.ripple +4 -2
  19. package/tests/client/composite/composite.render.test.ripple +46 -0
  20. package/tests/client/return.test.ripple +101 -0
  21. package/tests/client/tsx.test.ripple +486 -0
  22. package/tests/hydration/compiled/client/basic.js +8 -24
  23. package/tests/hydration/compiled/client/composite.js +6 -24
  24. package/tests/hydration/compiled/client/events.js +9 -54
  25. package/tests/hydration/compiled/client/for.js +59 -152
  26. package/tests/hydration/compiled/client/head.js +5 -20
  27. package/tests/hydration/compiled/client/hmr.js +2 -8
  28. package/tests/hydration/compiled/client/html.js +59 -226
  29. package/tests/hydration/compiled/client/if-children.js +6 -22
  30. package/tests/hydration/compiled/client/mixed-control-flow.js +18 -66
  31. package/tests/hydration/compiled/client/nested-control-flow.js +92 -368
  32. package/tests/hydration/compiled/client/portal.js +4 -16
  33. package/tests/hydration/compiled/client/reactivity.js +7 -40
  34. package/tests/hydration/compiled/client/return.js +1 -4
  35. package/tests/hydration/compiled/client/try.js +2 -2
  36. package/tests/utils/compiler-compat-config.test.js +38 -0
  37. package/tests/utils/vite-plugin-config.test.js +113 -0
  38. package/tsconfig.json +2 -0
  39. package/tsconfig.typecheck.json +2 -1
  40. package/types/index.d.ts +2 -12
@@ -29,13 +29,10 @@ export function SimplePortal(__anchor, _, __block) {
29
29
  return typeof document !== 'undefined' ? document.body : null;
30
30
  },
31
31
 
32
- children: _$_.ripple_element(function render_children(__anchor, _, __block) {
33
- _$_.push_component();
34
-
32
+ children: _$_.ripple_element(function render_children(__anchor, __block) {
35
33
  var div_2 = root_1();
36
34
 
37
35
  _$_.append(__anchor, div_2);
38
- _$_.pop_component();
39
36
  })
40
37
  },
41
38
  _$_.active_block
@@ -73,13 +70,10 @@ export function ConditionalPortal(__anchor, _, __block) {
73
70
  return typeof document !== 'undefined' ? document.body : null;
74
71
  },
75
72
 
76
- children: _$_.ripple_element(function render_children(__anchor, _, __block) {
77
- _$_.push_component();
78
-
73
+ children: _$_.ripple_element(function render_children(__anchor, __block) {
79
74
  var div_4 = root_4();
80
75
 
81
76
  _$_.append(__anchor, div_4);
82
- _$_.pop_component();
83
77
  })
84
78
  },
85
79
  _$_.active_block
@@ -116,13 +110,10 @@ export function PortalWithMainContent(__anchor, _, __block) {
116
110
  return typeof document !== 'undefined' ? document.body : null;
117
111
  },
118
112
 
119
- children: _$_.ripple_element(function render_children(__anchor, _, __block) {
120
- _$_.push_component();
121
-
113
+ children: _$_.ripple_element(function render_children(__anchor, __block) {
122
114
  var div_7 = root_6();
123
115
 
124
116
  _$_.append(__anchor, div_7);
125
- _$_.pop_component();
126
117
  })
127
118
  },
128
119
  _$_.active_block
@@ -154,13 +145,10 @@ export function NestedContentWithPortal(__anchor, _, __block) {
154
145
  return typeof document !== 'undefined' ? document.body : null;
155
146
  },
156
147
 
157
- children: _$_.ripple_element(function render_children(__anchor, _, __block) {
158
- _$_.push_component();
159
-
148
+ children: _$_.ripple_element(function render_children(__anchor, __block) {
160
149
  var div_10 = root_8();
161
150
 
162
151
  _$_.append(__anchor, div_10);
163
- _$_.pop_component();
164
152
  })
165
153
  },
166
154
  _$_.active_block
@@ -19,13 +19,10 @@ export function TrackedState(__anchor, _, __block) {
19
19
  {
20
20
  var expression = _$_.child(div_1, true);
21
21
 
22
+ _$_.expression(expression, () => _$_.get(lazy));
22
23
  _$_.pop(div_1);
23
24
  }
24
25
 
25
- _$_.render(() => {
26
- _$_.set_text(expression, _$_.get(lazy));
27
- });
28
-
29
26
  _$_.append(__anchor, div_1);
30
27
  _$_.pop_component();
31
28
  }
@@ -42,14 +39,11 @@ export function CounterWithInitial(__anchor, props, __block) {
42
39
  {
43
40
  var expression_1 = _$_.child(span_1, true);
44
41
 
42
+ _$_.expression(expression_1, () => _$_.get(lazy_1));
45
43
  _$_.pop(span_1);
46
44
  }
47
45
  }
48
46
 
49
- _$_.render(() => {
50
- _$_.set_text(expression_1, _$_.get(lazy_1));
51
- });
52
-
53
47
  _$_.append(__anchor, div_2);
54
48
  _$_.pop_component();
55
49
  }
@@ -76,13 +70,10 @@ export function ComputedValues(__anchor, _, __block) {
76
70
  {
77
71
  var expression_2 = _$_.child(div_3, true);
78
72
 
73
+ _$_.expression(expression_2, sum);
79
74
  _$_.pop(div_3);
80
75
  }
81
76
 
82
- _$_.render(() => {
83
- _$_.set_text(expression_2, sum());
84
- });
85
-
86
77
  _$_.append(__anchor, div_3);
87
78
  _$_.pop_component();
88
79
  }
@@ -99,6 +90,7 @@ export function MultipleTracked(__anchor, _, __block) {
99
90
  {
100
91
  var expression_3 = _$_.child(div_4, true);
101
92
 
93
+ _$_.expression(expression_3, () => _$_.get(lazy_4));
102
94
  _$_.pop(div_4);
103
95
  }
104
96
 
@@ -107,6 +99,7 @@ export function MultipleTracked(__anchor, _, __block) {
107
99
  {
108
100
  var expression_4 = _$_.child(div_5, true);
109
101
 
102
+ _$_.expression(expression_4, () => _$_.get(lazy_5));
110
103
  _$_.pop(div_5);
111
104
  }
112
105
 
@@ -115,34 +108,11 @@ export function MultipleTracked(__anchor, _, __block) {
115
108
  {
116
109
  var expression_5 = _$_.child(div_6, true);
117
110
 
111
+ _$_.expression(expression_5, () => _$_.get(lazy_6));
118
112
  _$_.pop(div_6);
119
113
  }
120
114
 
121
115
  _$_.next(2);
122
-
123
- _$_.render(
124
- (__prev) => {
125
- var __a = _$_.get(lazy_4);
126
-
127
- if (__prev.a !== __a) {
128
- _$_.set_text(expression_3, __prev.a = __a);
129
- }
130
-
131
- var __b = _$_.get(lazy_5);
132
-
133
- if (__prev.b !== __b) {
134
- _$_.set_text(expression_4, __prev.b = __b);
135
- }
136
-
137
- var __c = _$_.get(lazy_6);
138
-
139
- if (__prev.c !== __c) {
140
- _$_.set_text(expression_5, __prev.c = __c);
141
- }
142
- },
143
- { a: ' ', b: ' ', c: ' ' }
144
- );
145
-
146
116
  _$_.append(__anchor, fragment_1, true);
147
117
  _$_.pop_component();
148
118
  }
@@ -158,13 +128,10 @@ export function DerivedState(__anchor, _, __block) {
158
128
  {
159
129
  var expression_6 = _$_.child(div_7, true);
160
130
 
131
+ _$_.expression(expression_6, fullName);
161
132
  _$_.pop(div_7);
162
133
  }
163
134
 
164
- _$_.render(() => {
165
- _$_.set_text(expression_6, fullName());
166
- });
167
-
168
135
  _$_.append(__anchor, div_7);
169
136
  _$_.pop_component();
170
137
  }
@@ -1711,13 +1711,10 @@ export function ReactiveOuterInnerReturns(__anchor, _, __block) {
1711
1711
  {
1712
1712
  var expression = _$_.child(div_39, true);
1713
1713
 
1714
+ _$_.expression(expression, () => _$_.get(lazy_4) ? 'a-on rest' : 'a-off rest');
1714
1715
  _$_.pop(div_39);
1715
1716
  }
1716
1717
 
1717
- _$_.render(() => {
1718
- _$_.set_text(expression, _$_.get(lazy_4) ? 'a-on rest' : 'a-off rest');
1719
- });
1720
-
1721
1718
  _$_.append(__anchor, div_39);
1722
1719
  };
1723
1720
 
@@ -60,7 +60,7 @@ function AsyncList(__anchor, _, __block) {
60
60
  {
61
61
  var expression = _$_.child(li_1, true);
62
62
 
63
- expression.nodeValue = item;
63
+ _$_.expression(expression, () => item);
64
64
  _$_.pop(li_1);
65
65
  }
66
66
 
@@ -120,7 +120,7 @@ function AsyncContent(__anchor, _, __block) {
120
120
  {
121
121
  var expression_1 = _$_.child(div_3, true);
122
122
 
123
- expression_1.nodeValue = value;
123
+ _$_.expression(expression_1, () => value);
124
124
  _$_.pop(div_3);
125
125
  }
126
126
 
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { compile } from 'ripple/compiler';
3
+
4
+ const source = `
5
+ component App() {
6
+ <tsx:react>
7
+ <div className="react-content">{'Hello'}</div>
8
+ </tsx:react>
9
+ }
10
+ `;
11
+
12
+ describe('compiler tsx compat configuration', () => {
13
+ it('allows tsx compat when no compat config is provided', () => {
14
+ expect(() =>
15
+ compile(source, '/src/App.ripple', {
16
+ mode: 'client',
17
+ }),
18
+ ).not.toThrow();
19
+ });
20
+
21
+ it('throws when tsx compat kind is not configured', () => {
22
+ expect(() =>
23
+ compile(source, '/src/App.ripple', {
24
+ mode: 'client',
25
+ compat_kinds: [],
26
+ }),
27
+ ).toThrow('<tsx:react> requires "react" compat to be configured in ripple.config.ts.');
28
+ });
29
+
30
+ it('allows tsx compat kinds that are configured', () => {
31
+ expect(() =>
32
+ compile(source, '/src/App.ripple', {
33
+ mode: 'client',
34
+ compat_kinds: ['react'],
35
+ }),
36
+ ).not.toThrow();
37
+ });
38
+ });
@@ -0,0 +1,113 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { RenderRoute, resolveRippleConfig } from '@ripple-ts/vite-plugin';
3
+
4
+ const fake_compat_factory = Object.assign(
5
+ () =>
6
+ Object.assign(
7
+ {
8
+ createComponent() {},
9
+ createRoot() {
10
+ return () => {};
11
+ },
12
+ },
13
+ {
14
+ __ripple_compat__: {
15
+ from: '@ripple-ts/compat-react',
16
+ factory: 'createReactCompat',
17
+ },
18
+ },
19
+ ),
20
+ {
21
+ __ripple_compat__: {
22
+ from: '@ripple-ts/compat-react',
23
+ factory: 'createReactCompat',
24
+ },
25
+ },
26
+ );
27
+
28
+ describe('vite-plugin-ripple config resolution', () => {
29
+ it('preserves compat descriptors and applies defaults', () => {
30
+ const config = resolveRippleConfig({
31
+ router: {
32
+ routes: [
33
+ new RenderRoute({
34
+ path: '/',
35
+ entry: '/src/App.ripple',
36
+ }),
37
+ ],
38
+ },
39
+ compat: {
40
+ react: {
41
+ from: '@ripple-ts/compat-react',
42
+ factory: 'createReactCompat',
43
+ },
44
+ },
45
+ });
46
+
47
+ expect(config.compat).toEqual({
48
+ react: {
49
+ from: '@ripple-ts/compat-react',
50
+ factory: 'createReactCompat',
51
+ },
52
+ });
53
+ expect(config.middlewares).toEqual([]);
54
+ expect(config.platform.env).toEqual({});
55
+ expect(config.server.trustProxy).toBe(false);
56
+ });
57
+
58
+ it('defaults compat to an empty object', () => {
59
+ const config = resolveRippleConfig({
60
+ router: {
61
+ routes: [],
62
+ },
63
+ });
64
+
65
+ expect(config.compat).toEqual({});
66
+ });
67
+
68
+ it('allows compat-only configs without routes', () => {
69
+ const config = resolveRippleConfig({
70
+ compat: {
71
+ react: fake_compat_factory,
72
+ },
73
+ });
74
+
75
+ expect(config.router.routes).toEqual([]);
76
+ expect(config.compat.react).toEqual({
77
+ from: '@ripple-ts/compat-react',
78
+ factory: 'createReactCompat',
79
+ });
80
+ });
81
+
82
+ it('normalizes imported compat factories to descriptors', () => {
83
+ const config = resolveRippleConfig({
84
+ router: {
85
+ routes: [],
86
+ },
87
+ compat: {
88
+ react: fake_compat_factory,
89
+ },
90
+ });
91
+
92
+ expect(config.compat.react).toEqual({
93
+ from: '@ripple-ts/compat-react',
94
+ factory: 'createReactCompat',
95
+ });
96
+ });
97
+
98
+ it('normalizes invoked compat entries to descriptors', () => {
99
+ const config = resolveRippleConfig({
100
+ router: {
101
+ routes: [],
102
+ },
103
+ compat: {
104
+ react: fake_compat_factory(),
105
+ },
106
+ });
107
+
108
+ expect(config.compat.react).toEqual({
109
+ from: '@ripple-ts/compat-react',
110
+ factory: 'createReactCompat',
111
+ });
112
+ });
113
+ });
package/tsconfig.json CHANGED
@@ -26,7 +26,9 @@
26
26
  "./*.js",
27
27
  "./src/",
28
28
  "./tests/**/*.test.ripple",
29
+ "./tests/**/*.test.tsrx",
29
30
  "./tests/**/*.ripple",
31
+ "./tests/**/*.tsrx",
30
32
  "./tests/**/*.d.ts",
31
33
  "./tests/**/*.js"
32
34
  ],
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
- "include": ["./src/runtime/"]
3
+ "include": ["./src/"],
4
+ "exclude": ["./tests/"]
4
5
  }
package/types/index.d.ts CHANGED
@@ -10,24 +10,14 @@ export type RippleElement = {
10
10
  /** Type for implicit children fragments rendered with `{children}`. */
11
11
  export type Children = RippleElement;
12
12
 
13
- export type CompatApi = {
14
- createRoot: () => void;
15
- createComponent: (node: any, children_fn: () => any) => void;
16
- jsx: (type: any, props: any) => any;
17
- };
18
-
19
- export type CompatOptions = {
20
- [key: string]: CompatApi;
21
- };
22
-
23
13
  export function mount(
24
14
  component: Component,
25
- options: { target: HTMLElement; props?: Record<string, any>; compat?: CompatOptions },
15
+ options: { target: HTMLElement; props?: Record<string, any> },
26
16
  ): () => void;
27
17
 
28
18
  export function hydrate(
29
19
  component: Component,
30
- options: { target: HTMLElement; props?: Record<string, any>; compat?: CompatOptions },
20
+ options: { target: HTMLElement; props?: Record<string, any> },
31
21
  ): () => void;
32
22
 
33
23
  export function tick(): Promise<void>;