ripple 0.3.9 → 0.3.10
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 +12 -0
- package/package.json +2 -2
- package/src/compiler/phases/1-parse/index.js +25 -15
- package/src/compiler/phases/2-analyze/index.js +35 -88
- package/src/compiler/phases/2-analyze/prune.js +13 -5
- package/src/compiler/phases/3-transform/client/index.js +188 -56
- package/src/compiler/phases/3-transform/server/index.js +62 -40
- package/src/compiler/types/index.d.ts +9 -1
- package/src/compiler/types/parse.d.ts +2 -0
- package/src/compiler/utils.js +101 -1
- package/src/runtime/element.js +39 -0
- package/src/runtime/internal/client/composite.js +10 -6
- package/src/runtime/internal/client/expression.js +218 -0
- package/src/runtime/internal/client/index.js +4 -0
- package/src/runtime/internal/client/portal.js +12 -6
- package/src/runtime/internal/server/index.js +26 -1
- package/tests/client/basic/basic.components.test.ripple +85 -87
- package/tests/client/basic/basic.errors.test.ripple +4 -8
- package/tests/client/basic/basic.rendering.test.ripple +23 -8
- package/tests/client/capture-error.js +12 -0
- package/tests/client/compiler/compiler.basic.test.ripple +76 -6
- package/tests/client/composite/composite.props.test.ripple +1 -3
- package/tests/client/composite/composite.render.test.ripple +45 -13
- package/tests/client/css/global-additional-cases.test.ripple +3 -3
- package/tests/client/svg.test.ripple +4 -4
- package/tests/hydration/basic.test.js +23 -0
- package/tests/hydration/compiled/client/basic.js +118 -66
- package/tests/hydration/compiled/client/composite.js +90 -37
- package/tests/hydration/compiled/client/events.js +18 -18
- package/tests/hydration/compiled/client/for.js +62 -62
- package/tests/hydration/compiled/client/head.js +10 -10
- package/tests/hydration/compiled/client/hmr.js +13 -10
- package/tests/hydration/compiled/client/html.js +274 -236
- package/tests/hydration/compiled/client/if-children.js +41 -35
- package/tests/hydration/compiled/client/if.js +2 -2
- package/tests/hydration/compiled/client/mixed-control-flow.js +12 -12
- package/tests/hydration/compiled/client/nested-control-flow.js +46 -46
- package/tests/hydration/compiled/client/portal.js +8 -8
- package/tests/hydration/compiled/client/reactivity.js +14 -14
- package/tests/hydration/compiled/client/return.js +2 -2
- package/tests/hydration/compiled/client/try.js +4 -4
- package/tests/hydration/compiled/server/basic.js +64 -31
- package/tests/hydration/compiled/server/composite.js +62 -29
- package/tests/hydration/compiled/server/hmr.js +24 -37
- package/tests/hydration/compiled/server/html.js +472 -611
- package/tests/hydration/compiled/server/if-children.js +77 -103
- package/tests/hydration/compiled/server/portal.js +8 -8
- package/tests/hydration/components/basic.ripple +15 -5
- package/tests/hydration/components/composite.ripple +13 -1
- package/tests/hydration/components/hmr.ripple +1 -3
- package/tests/hydration/components/html.ripple +13 -35
- package/tests/hydration/components/if-children.ripple +4 -8
- package/tests/hydration/composite.test.js +11 -0
- package/tests/server/basic.attributes.test.ripple +50 -0
- package/tests/server/basic.components.test.ripple +22 -28
- package/tests/server/basic.test.ripple +12 -0
- package/tests/server/compiler.test.ripple +25 -8
- package/tests/server/composite.props.test.ripple +1 -3
- package/tests/server/style-identifier.test.ripple +2 -4
- package/types/index.d.ts +9 -2
|
@@ -10,17 +10,15 @@ import type {
|
|
|
10
10
|
describe('basic server > components & composition', () => {
|
|
11
11
|
it('renders with component composition and children', async () => {
|
|
12
12
|
component Card(props: PropsWithChildren<{}>) {
|
|
13
|
-
<div class="card">
|
|
14
|
-
<props.children />
|
|
15
|
-
</div>
|
|
13
|
+
<div class="card">{props.children}</div>
|
|
16
14
|
}
|
|
17
15
|
|
|
18
16
|
component Basic() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
component children() {
|
|
18
|
+
<p>{'Card content here'}</p>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
<Card {children} />
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
const { body } = await render(Basic);
|
|
@@ -37,16 +35,16 @@ describe('basic server > components & composition', () => {
|
|
|
37
35
|
component Card(props: PropsWithChildrenOptional<{ test: Component }>) {
|
|
38
36
|
<div class="card">
|
|
39
37
|
// @ts-expect-error - ripple automatically handles falsy children
|
|
40
|
-
|
|
38
|
+
{props.children}
|
|
41
39
|
</div>
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
component Basic() {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
component test() {
|
|
44
|
+
<p>{'Card content here'}</p>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
<Card {test} />
|
|
50
48
|
}
|
|
51
49
|
|
|
52
50
|
const { body } = await render(Basic);
|
|
@@ -62,9 +60,7 @@ describe('basic server > components & composition', () => {
|
|
|
62
60
|
|
|
63
61
|
it('renders a component when children is set a component prop', async () => {
|
|
64
62
|
component Card(props: PropsWithChildren<{}>) {
|
|
65
|
-
<div class="card">
|
|
66
|
-
<props.children />
|
|
67
|
-
</div>
|
|
63
|
+
<div class="card">{props.children}</div>
|
|
68
64
|
}
|
|
69
65
|
|
|
70
66
|
component Basic() {
|
|
@@ -174,21 +170,19 @@ describe('basic server > components & composition', () => {
|
|
|
174
170
|
<span>{'Hello from Span'}</span>
|
|
175
171
|
},
|
|
176
172
|
button: component({ children }: PropsWithChildren<{}>) {
|
|
177
|
-
<button>
|
|
178
|
-
<children />
|
|
179
|
-
</button>
|
|
173
|
+
<button>{children}</button>
|
|
180
174
|
},
|
|
181
175
|
};
|
|
182
176
|
|
|
183
177
|
component App() {
|
|
178
|
+
component children() {
|
|
179
|
+
<span>{'Click me!'}</span>
|
|
180
|
+
}
|
|
181
|
+
|
|
184
182
|
<div>
|
|
185
183
|
<h1>{'Component as Property Test'}</h1>
|
|
186
184
|
<UI.span />
|
|
187
|
-
<UI.button
|
|
188
|
-
component children() {
|
|
189
|
-
<span>{'Click me!'}</span>
|
|
190
|
-
}
|
|
191
|
-
</UI.button>
|
|
185
|
+
<UI.button {children} />
|
|
192
186
|
</div>
|
|
193
187
|
}
|
|
194
188
|
|
|
@@ -207,13 +201,13 @@ describe('basic server > components & composition', () => {
|
|
|
207
201
|
|
|
208
202
|
it('handles empty string children', async () => {
|
|
209
203
|
component Button({ children }: PropsWithChildren<{}>) {
|
|
210
|
-
|
|
204
|
+
{children}
|
|
211
205
|
}
|
|
212
206
|
|
|
213
207
|
component App() {
|
|
214
|
-
let
|
|
208
|
+
let content = '';
|
|
215
209
|
<Button>{''}</Button>
|
|
216
|
-
<Button>{
|
|
210
|
+
<Button>{content}</Button>
|
|
217
211
|
}
|
|
218
212
|
|
|
219
213
|
const { body } = await render(App);
|
|
@@ -13,6 +13,18 @@ describe('basic client', () => {
|
|
|
13
13
|
expect(body).toBeHtml('<div>Hello World</div>');
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
it('renders explicit text interpolation as escaped text', async () => {
|
|
17
|
+
component Basic() {
|
|
18
|
+
let markup = '<span>Not HTML</span>';
|
|
19
|
+
|
|
20
|
+
<div>{text markup}</div>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { body } = await render(Basic);
|
|
24
|
+
|
|
25
|
+
expect(body).toBeHtml('<div><span>Not HTML</span></div>');
|
|
26
|
+
});
|
|
27
|
+
|
|
16
28
|
it('renders tracked state updates', async () => {
|
|
17
29
|
component Counter() {
|
|
18
30
|
let &[count] = track(0);
|
|
@@ -78,9 +78,7 @@ export component Layout({ children }) {
|
|
|
78
78
|
<div>{children}</div>
|
|
79
79
|
}`;
|
|
80
80
|
|
|
81
|
-
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
82
|
-
'`children` cannot be rendered using text interpolation. Use `<children />` instead.',
|
|
83
|
-
);
|
|
81
|
+
expect(() => compile(source, 'test.ripple', { mode: 'server' })).not.toThrow();
|
|
84
82
|
});
|
|
85
83
|
|
|
86
84
|
it('throws error for interpolating props.children as text in SSR mode', () => {
|
|
@@ -89,9 +87,7 @@ export component Layout(props) {
|
|
|
89
87
|
<div>{props.children}</div>
|
|
90
88
|
}`;
|
|
91
89
|
|
|
92
|
-
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
93
|
-
'`children` cannot be rendered using text interpolation. Use `<children />` instead.',
|
|
94
|
-
);
|
|
90
|
+
expect(() => compile(source, 'test.ripple', { mode: 'server' })).not.toThrow();
|
|
95
91
|
});
|
|
96
92
|
|
|
97
93
|
it('throws error for calling children as a function in SSR mode', () => {
|
|
@@ -101,7 +97,7 @@ export component Layout({ children }) {
|
|
|
101
97
|
}`;
|
|
102
98
|
|
|
103
99
|
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
104
|
-
'`children` cannot be called like a regular function.
|
|
100
|
+
'`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
|
|
105
101
|
);
|
|
106
102
|
});
|
|
107
103
|
|
|
@@ -112,9 +108,30 @@ export component Layout(props) {
|
|
|
112
108
|
}`;
|
|
113
109
|
|
|
114
110
|
expect(() => compile(source, 'test.ripple', { mode: 'server' })).toThrow(
|
|
115
|
-
'`children` cannot be called like a regular function.
|
|
111
|
+
'`children` cannot be called like a regular function. Render it with `{children}` or `{props.children}` instead.',
|
|
116
112
|
);
|
|
117
113
|
});
|
|
114
|
+
|
|
115
|
+
it('merges explicit children prop with implicit children in SSR output', () => {
|
|
116
|
+
const source = `
|
|
117
|
+
component Card(props) {
|
|
118
|
+
<div>{props.children}</div>
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export component App() {
|
|
122
|
+
const fallback = 'fallback';
|
|
123
|
+
|
|
124
|
+
<Card children={fallback}>
|
|
125
|
+
<span>{'content'}</span>
|
|
126
|
+
</Card>
|
|
127
|
+
}
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const result = compile(source, 'test.ripple', { mode: 'server' }).js.code;
|
|
131
|
+
|
|
132
|
+
expect((result.match(/children:/g) || []).length).toBe(1);
|
|
133
|
+
expect(result).toContain('children: _$_.normalize_children(fallback) ?? _$_.ripple_element(');
|
|
134
|
+
});
|
|
118
135
|
});
|
|
119
136
|
|
|
120
137
|
describe('compiler server block tests', () => {
|
|
@@ -80,9 +80,7 @@ describe('composite > props', () => {
|
|
|
80
80
|
|
|
81
81
|
it('correctly retains prop accessors and reactivity when using rest props', async () => {
|
|
82
82
|
component Button(&{ children, ...rest }: Props) {
|
|
83
|
-
<button {...rest}>
|
|
84
|
-
<@children />
|
|
85
|
-
</button>
|
|
83
|
+
<button {...rest}>{children}</button>
|
|
86
84
|
<style>
|
|
87
85
|
.on {
|
|
88
86
|
color: blue;
|
|
@@ -190,7 +190,7 @@ describe('#style identifier (server)', () => {
|
|
|
190
190
|
component Wrapper({ children }) {
|
|
191
191
|
<div class="green">
|
|
192
192
|
{'Wrapper'}
|
|
193
|
-
|
|
193
|
+
{children}
|
|
194
194
|
</div>
|
|
195
195
|
|
|
196
196
|
<style>
|
|
@@ -235,9 +235,7 @@ describe('#style identifier (server)', () => {
|
|
|
235
235
|
|
|
236
236
|
it('applies caller scoped hash to slotted children through dynamic components', async () => {
|
|
237
237
|
component Wrapper({ children }) {
|
|
238
|
-
<section>
|
|
239
|
-
<children />
|
|
240
|
-
</section>
|
|
238
|
+
<section>{children}</section>
|
|
241
239
|
}
|
|
242
240
|
|
|
243
241
|
component App() {
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export type Component<T = Record<string, any>> = (props: T) => void;
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
declare const RIPPLE_ELEMENT: unique symbol;
|
|
4
|
+
|
|
5
|
+
export type RippleElement = {
|
|
6
|
+
readonly render: Function;
|
|
7
|
+
readonly [RIPPLE_ELEMENT]: true;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/** Type for implicit children fragments rendered with `{children}`. */
|
|
11
|
+
export type Children = RippleElement;
|
|
5
12
|
|
|
6
13
|
export type CompatApi = {
|
|
7
14
|
createRoot: () => void;
|