ripple 0.2.79 → 0.2.81

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 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.2.79",
6
+ "version": "0.2.81",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -354,40 +354,6 @@ function RipplePlugin(config) {
354
354
 
355
355
  jsx_parseAttribute() {
356
356
  let node = this.startNode();
357
- const lookahead = this.lookahead();
358
-
359
- if (lookahead.type?.label === ':') {
360
- let id = this.startNode();
361
- id.name = this.value;
362
- node.name = id;
363
- this.next();
364
- this.finishNode(id, 'Identifier');
365
-
366
- if (this.lookahead().value !== '=') {
367
- this.unexpected();
368
- }
369
- this.next();
370
- if (this.lookahead().type !== tt.braceL) {
371
- this.unexpected();
372
- }
373
- this.next();
374
- const value = this.jsx_parseAttributeValue();
375
- const expression = value.expression;
376
- node.get = null;
377
- node.set = null;
378
-
379
- if (expression.type == 'SequenceExpression') {
380
- node.get = expression.expressions[0];
381
- node.set = expression.expressions[1];
382
- if (expression.expressions.length > 2) {
383
- this.unexpected();
384
- }
385
- } else {
386
- node.get = expression;
387
- }
388
-
389
- return this.finishNode(node, 'AccessorAttribute');
390
- }
391
357
 
392
358
  if (this.eat(tt.braceL)) {
393
359
  if (this.value === 'ref') {
@@ -435,12 +435,6 @@ const visitors = {
435
435
  visit(attr.value, state);
436
436
  }
437
437
  }
438
- } else if (attr.type === 'AccessorAttribute') {
439
- error(
440
- 'Accessor props are not supported on DOM elements',
441
- state.analysis.module.filename,
442
- attr,
443
- );
444
438
  }
445
439
  }
446
440
 
@@ -458,12 +452,6 @@ const visitors = {
458
452
  attribute_names.add(attr.name);
459
453
  }
460
454
  visit(attr.value, state);
461
- } else if (attr.type === 'AccessorAttribute') {
462
- attribute_names.add(attr.name);
463
- visit(attr.get, state);
464
- if (attr.set) {
465
- visit(attr.set, state);
466
- }
467
455
  } else if (attr.type === 'SpreadAttribute') {
468
456
  visit(attr.argument, state);
469
457
  } else if (attr.type === 'RefAttribute') {
@@ -29,6 +29,7 @@ import {
29
29
  is_ripple_track_call,
30
30
  normalize_children,
31
31
  build_getter,
32
+ determine_namespace_for_children,
32
33
  } from '../../../utils.js';
33
34
  import is_reference from 'is-reference';
34
35
  import { object } from '../../../../utils/ast.js';
@@ -94,22 +95,6 @@ function visit_function(node, context) {
94
95
  context.next(state);
95
96
  }
96
97
 
97
- function determine_namespace_for_children(element_name, current_namespace) {
98
- if (element_name === 'foreignObject') {
99
- return 'html';
100
- }
101
-
102
- if (element_name === 'svg') {
103
- return 'svg';
104
- }
105
-
106
- if (element_name === 'math') {
107
- return 'mathml';
108
- }
109
-
110
- return current_namespace;
111
- }
112
-
113
98
  const visitors = {
114
99
  _: function set_scope(node, { next, state }) {
115
100
  const scope = state.scopes.get(node);
@@ -430,7 +415,6 @@ const visitors = {
430
415
  const is_dom_element = is_element_dom_element(node);
431
416
  const is_spreading = node.attributes.some((attr) => attr.type === 'SpreadAttribute');
432
417
  const spread_attributes = is_spreading ? [] : null;
433
-
434
418
  const child_namespace = is_dom_element
435
419
  ? determine_namespace_for_children(node.id.name, state.namespace)
436
420
  : state.namespace;
@@ -713,6 +697,20 @@ const visitors = {
713
697
  props.push(
714
698
  b.prop('get', attr.name, b.function(null, [], b.block([b.return(property)]))),
715
699
  );
700
+
701
+ if (attr.value.type === 'Identifier' && attr.value.tracked) {
702
+ props.push(
703
+ b.prop(
704
+ 'set',
705
+ attr.name,
706
+ b.function(
707
+ null,
708
+ [b.id('__v')],
709
+ b.block([b.stmt(visit(b.assignment('=', attr.value, b.id('__v'))))]),
710
+ ),
711
+ ),
712
+ );
713
+ }
716
714
  } else {
717
715
  props.push(b.prop('init', attr.name, property));
718
716
  }
@@ -727,50 +725,6 @@ const visitors = {
727
725
  );
728
726
  } else if (attr.type === 'RefAttribute') {
729
727
  props.push(b.prop('init', b.call('_$_.ref_prop'), visit(attr.argument, state), true));
730
- } else if (attr.type === 'AccessorAttribute') {
731
- let get_expr;
732
-
733
- if (
734
- attr.get.type === 'FunctionExpression' ||
735
- attr.get.type === 'ArrowFunctionExpression'
736
- ) {
737
- get_expr = context.state.scope.generate(attr.name.name + '_get');
738
-
739
- state.init.push(b.const(get_expr, visit(attr.get, state)));
740
- } else {
741
- get_expr = visit(attr.get, state);
742
- }
743
-
744
- props.push(
745
- b.prop('get', attr.name, b.function(null, [], b.block([b.return(b.call(get_expr))]))),
746
- );
747
-
748
- if (attr.set) {
749
- let set_expr;
750
-
751
- if (
752
- attr.set.type === 'FunctionExpression' ||
753
- attr.set.type === 'ArrowFunctionExpression'
754
- ) {
755
- set_expr = context.state.scope.generate(attr.name.name + '_set');
756
-
757
- state.init.push(b.const(set_expr, visit(attr.set, state)));
758
- } else {
759
- set_expr = visit(attr.set, state);
760
- }
761
-
762
- props.push(
763
- b.prop(
764
- 'set',
765
- attr.name,
766
- b.function(
767
- null,
768
- [b.id('__value')],
769
- b.block([b.return(b.call(set_expr, b.id('__value')))]),
770
- ),
771
- ),
772
- );
773
- }
774
728
  } else {
775
729
  throw new Error('TODO');
776
730
  }
@@ -802,20 +756,35 @@ const visitors = {
802
756
  }
803
757
  }
804
758
 
805
- if (is_spreading) {
759
+ const metadata = { tracking: false, await: false };
760
+ // We visit, but only to gather metadata
761
+ b.call(visit(node.id, { ...state, metadata }));
762
+
763
+ if (metadata.tracking) {
806
764
  state.init.push(
807
765
  b.stmt(
808
766
  b.call(
809
- node.id,
767
+ '_$_.composite',
768
+ b.thunk(visit(node.id, state)),
810
769
  id,
811
- b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block')),
812
- b.id('_$_.active_block'),
770
+ is_spreading
771
+ ? b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block'))
772
+ : b.object(props),
813
773
  ),
814
774
  ),
815
775
  );
816
776
  } else {
817
777
  state.init.push(
818
- b.stmt(b.call(visit(node.id, state), id, b.object(props), b.id('_$_.active_block'))),
778
+ b.stmt(
779
+ b.call(
780
+ visit(node.id, state),
781
+ id,
782
+ is_spreading
783
+ ? b.call('_$_.spread_props', b.thunk(b.object(props)), b.id('__block'))
784
+ : b.object(props),
785
+ b.id('_$_.active_block'),
786
+ ),
787
+ ),
819
788
  );
820
789
  }
821
790
  }
@@ -5,6 +5,7 @@ import path from 'node:path';
5
5
  import { print } from 'esrap';
6
6
  import {
7
7
  build_getter,
8
+ determine_namespace_for_children,
8
9
  escape_html,
9
10
  is_boolean_attribute,
10
11
  is_element_dom_element,
@@ -111,6 +112,9 @@ const visitors = {
111
112
  const is_dom_element = is_element_dom_element(node);
112
113
  const is_spreading = node.attributes.some((attr) => attr.type === 'SpreadAttribute');
113
114
  const spread_attributes = is_spreading ? [] : null;
115
+ const child_namespace = is_dom_element
116
+ ? determine_namespace_for_children(node.id.name, state.namespace)
117
+ : state.namespace;
114
118
 
115
119
  if (is_dom_element) {
116
120
  const is_void = is_void_element(node.id.name);
@@ -244,6 +248,7 @@ const visitors = {
244
248
  }
245
249
  } else {
246
250
  const props = [];
251
+ let children_prop = null;
247
252
 
248
253
  for (const attr of node.attributes) {
249
254
  if (attr.type === 'Attribute') {
@@ -251,6 +256,11 @@ const visitors = {
251
256
  const metadata = { tracking: false, await: false };
252
257
  let property = visit(attr.value, { ...state, metadata });
253
258
 
259
+ if (attr.name.name === 'children') {
260
+ children_prop = b.thunk(property);
261
+ continue;
262
+ }
263
+
254
264
  props.push(b.prop('init', attr.name, property));
255
265
  } else if (attr.type === 'SpreadAttribute') {
256
266
  props.push(
@@ -262,7 +272,33 @@ const visitors = {
262
272
  }
263
273
  }
264
274
 
265
- state.init.push(b.stmt(b.call(node.id.name, b.id('__output'), b.object(props))));
275
+ const children_filtered = [];
276
+
277
+ for (const child of node.children) {
278
+ if (child.type === 'Component') {
279
+ const id = child.id;
280
+ props.push(b.prop('init', id, visit(child, { ...state, namespace: child_namespace })));
281
+ } else {
282
+ children_filtered.push(child);
283
+ }
284
+ }
285
+
286
+ if (children_filtered.length > 0) {
287
+ const component_scope = context.state.scopes.get(node);
288
+ const children = visit(b.component(b.id('children'), [], children_filtered), {
289
+ ...context.state,
290
+ scope: component_scope,
291
+ namespace: child_namespace,
292
+ });
293
+
294
+ if (children_prop) {
295
+ children_prop.body = b.logical('??', children_prop.body, children);
296
+ } else {
297
+ props.push(b.prop('init', b.id('children'), children));
298
+ }
299
+ }
300
+
301
+ state.init.push(b.stmt(b.call(visit(node.id, state), b.id('__output'), b.object(props))));
266
302
  }
267
303
  },
268
304
 
@@ -706,4 +706,20 @@ export function build_getter(node, context) {
706
706
  }
707
707
 
708
708
  return node;
709
+ }
710
+
711
+ export function determine_namespace_for_children(element_name, current_namespace) {
712
+ if (element_name === 'foreignObject') {
713
+ return 'html';
714
+ }
715
+
716
+ if (element_name === 'svg') {
717
+ return 'svg';
718
+ }
719
+
720
+ if (element_name === 'math') {
721
+ return 'mathml';
722
+ }
723
+
724
+ return current_namespace;
709
725
  }
@@ -0,0 +1,22 @@
1
+ import { branch, destroy_block, render } from './blocks.js';
2
+ import { COMPOSITE_BLOCK } from './constants.js';
3
+ import { active_block } from './runtime.js';
4
+
5
+ export function composite(get_component, node, props) {
6
+ var anchor = node;
7
+ var b = null;
8
+
9
+ render(() => {
10
+ var component = get_component();
11
+
12
+ if (b !== null) {
13
+ destroy_block(b);
14
+ b = null;
15
+ }
16
+
17
+ b = branch(() => {
18
+ var block = active_block;
19
+ component(anchor, props, block);
20
+ });
21
+ }, COMPOSITE_BLOCK);
22
+ }
@@ -5,8 +5,8 @@ export var BRANCH_BLOCK = 1 << 4;
5
5
  export var FOR_BLOCK = 1 << 5;
6
6
  export var TRY_BLOCK = 1 << 6;
7
7
  export var IF_BLOCK = 1 << 7;
8
- export var ASYNC_BLOCK = 1 << 8;
9
- export var COMPAT_BLOCK = 1 << 9;
8
+ export var COMPOSITE_BLOCK = 1 << 8;
9
+ export var ASYNC_BLOCK = 1 << 9;
10
10
  export var CONTAINS_UPDATE = 1 << 10;
11
11
  export var CONTAINS_TEARDOWN = 1 << 11;
12
12
  export var BLOCK_HAS_RUN = 1 << 12;
@@ -16,7 +16,7 @@ export var DEFERRED = 1 << 15;
16
16
  export var PAUSED = 1 << 16;
17
17
  export var DESTROYED = 1 << 17;
18
18
 
19
- export var LOGIC_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK;
19
+ export var CONTROL_FLOW_BLOCK = FOR_BLOCK | IF_BLOCK | TRY_BLOCK | COMPOSITE_BLOCK;
20
20
 
21
21
  export var UNINITIALIZED = Symbol();
22
22
  /** @type {unique symbol} */
@@ -43,6 +43,8 @@ export {
43
43
  maybe_tracked,
44
44
  } from './runtime.js';
45
45
 
46
+ export { composite } from './composite.js';
47
+
46
48
  export { for_block as for } from './for.js';
47
49
 
48
50
  export { if_block as if } from './if.js';