ripple 0.2.204 → 0.2.205

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.204",
6
+ "version": "0.2.205",
7
7
  "type": "module",
8
8
  "module": "src/runtime/index-client.js",
9
9
  "main": "src/runtime/index-client.js",
@@ -97,6 +97,6 @@
97
97
  "vscode-languageserver-types": "^3.17.5"
98
98
  },
99
99
  "peerDependencies": {
100
- "ripple": "0.2.204"
100
+ "ripple": "0.2.205"
101
101
  }
102
102
  }
@@ -1749,15 +1749,7 @@ function RipplePlugin(config) {
1749
1749
  jsx_parseAttributeValue() {
1750
1750
  switch (this.type) {
1751
1751
  case tt.braceL:
1752
- const t = this.jsx_parseExpressionContainer();
1753
- return (
1754
- t.expression.type === 'JSXEmptyExpression' &&
1755
- this.raise(
1756
- /** @type {AST.NodeWithLocation} */ (t).start,
1757
- 'attributes must only be assigned a non-empty expression',
1758
- ),
1759
- t
1760
- );
1752
+ return this.jsx_parseExpressionContainer();
1761
1753
  case tstt.jsxTagStart:
1762
1754
  case tt.string:
1763
1755
  return this.parseExprAtom();
@@ -10,7 +10,10 @@
10
10
  StyleClasses,
11
11
  } from '#compiler';
12
12
  */
13
- /** @import * as AST from 'estree' */
13
+ /**
14
+ @import * as AST from 'estree';
15
+ @import * as ESTreeJSX from 'estree-jsx';
16
+ */
14
17
 
15
18
  import * as b from '../../../utils/builders.js';
16
19
  import { walk } from 'zimmerframe';
@@ -959,6 +962,31 @@ const visitors = {
959
962
 
960
963
  for (const attr of node.attributes) {
961
964
  if (attr.type === 'Attribute') {
965
+ if (attr.value && attr.value.type === 'JSXEmptyExpression') {
966
+ const value = /** @type {ESTreeJSX.JSXEmptyExpression & AST.NodeWithLocation} */ (
967
+ attr.value
968
+ );
969
+ error(
970
+ 'attributes must only be assigned a non-empty expression',
971
+ state.analysis.module.filename,
972
+ {
973
+ ...value,
974
+ start: value.start - 1,
975
+ end: value.end + 1,
976
+ loc: {
977
+ start: {
978
+ line: value.loc.start.line,
979
+ column: value.loc.start.column - 1,
980
+ },
981
+ end: {
982
+ line: value.loc.end.line,
983
+ column: value.loc.end.column + 1,
984
+ },
985
+ },
986
+ },
987
+ context.state.loose ? context.state.analysis.errors : undefined,
988
+ );
989
+ }
962
990
  if (attr.name.type === 'Identifier') {
963
991
  attribute_names.add(attr.name);
964
992
 
@@ -2492,11 +2492,16 @@ function transform_ts_child(node, context) {
2492
2492
  if (attr.type === 'Attribute') {
2493
2493
  const metadata = { await: false };
2494
2494
  const name = visit(attr.name, { ...state, metadata });
2495
+ const attr_value = /** @type { AST.Expression & AST.NodeWithLocation | null} */ (
2496
+ attr.value
2497
+ );
2495
2498
  const value =
2496
- attr.value === null
2497
- ? b.literal(true)
2499
+ attr_value === null
2500
+ ? // <div attr>, not adding `name` for loc because `jsx_name` below
2501
+ // will take care of the mapping JSXAttribute's JSXIdentifier
2502
+ b.literal(true)
2498
2503
  : // reset init, update, final to avoid adding attr value to the component body
2499
- visit(attr.value, SetStateForOutsideComponent(state, { metadata }));
2504
+ visit(attr_value, SetStateForOutsideComponent(state, { metadata }));
2500
2505
 
2501
2506
  // Handle both regular identifiers and tracked identifiers
2502
2507
  /** @type {string} */
@@ -2524,7 +2529,23 @@ function transform_ts_child(node, context) {
2524
2529
  jsx_name,
2525
2530
  b.jsx_expression_container(
2526
2531
  /** @type {AST.Expression} */ (value),
2527
- /** @type {AST.NodeWithLocation} */ (attr.value),
2532
+ attr_value === null
2533
+ ? /** @type {AST.NodeWithLocation} */ (value)
2534
+ : // account location for opening and closing braces around the expression
2535
+ /** @type {AST.NodeWithLocation} */ ({
2536
+ start: attr_value.start - 1,
2537
+ end: attr_value.end + 1,
2538
+ loc: {
2539
+ start: {
2540
+ line: attr_value.loc.start.line,
2541
+ column: attr_value.loc.start.column - 1,
2542
+ },
2543
+ end: {
2544
+ line: attr_value.loc.end.line,
2545
+ column: attr_value.loc.end.column + 1,
2546
+ },
2547
+ },
2548
+ }),
2528
2549
  ),
2529
2550
  attr.shorthand ?? false,
2530
2551
  /** @type {AST.NodeWithLocation} */ (attr),
@@ -3587,6 +3608,16 @@ function create_tsx_with_typescript_support(comments) {
3587
3608
  context.write(node.name);
3588
3609
  context.location(loc.end.line, loc.end.column);
3589
3610
  },
3611
+ JSXExpressionContainer(node, context) {
3612
+ const loc = /** @type {AST.SourceLocation} */ (node.loc);
3613
+ if (!loc) {
3614
+ base_tsx.JSXExpressionContainer?.(node, context);
3615
+ return;
3616
+ }
3617
+ context.location(loc.start.line, loc.start.column);
3618
+ base_tsx.JSXExpressionContainer?.(node, context);
3619
+ context.location(loc.end.line, loc.end.column);
3620
+ },
3590
3621
  MethodDefinition(node, context) {
3591
3622
  node.value.metadata.is_method = true;
3592
3623
  /** @type {AST.Position | undefined} */
@@ -652,6 +652,11 @@ export function convert_source_map_to_mappings(
652
652
  }
653
653
  return;
654
654
  } else if (node.type === 'JSXExpressionContainer') {
655
+ if (node.loc) {
656
+ mappings.push(
657
+ get_mapping_from_node(node, src_to_gen_map, gen_line_offsets, mapping_data_verify_only),
658
+ );
659
+ }
655
660
  // Visit the expression inside {}
656
661
  if (node.expression) {
657
662
  visit(node.expression);
@@ -131,6 +131,7 @@ declare module 'estree' {
131
131
  StyleIdentifier: StyleIdentifier;
132
132
  ServerIdentifier: ServerIdentifier;
133
133
  Text: TextNode;
134
+ JSXEmptyExpression: ESTreeJSX.JSXEmptyExpression;
134
135
  }
135
136
 
136
137
  // Missing estree type
@@ -15,7 +15,7 @@ export class TrackedDate extends Date {
15
15
  // @ts-ignore
16
16
  super(...params);
17
17
 
18
- var block = this.#block = safe_scope();
18
+ var block = (this.#block = safe_scope());
19
19
  this.#time = tracked(super.getTime(), block);
20
20
 
21
21
  if (!init) this.#init();
@@ -216,11 +216,12 @@ export function bindValue(maybe_tracked, set_func = undefined) {
216
216
  value = [].map.call(select.querySelectorAll(query), get_option_value);
217
217
  } else {
218
218
  /** @type {HTMLOptionElement | null} */
219
- // @ts-ignore
220
219
  var selected_option =
221
- select.querySelector(query) ??
220
+ /** @type {HTMLOptionElement | null} */ (select.querySelector(query)) ??
222
221
  // will fall back to first non-disabled option if no option is selected
223
- select.querySelector('option:not([disabled])');
222
+ /** @type {HTMLOptionElement | null} */ (
223
+ select.querySelector('option:not([disabled])')
224
+ );
224
225
  value = selected_option && get_option_value(selected_option);
225
226
  }
226
227
 
@@ -234,8 +235,9 @@ export function bindValue(maybe_tracked, set_func = undefined) {
234
235
  // Mounting and value undefined -> take selection from dom
235
236
  if (mounting && value === undefined) {
236
237
  /** @type {HTMLOptionElement | null} */
237
- // @ts-ignore
238
- var selected_option = select.querySelector(':checked');
238
+ var selected_option = /** @type {HTMLOptionElement | null} */ (
239
+ select.querySelector(':checked')
240
+ );
239
241
  if (selected_option !== null) {
240
242
  value = get_option_value(selected_option);
241
243
  setter(value);
@@ -532,11 +534,9 @@ export function bind_content_editable(maybe_tracked, property, set_func = undefi
532
534
  var value = getter();
533
535
  if (element[property] !== value) {
534
536
  if (value == null) {
535
- // @ts-ignore
536
537
  var non_null_value = element[property];
537
538
  setter(non_null_value);
538
539
  } else {
539
- // @ts-ignore
540
540
  element[property] = value + '';
541
541
  }
542
542
  }