@ripple-ts/prettier-plugin 0.3.6 → 0.3.8

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ripple-ts/prettier-plugin",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Ripple plugin for Prettier",
5
5
  "type": "module",
6
6
  "module": "src/index.js",
@@ -26,7 +26,7 @@
26
26
  "devDependencies": {
27
27
  "@types/node": "^24.3.0",
28
28
  "prettier": "^3.8.1",
29
- "ripple": "0.3.6"
29
+ "ripple": "0.3.8"
30
30
  },
31
31
  "dependencies": {},
32
32
  "files": [
package/src/index.js CHANGED
@@ -2076,6 +2076,10 @@ function printRippleNode(node, path, options, print, args) {
2076
2076
  nodeContent = printTSMethodSignature(node, path, options, print);
2077
2077
  break;
2078
2078
 
2079
+ case 'TSCallSignatureDeclaration':
2080
+ nodeContent = printTSCallSignatureDeclaration(node, path, options, print);
2081
+ break;
2082
+
2079
2083
  case 'TSEnumMember':
2080
2084
  nodeContent = printTSEnumMember(node, path, options, print);
2081
2085
  break;
@@ -2154,6 +2158,9 @@ function printRippleNode(node, path, options, print, args) {
2154
2158
  case 'TSConditionalType':
2155
2159
  nodeContent = printTSConditionalType(node, path, options, print);
2156
2160
  break;
2161
+ case 'TSInferType':
2162
+ nodeContent = ['infer ', path.call(print, 'typeParameter')];
2163
+ break;
2157
2164
 
2158
2165
  case 'TSMappedType':
2159
2166
  nodeContent = printTSMappedType(node, path, options, print);
@@ -5179,6 +5186,46 @@ function printTSMethodSignature(node, path, options, print) {
5179
5186
  return parts;
5180
5187
  }
5181
5188
 
5189
+ /**
5190
+ * Print a TypeScript call signature in an interface
5191
+ * @param {AST.TSCallSignatureDeclaration} node - The call signature node
5192
+ * @param {AstPath<AST.TSCallSignatureDeclaration>} path - The AST path
5193
+ * @param {RippleFormatOptions} options - Prettier options
5194
+ * @param {PrintFn} print - Print callback
5195
+ * @returns {Doc[]}
5196
+ */
5197
+ function printTSCallSignatureDeclaration(node, path, options, print) {
5198
+ /** @type {Doc[]} */
5199
+ const parts = [];
5200
+
5201
+ // Add TypeScript generics/type parameters if present
5202
+ if (node.typeParameters) {
5203
+ const type_params = path.call(print, 'typeParameters');
5204
+ if (Array.isArray(type_params)) {
5205
+ parts.push(...type_params);
5206
+ } else {
5207
+ parts.push(type_params);
5208
+ }
5209
+ }
5210
+
5211
+ parts.push('(');
5212
+ if (node.parameters && node.parameters.length > 0) {
5213
+ const params = path.map(print, 'parameters');
5214
+ for (let i = 0; i < params.length; i++) {
5215
+ if (i > 0) parts.push(', ');
5216
+ parts.push(params[i]);
5217
+ }
5218
+ }
5219
+ parts.push(')');
5220
+
5221
+ if (node.typeAnnotation) {
5222
+ parts.push(': ');
5223
+ parts.push(path.call(print, 'typeAnnotation'));
5224
+ }
5225
+
5226
+ return parts;
5227
+ }
5228
+
5182
5229
  /**
5183
5230
  * Print a TypeScript type reference (e.g., Array<string>)
5184
5231
  * @param {AST.TSTypeReference} node - The type reference node
package/src/index.test.js CHANGED
@@ -291,10 +291,10 @@ export default component App() {
291
291
  expect(result).toBeWithNewline(expected);
292
292
  });
293
293
 
294
- it('should format a component with an object reactive property notation props.@children', async () => {
294
+ it('should format a component with a dynamic component using props member access', async () => {
295
295
  const expected = `component Card(props) {
296
296
  <div class="card">
297
- <props.@children />
297
+ <@props.children />
298
298
  </div>
299
299
  }`;
300
300
 
@@ -652,26 +652,26 @@ import { Something, type Props, track } from 'ripple';`;
652
652
  expect(result).toBeWithNewline(expected);
653
653
  });
654
654
 
655
- it('should handle @ prefix', async () => {
655
+ it('should handle tracked variable with lazy destructuring', async () => {
656
656
  const input = `export default component App() {
657
657
  <div>
658
- let count = track(0);
659
- @count = 2;
660
- console.log(@count);
658
+ let &[count] = track(0);
659
+ count = 2;
661
660
  console.log(count);
662
- if (@count > 1) {
663
- <button onClick={() => @count++}>{@count}</button>
661
+ console.log(count);
662
+ if (count > 1) {
663
+ <button onClick={() => count++}>{count}</button>
664
664
  }
665
665
  </div>
666
666
  }`;
667
667
  const expected = `export default component App() {
668
668
  <div>
669
- let count = track(0);
670
- @count = 2;
671
- console.log(@count);
669
+ let &[count] = track(0);
670
+ count = 2;
671
+ console.log(count);
672
672
  console.log(count);
673
- if (@count > 1) {
674
- <button onClick={() => @count++}>{@count}</button>
673
+ if (count > 1) {
674
+ <button onClick={() => count++}>{count}</button>
675
675
  }
676
676
  </div>
677
677
  }`;
@@ -706,19 +706,19 @@ import { Something, type Props, track } from 'ripple';`;
706
706
  expect(result).toBeWithNewline(expected);
707
707
  });
708
708
 
709
- it('should preserve @ symbol in JSX attributes and shorthand syntax', async () => {
709
+ it('should format JSX attributes with tracked values', async () => {
710
710
  const input = `component App() {
711
- const count = track(0);
711
+ const &[count] = track(0);
712
712
 
713
- <Counter count={@count} />
714
- <Counter {@count} />
713
+ <Counter count={count} />
714
+ <Counter {count} />
715
715
  }`;
716
716
 
717
717
  const expected = `component App() {
718
- const count = track(0);
718
+ const &[count] = track(0);
719
719
 
720
- <Counter {@count} />
721
- <Counter {@count} />
720
+ <Counter {count} />
721
+ <Counter {count} />
722
722
  }`;
723
723
 
724
724
  const result = await format(input, { singleQuote: true });
@@ -963,7 +963,7 @@ export component Test({ a, b }: Props) {}`;
963
963
 
964
964
  it('should not strip @ from dynamic self-closing components', async () => {
965
965
  const expected = `component App() {
966
- <@ripple_object.@tracked_basic />
966
+ <@ripple_object.tracked_basic />
967
967
  }`;
968
968
 
969
969
  const result = await format(expected, { singleQuote: true, printWidth: 100 });
@@ -1733,7 +1733,7 @@ const program =
1733
1733
  });
1734
1734
 
1735
1735
  it('should keep parents in math subtraction and multiplication', async () => {
1736
- const expected = `let offset = track(() => (@page - 1) * @limit);`;
1736
+ const expected = `let offset = track(() => (page - 1) * limit);`;
1737
1737
 
1738
1738
  const result = await format(expected, { singleQuote: true, printWidth: 100 });
1739
1739
  expect(result).toBeWithNewline(expected);
@@ -2292,18 +2292,18 @@ component Child({ something }) {
2292
2292
 
2293
2293
  it('should correctly handle call expressions', async () => {
2294
2294
  const input = `export component App() {
2295
- const context = track(globalContext.get().theme);
2295
+ const &[context] = track(globalContext.get().theme);
2296
2296
  <div>
2297
2297
  <TypedComponent />
2298
- {@context}
2298
+ {context}
2299
2299
  </div>
2300
2300
  }`;
2301
2301
 
2302
2302
  const expected = `export component App() {
2303
- const context = track(globalContext.get().theme);
2303
+ const &[context] = track(globalContext.get().theme);
2304
2304
  <div>
2305
2305
  <TypedComponent />
2306
- {@context}
2306
+ {context}
2307
2307
  </div>
2308
2308
  }`;
2309
2309
 
@@ -2725,13 +2725,13 @@ function test() {
2725
2725
  const expected = `component App() {
2726
2726
  <button
2727
2727
  onClick={() => {
2728
- @hasError = false;
2728
+ hasError = false;
2729
2729
  try {
2730
- @hasError = false;
2730
+ hasError = false;
2731
2731
  // @ts-ignore
2732
2732
  obj['nonexistent']();
2733
2733
  } catch {
2734
- // @hasError = true;
2734
+ // hasError = true;
2735
2735
  }
2736
2736
  }}
2737
2737
  >
@@ -3254,6 +3254,14 @@ const items = [] as unknown[];`;
3254
3254
  expect(result).toBeWithNewline(expected);
3255
3255
  });
3256
3256
 
3257
+ it('should preserve TSCallSignatureDeclaration with conditional types', async () => {
3258
+ const expected = `interface TrackedCallable<V> {
3259
+ (props: V extends Component<infer P> ? P : never): V extends Component ? void : never;
3260
+ }`;
3261
+ const result = await format(expected, { printWidth: 100 });
3262
+ expect(result).toBeWithNewline(expected);
3263
+ });
3264
+
3257
3265
  it('should format TSNonNullExpression', async () => {
3258
3266
  const input = `component Test(){let value:string|null=null;let length=value!.length;<div>{length}</div>}`;
3259
3267
  const expected = `component Test() {
@@ -4369,7 +4377,7 @@ component Polygon() {
4369
4377
  // <div id="third-top-block">{"Top Scope - Show is true"}</div>
4370
4378
  // }
4371
4379
 
4372
- <button onClick={() => (@b = !@b)}>{"Toggle b"}</button>
4380
+ <button onClick={() => (b = !b)}>{"Toggle b"}</button>
4373
4381
  }`;
4374
4382
 
4375
4383
  const result = await format(expected, { printWidth: 100 });
@@ -4392,7 +4400,7 @@ component Polygon() {
4392
4400
  // <div>{"Top Scope - Show is true"}</div>
4393
4401
  // }
4394
4402
 
4395
- <button onClick={() => (@b = !@b)}>{"Toggle b"}</button>
4403
+ <button onClick={() => (b = !b)}>{"Toggle b"}</button>
4396
4404
  }`;
4397
4405
 
4398
4406
  const result = await format(expected, { printWidth: 100 });
@@ -4820,25 +4828,25 @@ component Polygon() {
4820
4828
  expect(result).toBeWithNewline(expected);
4821
4829
  });
4822
4830
 
4823
- it('should preserve @ symbol in JSX attributes inside <tsx:react>', async () => {
4831
+ it('should format JSX attributes inside <tsx:react>', async () => {
4824
4832
  const input = `component App() {
4825
- const count = track(0);
4833
+ const &[count] = track(0);
4826
4834
 
4827
4835
  <div>
4828
4836
  <h1>{'Hello, from Ripple!'}</h1>
4829
4837
  <tsx:react>
4830
- <Counter count={@count} />
4838
+ <Counter count={count} />
4831
4839
  </tsx:react>
4832
4840
  </div>
4833
4841
  }`;
4834
4842
 
4835
4843
  const expected = `component App() {
4836
- const count = track(0);
4844
+ const &[count] = track(0);
4837
4845
 
4838
4846
  <div>
4839
4847
  <h1>{'Hello, from Ripple!'}</h1>
4840
4848
  <tsx:react>
4841
- <Counter count={@count} />
4849
+ <Counter count={count} />
4842
4850
  </tsx:react>
4843
4851
  </div>
4844
4852
  }`;
@@ -4890,7 +4898,7 @@ component App() {
4890
4898
  <tsx:react>
4891
4899
  Hello world
4892
4900
  <DemoContext.Provider value={"Hello from Context!"}>
4893
- <Child count={@count} />
4901
+ <Child count={count} />
4894
4902
  </DemoContext.Provider>
4895
4903
  </tsx:react>
4896
4904
  }`;
@@ -4898,7 +4906,7 @@ component App() {
4898
4906
  <tsx:react>
4899
4907
  Hello world
4900
4908
  <DemoContext.Provider value={"Hello from Context!"}>
4901
- <Child count={@count} />
4909
+ <Child count={count} />
4902
4910
  </DemoContext.Provider>
4903
4911
  </tsx:react>
4904
4912
  }`;
@@ -4955,7 +4963,7 @@ component App() {
4955
4963
  const input = `component Test() {
4956
4964
  <button
4957
4965
  onClick={() => {
4958
- if (@status === 'a') @status = 'b'; else if (@status === 'b') @status = 'c'; else @status =
4966
+ if (status === 'a') status = 'b'; else if (status === 'b') status = 'c'; else status =
4959
4967
  'a';
4960
4968
  }}
4961
4969
  >
@@ -4965,9 +4973,9 @@ if (@status === 'a') @status = 'b'; else if (@status === 'b') @status = 'c'; els
4965
4973
  const expected = `component Test() {
4966
4974
  <button
4967
4975
  onClick={() => {
4968
- if (@status === 'a') @status = 'b';
4969
- else if (@status === 'b') @status = 'c';
4970
- else @status = 'a';
4976
+ if (status === 'a') status = 'b';
4977
+ else if (status === 'b') status = 'c';
4978
+ else status = 'a';
4971
4979
  }}
4972
4980
  >
4973
4981
  {'Click'}