ripple 0.3.42 → 0.3.43

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # ripple
2
2
 
3
+ ## 0.3.43
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ [[`5c6ee71`](https://github.com/Ripple-TS/ripple/commit/5c6ee71bfd4f5dc443c43eb34e631bb032606faf),
9
+ [`83b19fd`](https://github.com/Ripple-TS/ripple/commit/83b19fd67aa27eb10e93205dd88c61b13ffbc523)]:
10
+ - @tsrx/ripple@0.0.25
11
+ - ripple@0.3.43
12
+
3
13
  ## 0.3.42
4
14
 
5
15
  ### Patch Changes
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.3.42",
6
+ "version": "0.3.43",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -76,7 +76,7 @@
76
76
  "esm-env": "^1.2.2",
77
77
  "@types/estree": "^1.0.8",
78
78
  "@types/estree-jsx": "^1.0.5",
79
- "@tsrx/ripple": "0.0.24"
79
+ "@tsrx/ripple": "0.0.25"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@types/node": "^24.3.0",
@@ -84,9 +84,9 @@
84
84
  "typescript": "^5.9.3",
85
85
  "@volar/language-core": "~2.4.28",
86
86
  "vscode-languageserver-types": "^3.17.5",
87
- "@tsrx/core": "0.0.22"
87
+ "@tsrx/core": "0.0.23"
88
88
  },
89
89
  "peerDependencies": {
90
- "ripple": "0.3.42"
90
+ "ripple": "0.3.43"
91
91
  }
92
92
  }
@@ -20,25 +20,25 @@ describe('compiler > basics', () => {
20
20
  const source = `export component App() {
21
21
  <div id="myid" class="myclass">{"Hello World"}</div>
22
22
 
23
- <style>#style</style>
23
+ <style>__STYLE__</style>
24
24
  }`;
25
25
  const style1 = '.myid {color: green }';
26
26
  const style2 = '#myid {color: green }';
27
27
  const style3 = 'div {color: green }';
28
28
 
29
- let input = source.replace('#style', style1);
29
+ let input = source.replace('__STYLE__', style1);
30
30
  let ast = parse(input);
31
31
  expect(
32
32
  ((ast.body[0] as AST.ExportNamedDeclaration).declaration as unknown as AST.Component)?.css.source,
33
33
  ).toEqual(style1);
34
34
 
35
- input = source.replace('#style', style2);
35
+ input = source.replace('__STYLE__', style2);
36
36
  ast = parse(input);
37
37
  expect(
38
38
  ((ast.body[0] as AST.ExportNamedDeclaration).declaration as unknown as AST.Component)?.css.source,
39
39
  ).toEqual(style2);
40
40
 
41
- input = source.replace('#style', style3);
41
+ input = source.replace('__STYLE__', style3);
42
42
  ast = parse(input);
43
43
  expect(
44
44
  ((ast.body[0] as AST.ExportNamedDeclaration).declaration as unknown as AST.Component)?.css.source,
@@ -756,6 +756,75 @@ export component App() {
756
756
  ).toBe(true);
757
757
  });
758
758
 
759
+ it('maps module server import identifiers in Volar output', () => {
760
+ const source = `module server {
761
+ export function loadUser() {
762
+ return { id: '1' };
763
+ }
764
+ }
765
+
766
+ import { loadUser as getUser } from server;
767
+ import { loadUser } from server;
768
+
769
+ component App() {
770
+ const user = getUser();
771
+ const user2 = loadUser();
772
+ <div>{user.id}{user2.id}</div>
773
+ }`;
774
+ const result = compile_to_volar_mappings(source, 'test.tsrx', { loose: true });
775
+ const generated_member = '_$_server_$_.loadUser';
776
+ const generated_member_offset = result.code.indexOf(generated_member);
777
+ const generated_imported_offset = generated_member_offset + '_$_server_$_'.length + 1;
778
+ const generated_local_offset = result.code.indexOf('const getUser') + 'const '.length;
779
+ const generated_non_alias_member_offset =
780
+ result.code.indexOf(generated_member, generated_member_offset + 1) + '_$_server_$_'.length +
781
+ 1;
782
+ const generated_non_alias_local_offset =
783
+ result.code.indexOf('const loadUser') + 'const '.length;
784
+ const source_imported_offset = source.indexOf('loadUser as');
785
+ const source_local_offset = source.indexOf('getUser }');
786
+ const source_non_alias_offset = source.indexOf('loadUser }');
787
+ const source_server_offset = source.indexOf('server;');
788
+
789
+ function find_mapping(
790
+ source_offset: number,
791
+ generated_offset: number,
792
+ length: number,
793
+ generated_length = length,
794
+ ) {
795
+ return result.mappings.find(
796
+ (mapping) => mapping.sourceOffsets[0] === source_offset &&
797
+ mapping.generatedOffsets[0] === generated_offset &&
798
+ mapping.lengths[0] === length &&
799
+ mapping.generatedLengths[0] === generated_length,
800
+ );
801
+ }
802
+
803
+ expect(result.errors).toEqual([]);
804
+ expect(result.code).toContain('const getUser = _$_server_$_.loadUser;');
805
+ expect(result.code).toContain('const loadUser = _$_server_$_.loadUser;');
806
+ expect(
807
+ find_mapping(source_imported_offset, generated_imported_offset, 'loadUser'.length),
808
+ ).toBeDefined();
809
+ expect(
810
+ find_mapping(source_local_offset, generated_local_offset, 'getUser'.length),
811
+ ).toBeDefined();
812
+ expect(
813
+ find_mapping(source_non_alias_offset, generated_non_alias_local_offset, 'loadUser'.length),
814
+ ).toBeDefined();
815
+ expect(
816
+ find_mapping(source_non_alias_offset, generated_non_alias_member_offset, 'loadUser'.length),
817
+ ).toBeDefined();
818
+ expect(
819
+ find_mapping(
820
+ source_server_offset,
821
+ generated_member_offset,
822
+ 'server'.length,
823
+ '_$_server_$_'.length,
824
+ ),
825
+ ).toBeDefined();
826
+ });
827
+
759
828
  it('collects volar parser diagnostics outside loose mode', () => {
760
829
  const result = compile_to_volar_mappings(`component App() {
761
830
  return <div />;
@@ -1,15 +1,15 @@
1
1
  import { track } from 'ripple';
2
2
  import { compile } from '@tsrx/ripple';
3
3
 
4
- describe('#style identifier', () => {
4
+ describe('{style} directive', () => {
5
5
  describe('basic usage with components', () => {
6
- it('passes scoped class to a child component via #style', () => {
6
+ it('passes scoped class to a child component via {style}', () => {
7
7
  component Child({ className }: { className: string }) {
8
8
  <div class={className}>{'styled child'}</div>
9
9
  }
10
10
 
11
11
  component Parent() {
12
- <Child className={#style.highlight} />
12
+ <Child className={style 'highlight'} />
13
13
 
14
14
  <style>
15
15
  .highlight {
@@ -28,14 +28,14 @@ describe('#style identifier', () => {
28
28
  expect(classes.some((cls: string) => cls === 'highlight')).toBe(true);
29
29
  });
30
30
 
31
- it('passes multiple #style classes to a child component', () => {
31
+ it('passes multiple {style} classes to a child component', () => {
32
32
  component Child({ primary, secondary }: { primary: string; secondary: string }) {
33
33
  <div class={primary}>{'primary'}</div>
34
34
  <span class={secondary}>{'secondary'}</span>
35
35
  }
36
36
 
37
37
  component Parent() {
38
- <Child primary={#style.primary} secondary={#style.secondary} />
38
+ <Child primary={style 'primary'} secondary={style 'secondary'} />
39
39
 
40
40
  <style>
41
41
  .primary {
@@ -64,7 +64,25 @@ describe('#style identifier', () => {
64
64
  expect(spanClasses.some((cls: string) => cls === 'secondary')).toBe(true);
65
65
  });
66
66
 
67
- it('passes scoped class to a dynamic child component via #style', () => {
67
+ it('allows {style} props on child components with children', () => {
68
+ const source = `
69
+ component Child({ className }) {
70
+ <div class={className}>"hello world"</div>
71
+ }
72
+ component App() {
73
+ <Child className={style 'container'}>"hello world"</Child>
74
+
75
+ <style>
76
+ .container {
77
+ color: red;
78
+ }
79
+ </style>
80
+ }`;
81
+
82
+ expect(() => compile(source, 'test.tsrx')).not.toThrow();
83
+ });
84
+
85
+ it('passes scoped class to a dynamic child component via {style}', () => {
68
86
  component Child({ cls }: { cls: string }) {
69
87
  <span class={cls}>{'text'}</span>
70
88
  }
@@ -72,7 +90,7 @@ describe('#style identifier', () => {
72
90
  component Parent() {
73
91
  let dynamic = track(() => Child);
74
92
  <div class="wrapper">
75
- <@dynamic cls={#style.text} />
93
+ <@dynamic cls={style 'text'} />
76
94
  </div>
77
95
 
78
96
  <style>
@@ -91,7 +109,7 @@ describe('#style identifier', () => {
91
109
  expect(classes.some((cls: string) => cls === 'text')).toBe(true);
92
110
  });
93
111
 
94
- it('child can combine its own classes with parent #style class', () => {
112
+ it('child can combine its own classes with parent {style} class', () => {
95
113
  component Card({ className }: { className?: string }) {
96
114
  <div class={['card-base', className ?? '']}>{'card content'}</div>
97
115
 
@@ -103,7 +121,7 @@ describe('#style identifier', () => {
103
121
  }
104
122
 
105
123
  component App() {
106
- <Card className={#style.themed} />
124
+ <Card className={style 'themed'} />
107
125
 
108
126
  <style>
109
127
  .themed {
@@ -128,7 +146,7 @@ describe('#style identifier', () => {
128
146
 
129
147
  component App() {
130
148
  <div class="parent">
131
- <Child cls={#style.dual} />
149
+ <Child cls={style 'dual'} />
132
150
  </div>
133
151
 
134
152
  <style>
@@ -152,10 +170,10 @@ describe('#style identifier', () => {
152
170
  });
153
171
 
154
172
  describe('compile errors', () => {
155
- it('errors when #style is used directly on a DOM element', () => {
173
+ it('errors when {style} is used directly on a DOM element', () => {
156
174
  const source = `
157
175
  component App() {
158
- <div class={#style.box}>{'content'}</div>
176
+ <div class={style 'box'}>{'content'}</div>
159
177
 
160
178
  <style>
161
179
  .box {
@@ -166,10 +184,10 @@ component App() {
166
184
  expect(() => compile(source, 'test.tsrx')).toThrow(/cannot be used directly on DOM elements/);
167
185
  });
168
186
 
169
- it('errors when #style bracket notation is used directly on a DOM element', () => {
187
+ it('errors when {style} is used directly on a DOM element class', () => {
170
188
  const source = `
171
189
  component App() {
172
- <div class={#style['container']}>{'content'}</div>
190
+ <div class={style 'container'}>{'content'}</div>
173
191
 
174
192
  <style>
175
193
  .container {
@@ -180,13 +198,13 @@ component App() {
180
198
  expect(() => compile(source, 'test.tsrx')).toThrow(/cannot be used directly on DOM elements/);
181
199
  });
182
200
 
183
- it('errors when #style references a class in a compound selector passed to component', () => {
201
+ it('errors when {style} references a class in a compound selector passed to component', () => {
184
202
  const source = `
185
203
  component Child({ cls }) {
186
204
  <span class={cls}>{'text'}</span>
187
205
  }
188
206
  component App() {
189
- <Child cls={#style.special} />
207
+ <Child cls={style 'special'} />
190
208
 
191
209
  <style>
192
210
  span.special {
@@ -206,7 +224,7 @@ component App() {
206
224
  component App() {
207
225
  <div class="wrapper">
208
226
  <Child
209
- cls={#style.nested}
227
+ cls={style 'nested'}
210
228
  />
211
229
  </div>
212
230
 
@@ -234,7 +252,7 @@ component App() {
234
252
  <Child
235
253
  // @ts-expect-error - cannot use child combinator class as standalone
236
254
  // @ripple-expect-error - cannot use child combinator class as standalone
237
- cls={#style.child}
255
+ cls={style 'child'}
238
256
  />
239
257
  </div>
240
258
 
@@ -261,7 +279,7 @@ component App() {
261
279
  <Child
262
280
  // @ts-expect-error - cannot use compound class as standalone
263
281
  // @ripple-expect-error - cannot use compound class as standalone
264
- cls={#style.child}
282
+ cls={style 'child'}
265
283
  />
266
284
  </div>
267
285
 
@@ -277,7 +295,7 @@ component App() {
277
295
  expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
278
296
  });
279
297
 
280
- it('errors if descendant #style class is used on a dynamic component', () => {
298
+ it('errors if descendant {style} class is used on a dynamic component', () => {
281
299
  const source = `
282
300
 
283
301
  component Child({ cls }) {
@@ -287,7 +305,7 @@ component App() {
287
305
  component App() {
288
306
  let dynamic = track(() => Child);
289
307
  <div class="wrapper">
290
- <@dynamic cls={#style.nested} />
308
+ <@dynamic cls={style 'nested'} />
291
309
  </div>
292
310
 
293
311
  <style>
@@ -302,13 +320,13 @@ component App() {
302
320
  expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
303
321
  });
304
322
 
305
- it('errors when #style references a class that does not exist in the style block', () => {
323
+ it('errors when {style} references a class that does not exist in the style block', () => {
306
324
  const source = `
307
325
  component Child({ cls }) {
308
326
  <div class={cls}>{'text'}</div>
309
327
  }
310
328
  component App() {
311
- <Child cls={#style.missing} />
329
+ <Child cls={style 'missing'} />
312
330
 
313
331
  <style>
314
332
  .other {
@@ -319,14 +337,14 @@ component App() {
319
337
  expect(() => compile(source, 'test.tsrx')).toThrow(/does not exist as a stand-alone class/);
320
338
  });
321
339
 
322
- it('errors when #style is used with a dynamic expression', () => {
340
+ it('errors when {style} is used with a dynamic expression', () => {
323
341
  const source = `
324
342
  component Child({ cls }) {
325
343
  <div class={cls}>{'text'}</div>
326
344
  }
327
- component App() {
328
- const key = 'highlight';
329
- <Child cls={#style[key]} />
345
+ component App() {
346
+ const key = 'highlight';
347
+ <Child cls={style 'highlight' + key} />
330
348
 
331
349
  <style>
332
350
  .highlight {
@@ -334,27 +352,32 @@ component App() {
334
352
  }
335
353
  </style>
336
354
  }`;
337
- expect(() => compile(source, 'test.tsrx')).toThrow(
338
- /must use a dot property or static string/,
339
- );
355
+ expect(() => compile(source, 'test.tsrx')).toThrow(/must be used in the form/);
340
356
  });
341
357
 
342
- it('errors when #style is used outside of a component', () => {
343
- const source = `function notAComponent() {
344
- const cls = #style.foo;
358
+ it('errors when {style} is used as a child expression', () => {
359
+ const source = `component App() {
360
+ <div>{style 'foo'}</div>
361
+ <style>
362
+ .foo {
363
+ color: red;
364
+ }
365
+ </style>
345
366
  }`;
346
- expect(() => compile(source, 'test.tsrx')).toThrow(/can only be used within a component/);
367
+ expect(() => compile(source, 'test.tsrx')).toThrow(
368
+ /can only be used as an element attribute value/,
369
+ );
347
370
  });
348
371
  });
349
372
 
350
373
  describe('compiler output', () => {
351
- it('generates #style object with standalone classes for client mode', () => {
374
+ it('inlines scoped class strings for client mode', () => {
352
375
  const source = `
353
376
  component Child({ cls }) {
354
377
  <div class={cls}>{'text'}</div>
355
378
  }
356
379
  export component App() {
357
- <Child cls={#style.highlight} />
380
+ <Child cls={style 'highlight'} />
358
381
 
359
382
  <style>
360
383
  .highlight {
@@ -368,13 +391,13 @@ export component App() {
368
391
  expect(js.code).toMatch(/tsrx-[a-z0-9]+/);
369
392
  });
370
393
 
371
- it('generates #style object with standalone classes for server mode', () => {
394
+ it('inlines scoped class strings for server mode', () => {
372
395
  const source = `
373
396
  component Child({ cls }) {
374
397
  <div class={cls}>{'text'}</div>
375
398
  }
376
399
  export component App() {
377
- <Child cls={#style.highlight} />
400
+ <Child cls={style 'highlight'} />
378
401
 
379
402
  <style>
380
403
  .highlight {
@@ -32,10 +32,8 @@ var root_25 = _$_.template(`<button class="increment">increment</button><!>`, 1,
32
32
 
33
33
  import { track, trackAsync } from 'ripple';
34
34
 
35
- var _$__u0023_server = {
36
- formatValue(...args) {
37
- return _$_.rpc('1215faad', args);
38
- }
35
+ const formatValue = function (...args) {
36
+ return _$_.rpc('1215faad', args);
39
37
  };
40
38
 
41
39
  export function AsyncWithServerCall(__anchor, _, __block) {
@@ -54,7 +52,7 @@ export function AsyncWithServerCall(__anchor, _, __block) {
54
52
  _$_.try(
55
53
  node,
56
54
  (__anchor) => {
57
- let lazy_1 = _$_.track_async(() => _$_.with_scope(__block, () => _$__u0023_server.formatValue(_$_.get(lazy))), __block, 'f0c2b41e');
55
+ let lazy_1 = _$_.track_async(() => _$_.with_scope(__block, () => formatValue(_$_.get(lazy))), __block, 'f0c2b41e');
58
56
  var p_1 = root_1();
59
57
 
60
58
  {
@@ -13,6 +13,10 @@ export const _$_server_$_ = (() => {
13
13
  return _$_server_$_;
14
14
  })();
15
15
 
16
+ const formatValue = function (...args) {
17
+ return _$_server_$_.formatValue(...args);
18
+ };
19
+
16
20
  export function AsyncWithServerCall() {
17
21
  _$_.push_component();
18
22
 
@@ -34,7 +38,7 @@ export function AsyncWithServerCall() {
34
38
  () => {
35
39
  _$_.output_push('<!--[-->');
36
40
 
37
- let lazy_1 = _$_.track_async(() => _$_server_$_.formatValue(_$_.get(lazy)), 'f0c2b41e');
41
+ let lazy_1 = _$_.track_async(() => formatValue(_$_.get(lazy)), 'f0c2b41e');
38
42
 
39
43
  _$_.regular_block(() => {
40
44
  _$_.output_push('<p');
@@ -1,11 +1,13 @@
1
1
  import { track, trackAsync } from 'ripple';
2
2
 
3
- #server {
3
+ module server {
4
4
  export async function formatValue(n: number): Promise<string> {
5
5
  return `server-${n}`;
6
6
  }
7
7
  }
8
8
 
9
+ import { formatValue } from server;
10
+
9
11
  export component AsyncWithServerCall() {
10
12
  let &[count] = track(0);
11
13
 
@@ -18,7 +20,7 @@ export component AsyncWithServerCall() {
18
20
  {'increment'}
19
21
  </button>
20
22
  try {
21
- let &[data] = trackAsync(() => #server.formatValue(count));
23
+ let &[data] = trackAsync(() => formatValue(count));
22
24
  <p class="result">{data}</p>
23
25
  } pending {
24
26
  <p class="loading">{'loading...'}</p>
@@ -111,7 +111,7 @@ describe('hydration > html tags', () => {
111
111
  expect(html).toContain('toc');
112
112
  });
113
113
 
114
- it('reproduces hydration mismatch when client has default props (DocsPage #server pattern)', async () => {
114
+ it('reproduces hydration mismatch when client has default props (DocsPage module server pattern)', async () => {
115
115
  await hydrateComponent(
116
116
  ServerComponents.HtmlWithServerData,
117
117
  ClientComponents.HtmlWithClientDefaults,
@@ -77,7 +77,7 @@ describe('hydration > trackAsync serialization', () => {
77
77
  expect(container.querySelector('.result')?.textContent).toBe('count-1');
78
78
  });
79
79
 
80
- it('reruns trackAsync via #server RPC call when a dependency changes', async () => {
80
+ it('reruns trackAsync via module server RPC call when a dependency changes', async () => {
81
81
  const originalFetch = globalThis.fetch;
82
82
  const fetchMock = vi.fn(async (_url, init) => {
83
83
  const args = devalue.parse(init.body);
@@ -1,6 +1,6 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`compiler server block tests > compiles server block with with only supported types 1`] = `
3
+ exports[`compiler server module tests > compiles module server with only supported types 1`] = `
4
4
  "import * as _$_ from 'ripple/internal/server';
5
5
 
6
6
  export const _$_server_$_ = (() => {
@@ -73,6 +73,20 @@ export component Layout(props) {
73
73
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).not.toThrow();
74
74
  });
75
75
 
76
+ it('compiles indented direct double-quoted text children in SSR mode', () => {
77
+ const source = `
78
+ export default component A() {
79
+ <div>
80
+ "Hello"
81
+ </div>
82
+ }`;
83
+
84
+ const result = compile(source, 'test.tsrx', { mode: 'server' }).js.code;
85
+
86
+ expect(result).toContain(`_$_.output_push('Hello')`);
87
+ expect(result).not.toContain(`"Hello";`);
88
+ });
89
+
76
90
  it('throws error for calling children as a function in SSR mode', () => {
77
91
  const source = `
78
92
  export component Layout({ children }) {
@@ -118,10 +132,10 @@ export component App() {
118
132
  });
119
133
  });
120
134
 
121
- describe('compiler server block tests', () => {
122
- it('compiles server block with with only supported types', () => {
135
+ describe('compiler server module tests', () => {
136
+ it('compiles module server with only supported types', () => {
123
137
  const source = `
124
- #server {
138
+ module server {
125
139
  function something() {
126
140
  return 'unexported function';
127
141
  }
@@ -157,9 +171,43 @@ describe('compiler server block tests', () => {
157
171
  expect(result.js.code).toMatchSnapshot();
158
172
  });
159
173
 
160
- it('throws error for unsupported exported object pattern in server block', () => {
174
+ it('compiles imports from module server as server-call wrappers', () => {
175
+ const source = `
176
+ module server {
177
+ export async function loadUser(id) {
178
+ return { id };
179
+ }
180
+ }
181
+
182
+ import { loadUser as getUser } from server;
183
+
184
+ export component App() {
185
+ const user = getUser('1');
186
+ <div>{user.id}</div>
187
+ }`;
188
+
189
+ const result = compile(source, 'test.tsrx', { mode: 'server' });
190
+ expect(result.js.code).toContain('const getUser = function (...args)');
191
+ expect(result.js.code).toContain('return _$_server_$_.loadUser(...args)');
192
+ expect(result.js.code).toContain('export const _$_server_$_');
193
+ });
194
+
195
+ it('throws when server exports are used through direct member access', () => {
196
+ const source = `
197
+ module server {
198
+ export async function loadUser() {}
199
+ }
200
+
201
+ server.loadUser();`;
202
+
203
+ expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrowError(
204
+ /Import server exports/,
205
+ );
206
+ });
207
+
208
+ it('throws error for unsupported exported object pattern in server module', () => {
161
209
  const source = `
162
- #server {
210
+ module server {
163
211
  const obj = { fn1: () => {}, fn2: () => {} };
164
212
 
165
213
  export const { fn1, fn2 } = obj;
@@ -168,9 +216,9 @@ describe('compiler server block tests', () => {
168
216
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrowError();
169
217
  });
170
218
 
171
- it('throws error for unsupported exported array pattern in server block', () => {
219
+ it('throws error for unsupported exported array pattern in server module', () => {
172
220
  const source = `
173
- #server {
221
+ module server {
174
222
  const arr = [() => {}, () => {}];
175
223
 
176
224
  export const [fnarr1, fnarr2] = arr;
@@ -179,9 +227,9 @@ describe('compiler server block tests', () => {
179
227
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrowError();
180
228
  });
181
229
 
182
- it('throws error for unsupported exported member expression via object in server block', () => {
230
+ it('throws error for unsupported exported member expression via object in server module', () => {
183
231
  const source = `
184
- #server {
232
+ module server {
185
233
  const obj = { fn1: () => {}, fn2: () => {} };
186
234
 
187
235
  export const objProp = obj.fn1;
@@ -190,9 +238,9 @@ describe('compiler server block tests', () => {
190
238
  expect(() => compile(source, 'test.tsrx', { mode: 'server' })).toThrowError();
191
239
  });
192
240
 
193
- it('throws error for unsupported exported member expression via array in server block', () => {
241
+ it('throws error for unsupported exported member expression via array in server module', () => {
194
242
  const source = `
195
- #server {
243
+ module server {
196
244
  const arr = [() => {}, () => {}];
197
245
 
198
246
  export const arrIndex0 = arr[0];
@@ -1,15 +1,15 @@
1
1
  import { track } from 'ripple';
2
2
  import { compile } from '@tsrx/ripple';
3
3
 
4
- describe('#style identifier (server)', () => {
4
+ describe('{style} directive (server)', () => {
5
5
  describe('basic usage with components', () => {
6
- it('passes scoped class to a child component via #style', async () => {
6
+ it('passes scoped class to a child component via {style}', async () => {
7
7
  component Child({ className }: { className: string }) {
8
8
  <div class={className}>{'styled child'}</div>
9
9
  }
10
10
 
11
11
  component Parent() {
12
- <Child className={#style.highlight} />
12
+ <Child className={style 'highlight'} />
13
13
 
14
14
  <style>
15
15
  .highlight {
@@ -29,14 +29,14 @@ describe('#style identifier (server)', () => {
29
29
  expect(classes.some((cls: string) => cls === 'highlight')).toBe(true);
30
30
  });
31
31
 
32
- it('passes multiple #style classes to a child component', async () => {
32
+ it('passes multiple {style} classes to a child component', async () => {
33
33
  component Child({ primary, secondary }: { primary: string; secondary: string }) {
34
34
  <div class={primary}>{'primary'}</div>
35
35
  <span class={secondary}>{'secondary'}</span>
36
36
  }
37
37
 
38
38
  component Parent() {
39
- <Child primary={#style.primary} secondary={#style.secondary} />
39
+ <Child primary={style 'primary'} secondary={style 'secondary'} />
40
40
 
41
41
  <style>
42
42
  .primary {
@@ -68,13 +68,13 @@ describe('#style identifier (server)', () => {
68
68
  });
69
69
 
70
70
  describe('parent styling applied to child', () => {
71
- it('allows parent to style child elements via #style prop', async () => {
71
+ it('allows parent to style child elements via {style} prop', async () => {
72
72
  component Button({ extraClass }: { extraClass?: string }) {
73
73
  <button class={extraClass ?? ''}>{'Click me'}</button>
74
74
  }
75
75
 
76
76
  component App() {
77
- <Button extraClass={#style.fancy} />
77
+ <Button extraClass={style 'fancy'} />
78
78
 
79
79
  <style>
80
80
  .fancy {
@@ -93,7 +93,7 @@ describe('#style identifier (server)', () => {
93
93
  expect(classes.some((cls: string) => cls === 'fancy')).toBe(true);
94
94
  });
95
95
 
96
- it('child can combine its own classes with parent #style class', async () => {
96
+ it('child can combine its own classes with parent {style} class', async () => {
97
97
  component Card({ className }: { className?: string }) {
98
98
  <div class={['card-base', className ?? '']}>{'card content'}</div>
99
99
 
@@ -105,7 +105,7 @@ describe('#style identifier (server)', () => {
105
105
  }
106
106
 
107
107
  component App() {
108
- <Card className={#style.themed} />
108
+ <Card className={style 'themed'} />
109
109
 
110
110
  <style>
111
111
  .themed {
@@ -133,7 +133,7 @@ describe('#style identifier (server)', () => {
133
133
 
134
134
  component App() {
135
135
  <div class="parent">
136
- <Child cls={#style.dual} />
136
+ <Child cls={style 'dual'} />
137
137
  </div>
138
138
 
139
139
  <style>
@@ -158,7 +158,7 @@ describe('#style identifier (server)', () => {
158
158
  );
159
159
  });
160
160
 
161
- it('passes scoped class to a dynamic child component via #style', async () => {
161
+ it('passes scoped class to a dynamic child component via {style}', async () => {
162
162
  component Child({ cls }: { cls: string }) {
163
163
  <span class={cls}>{'text'}</span>
164
164
  }
@@ -166,7 +166,7 @@ describe('#style identifier (server)', () => {
166
166
  component Parent() {
167
167
  let dynamic = track(() => Child);
168
168
  <div class="wrapper">
169
- <@dynamic cls={#style.text} />
169
+ <@dynamic cls={style 'text'} />
170
170
  </div>
171
171
 
172
172
  <style>
@@ -261,13 +261,13 @@ describe('#style identifier (server)', () => {
261
261
  });
262
262
 
263
263
  describe('server compiler output', () => {
264
- it('generates #style object with standalone classes', () => {
264
+ it('inlines scoped class strings', () => {
265
265
  const source = `
266
266
  component Child({ cls }: { cls: string }) {
267
267
  <div class={cls}>{'text'}</div>
268
268
  }
269
269
  export component App() {
270
- <Child cls={#style.highlight} />
270
+ <Child cls={style 'highlight'} />
271
271
 
272
272
  <style>
273
273
  .highlight {
@@ -288,7 +288,7 @@ export component App() {
288
288
  }
289
289
 
290
290
  component App() {
291
- <Child cls={#style.styled} />
291
+ <Child cls={style 'styled'} />
292
292
 
293
293
  <style>
294
294
  .styled {
@@ -1,95 +0,0 @@
1
- // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
-
3
- exports[`compiler server block tests > compiles server block with with only supported types 1`] = `
4
- "import * as _$_ from 'ripple/internal/server';
5
-
6
- export const _$_server_$_ = (() => {
7
- var _$_server_$_ = {};
8
-
9
- function something() {
10
- return 'unexported function';
11
- }
12
-
13
- _$_server_$_.fetchUser = async function fetchUser(id) {
14
- const response = await fetch(\`/api/user/\${id}\`);
15
- const data = await response.json();
16
-
17
- return data;
18
- };
19
-
20
- const fetchUserAlias = fetchUser;
21
- const AliasForFetchUserAlias = fetchUserAlias;
22
-
23
- {
24
- _$_server_$_.AnotherAlias = AliasForFetchUserAlias;
25
- }
26
-
27
- {
28
- _$_server_$_.func = function test() {
29
- return 'test';
30
- };
31
- }
32
-
33
- {
34
- _$_server_$_.func2 = function () {
35
- return 'test';
36
- };
37
- }
38
-
39
- {
40
- _$_server_$_.func3 = () => {
41
- return 'test';
42
- };
43
- }
44
-
45
- {
46
- _$_server_$_.fetchUserAlias = fetchUserAlias;
47
- _$_server_$_.AliasForFetchUserAlias = AliasForFetchUserAlias;
48
- }
49
-
50
- return _$_server_$_;
51
- })();"
52
- `;
53
-
54
- exports[`compiler typescript tests > compiles TSInstantiationExpression 1`] = `
55
- "import * as _$_ from 'ripple/internal/server';
56
-
57
- function makeBox(value) {
58
- return { value };
59
- }
60
-
61
- const makeStringBox = (makeBox);
62
- const stringBox = makeStringBox('abc');
63
- const ErrorMap = (Map);
64
- const errorMap = new ErrorMap();"
65
- `;
66
-
67
- exports[`compiler typescript tests > removes class TypeScript syntax from JS output 1`] = `
68
- "import * as _$_ from 'ripple/internal/server';
69
-
70
- class PrintEvent {
71
- text;
72
-
73
- constructor(text) {
74
- this.text = text;
75
- }
76
- }"
77
- `;
78
-
79
- exports[`compiler typescript tests > removes class extends type arguments from JS output 1`] = `
80
- "import * as _$_ from 'ripple/internal/server';
81
-
82
- class StringMap extends Map {
83
- constructor() {
84
- super();
85
- }
86
- }"
87
- `;
88
-
89
- exports[`compiler typescript tests > removes type assertions from function parameters and leaves default values 1`] = `
90
- "import * as _$_ from 'ripple/internal/server';
91
-
92
- function getString(e = 'test') {
93
- return e;
94
- }"
95
- `;
@@ -1,95 +0,0 @@
1
- // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
-
3
- exports[`compiler server block tests > compiles server block with with only supported types 1`] = `
4
- "import * as _$_ from 'ripple/internal/server';
5
-
6
- export const _$_server_$_ = (() => {
7
- var _$_server_$_ = {};
8
-
9
- function something() {
10
- return 'unexported function';
11
- }
12
-
13
- _$_server_$_.fetchUser = async function fetchUser(id) {
14
- const response = await fetch(\`/api/user/\${id}\`);
15
- const data = await response.json();
16
-
17
- return data;
18
- };
19
-
20
- const fetchUserAlias = fetchUser;
21
- const AliasForFetchUserAlias = fetchUserAlias;
22
-
23
- {
24
- _$_server_$_.AnotherAlias = AliasForFetchUserAlias;
25
- }
26
-
27
- {
28
- _$_server_$_.func = function test() {
29
- return 'test';
30
- };
31
- }
32
-
33
- {
34
- _$_server_$_.func2 = function () {
35
- return 'test';
36
- };
37
- }
38
-
39
- {
40
- _$_server_$_.func3 = () => {
41
- return 'test';
42
- };
43
- }
44
-
45
- {
46
- _$_server_$_.fetchUserAlias = fetchUserAlias;
47
- _$_server_$_.AliasForFetchUserAlias = AliasForFetchUserAlias;
48
- }
49
-
50
- return _$_server_$_;
51
- })();"
52
- `;
53
-
54
- exports[`compiler typescript tests > compiles TSInstantiationExpression 1`] = `
55
- "import * as _$_ from 'ripple/internal/server';
56
-
57
- function makeBox(value) {
58
- return { value };
59
- }
60
-
61
- const makeStringBox = (makeBox);
62
- const stringBox = makeStringBox('abc');
63
- const ErrorMap = (Map);
64
- const errorMap = new ErrorMap();"
65
- `;
66
-
67
- exports[`compiler typescript tests > removes class TypeScript syntax from JS output 1`] = `
68
- "import * as _$_ from 'ripple/internal/server';
69
-
70
- class PrintEvent {
71
- text;
72
-
73
- constructor(text) {
74
- this.text = text;
75
- }
76
- }"
77
- `;
78
-
79
- exports[`compiler typescript tests > removes class extends type arguments from JS output 1`] = `
80
- "import * as _$_ from 'ripple/internal/server';
81
-
82
- class StringMap extends Map {
83
- constructor() {
84
- super();
85
- }
86
- }"
87
- `;
88
-
89
- exports[`compiler typescript tests > removes type assertions from function parameters and leaves default values 1`] = `
90
- "import * as _$_ from 'ripple/internal/server';
91
-
92
- function getString(e = 'test') {
93
- return e;
94
- }"
95
- `;