@tsrx/prettier-plugin 0.3.74 → 0.3.76

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": "@tsrx/prettier-plugin",
3
- "version": "0.3.74",
3
+ "version": "0.3.76",
4
4
  "description": "Ripple plugin for Prettier",
5
5
  "type": "module",
6
6
  "module": "src/index.js",
@@ -27,7 +27,7 @@
27
27
  "prettier": "^3.8.3"
28
28
  },
29
29
  "dependencies": {
30
- "@tsrx/core": "0.1.22"
30
+ "@tsrx/core": "0.1.24"
31
31
  },
32
32
  "files": [
33
33
  "src/"
package/src/index.js CHANGED
@@ -42,16 +42,16 @@ const { replaceEndOfLine, willBreak } = utils;
42
42
  /** @type {import('prettier').Plugin['languages']} */
43
43
  export const languages = [
44
44
  {
45
- name: 'ripple',
46
- parsers: ['ripple'],
45
+ name: 'tsrx',
46
+ parsers: ['tsrx'],
47
47
  extensions: ['.tsrx'],
48
- vscodeLanguageIds: ['ripple'],
48
+ vscodeLanguageIds: ['tsrx', 'ripple'],
49
49
  },
50
50
  ];
51
51
 
52
52
  /** @type {import('prettier').Plugin['parsers']} */
53
53
  export const parsers = {
54
- ripple: {
54
+ tsrx: {
55
55
  astFormat: 'ripple-ast',
56
56
  /**
57
57
  * @param {string} text
@@ -1732,18 +1732,12 @@ function printRippleNode(node, path, options, print, args) {
1732
1732
  }
1733
1733
  case 'Identifier': {
1734
1734
  // Simple case - just return the name directly like Prettier core
1735
- const trackedPrefix = node.tracked ? '@' : '';
1736
1735
  let identifierContent;
1737
1736
  if (node.typeAnnotation) {
1738
1737
  const optionalMarker = node.optional ? '?' : '';
1739
- identifierContent = [
1740
- trackedPrefix + node.name,
1741
- optionalMarker,
1742
- ': ',
1743
- path.call(print, 'typeAnnotation'),
1744
- ];
1738
+ identifierContent = [node.name, optionalMarker, ': ', path.call(print, 'typeAnnotation')];
1745
1739
  } else {
1746
- identifierContent = trackedPrefix + node.name;
1740
+ identifierContent = node.name;
1747
1741
  }
1748
1742
  // Preserve parentheses for type-cast identifiers, but only if:
1749
1743
  // 1. The identifier itself is marked as parenthesized
@@ -4010,7 +4004,6 @@ function printMemberExpression(node, path, options, print) {
4010
4004
 
4011
4005
  let result;
4012
4006
  if (node.computed) {
4013
- // Check if the MemberExpression itself is tracked to add @ symbol
4014
4007
  const openBracket = node.optional ? '?.[' : '[';
4015
4008
  result = [objectPart, openBracket, propertyPart, ']'];
4016
4009
  } else {
@@ -6464,7 +6457,7 @@ function printJSXAttribute(attr, path, options, print) {
6464
6457
  */
6465
6458
  function printJSXElementName(node) {
6466
6459
  if (node.type === 'JSXIdentifier') {
6467
- return (isDynamicJSXIdentifier(node) ? '@' : '') + node.name;
6460
+ return node.name;
6468
6461
  }
6469
6462
  if (node.type === 'JSXMemberExpression') {
6470
6463
  return printJSXElementName(node.object) + '.' + printJSXElementName(node.property);
@@ -6477,14 +6470,6 @@ function printJSXElementName(node) {
6477
6470
  return 'Unknown';
6478
6471
  }
6479
6472
 
6480
- /**
6481
- * @param {ESTreeJSX.JSXIdentifier} node
6482
- * @returns {boolean}
6483
- */
6484
- function isDynamicJSXIdentifier(node) {
6485
- return /** @type {{ dynamic?: boolean }} */ (node).dynamic === true;
6486
- }
6487
-
6488
6473
  /**
6489
6474
  * Print a member expression as simple string (for element tag names)
6490
6475
  * @param {AST.Node} node - The node to print
@@ -6494,7 +6479,7 @@ function isDynamicJSXIdentifier(node) {
6494
6479
  */
6495
6480
  function printMemberExpressionSimple(node, options, computed = false) {
6496
6481
  if (node.type === 'JSXIdentifier') {
6497
- return (isDynamicJSXIdentifier(node) ? '@' : '') + node.name;
6482
+ return node.name;
6498
6483
  }
6499
6484
 
6500
6485
  if (node.type === 'JSXMemberExpression') {
@@ -6510,7 +6495,7 @@ function printMemberExpressionSimple(node, options, computed = false) {
6510
6495
  }
6511
6496
 
6512
6497
  if (node.type === 'Identifier') {
6513
- return (computed ? '' : node.tracked ? '@' : '') + node.name;
6498
+ return node.name;
6514
6499
  }
6515
6500
 
6516
6501
  if (node.type === 'MemberExpression') {
package/src/index.test.js CHANGED
@@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest';
2
2
  import prettier from 'prettier';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { dirname, join } from 'path';
5
- import { languages } from './index.js';
5
+ import { languages, parsers } from './index.js';
6
6
 
7
7
  const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = dirname(__filename);
@@ -40,13 +40,16 @@ expect.extend({
40
40
 
41
41
  describe('prettier-plugin', () => {
42
42
  it('registers .tsrx as a supported file extension', () => {
43
- const ripple_language = languages?.[0];
43
+ const tsrx_language = languages?.[0];
44
44
 
45
- if (!ripple_language) {
46
- throw new Error('Missing Ripple language metadata');
45
+ if (!tsrx_language) {
46
+ throw new Error('Missing TSRX language metadata');
47
47
  }
48
48
 
49
- expect(ripple_language.extensions).toContain('.tsrx');
49
+ expect(tsrx_language.extensions).toContain('.tsrx');
50
+ expect(tsrx_language.parsers).toContain('tsrx');
51
+ expect(parsers?.tsrx).toBeDefined();
52
+ expect(parsers?.ripple).toBeUndefined();
50
53
  });
51
54
 
52
55
  /**
@@ -55,7 +58,7 @@ describe('prettier-plugin', () => {
55
58
  */
56
59
  const format = async (code, options = {}) => {
57
60
  return await prettier.format(code, {
58
- parser: 'ripple',
61
+ parser: 'tsrx',
59
62
  plugins: [join(__dirname, 'index.js')],
60
63
  ...options,
61
64
  });
@@ -233,10 +236,10 @@ const items=[1,2,3];
233
236
  });
234
237
 
235
238
  it('keeps native fragments expression based', async () => {
236
- const input = `function App(){return <><div>"Hello world"</div>{value}</>}`;
239
+ const input = `function App(){return <><div>Hello world</div>{value}</>}`;
237
240
  const expected = `function App() {
238
241
  return <>
239
- <div>"Hello world"</div>
242
+ <div>Hello world</div>
240
243
  {value}
241
244
  </>;
242
245
  }`;
@@ -277,17 +280,17 @@ const items=[1,2,3];
277
280
  const input = `export function App() {
278
281
  let [count] = track(0);
279
282
  return <div>
280
- <p>"Count: "{count}</p>
281
- <p>"Count: "{count}</p>
282
- <button onClick={() => count++}>"Increment"</button>
283
+ <p>Count: {count}</p>
284
+ <p>Count: {count}</p>
285
+ <button onClick={() => count++}>Increment</button>
283
286
  </div>;
284
287
  }`;
285
288
  const expected = `export function App() {
286
289
  let [count] = track(0);
287
290
  return <div>
288
- <p>"Count: "{count}</p>
289
- <p>"Count: "{count}</p>
290
- <button onClick={() => count++}>"Increment"</button>
291
+ <p>Count: {count}</p>
292
+ <p>Count: {count}</p>
293
+ <button onClick={() => count++}>Increment</button>
291
294
  </div>;
292
295
  }`;
293
296
 
@@ -400,28 +403,6 @@ function App() {
400
403
  expect(result).toBeWithNewline(expected);
401
404
  });
402
405
 
403
- it('preserves dynamic component syntax', async () => {
404
- const input = `function App(){return <>@{
405
- function Basic(){return <><div>{"Basic Component"}</div></>;}
406
- const obj={Basic};
407
- const comp=obj.Basic;
408
- <@comp />
409
- }</>}`;
410
- const expected = `function App() {
411
- return <>@{
412
- function Basic() {
413
- return <><div>{"Basic Component"}</div></>;
414
- }
415
- const obj = { Basic };
416
- const comp = obj.Basic;
417
- <@comp />
418
- }</>;
419
- }`;
420
-
421
- const result = await format(input);
422
- expect(result).toBeWithNewline(expected);
423
- });
424
-
425
406
  it('formats raw HTML props inside native elements', async () => {
426
407
  const input = `function App(){return <article innerHTML={source}/>}`;
427
408
  const expected = `function App() {
@@ -608,10 +589,10 @@ const items=[1,2,3];
608
589
  });
609
590
 
610
591
  it('should keep sibling children in tsrx expression fragments on separate lines', async () => {
611
- const input = `function Test(p1,p2){return <><div>"Hello"</div><div>{p1}</div><div>{p2}</div></>}`;
592
+ const input = `function Test(p1,p2){return <><div>Hello</div><div>{p1}</div><div>{p2}</div></>}`;
612
593
  const expected = `function Test(p1, p2) {
613
594
  return <>
614
- <div>"Hello"</div>
595
+ <div>Hello</div>
615
596
  <div>{p1}</div>
616
597
  <div>{p2}</div>
617
598
  </>;
@@ -706,9 +687,9 @@ const items=[1,2,3];
706
687
  });
707
688
 
708
689
  it('keeps fitting single-child fragments inline and expands non-fitting single-child fragments', async () => {
709
- const input = `function Test(){const short=<><span>"Ready"</span></>;const long=<><ReallyLongComponentName first={alpha} second={beta} third={gamma}/></>;}`;
690
+ const input = `function Test(){const short=<><span>Ready</span></>;const long=<><ReallyLongComponentName first={alpha} second={beta} third={gamma}/></>;}`;
710
691
  const expected = `function Test() {
711
- const short = <><span>"Ready"</span></>;
692
+ const short = <><span>Ready</span></>;
712
693
  const long = <>
713
694
  <ReallyLongComponentName
714
695
  first={alpha}
@@ -723,16 +704,16 @@ const items=[1,2,3];
723
704
  });
724
705
 
725
706
  it('expands multi-child fragments while keeping fitting openers on the first line', async () => {
726
- const input = `function Test(){const short=<><div>"A"</div><div>"B"</div></>;const thisNameIsRidiculouslyLongEnoughToMissThePrintWidth=<><div>"A"</div><div>"B"</div></>;}`;
707
+ const input = `function Test(){const short=<><div>A</div><div>B</div></>;const thisNameIsRidiculouslyLongEnoughToMissThePrintWidth=<><div>A</div><div>B</div></>;}`;
727
708
  const expected = `function Test() {
728
709
  const short = <>
729
- <div>"A"</div>
730
- <div>"B"</div>
710
+ <div>A</div>
711
+ <div>B</div>
731
712
  </>;
732
713
  const thisNameIsRidiculouslyLongEnoughToMissThePrintWidth =
733
714
  <>
734
- <div>"A"</div>
735
- <div>"B"</div>
715
+ <div>A</div>
716
+ <div>B</div>
736
717
  </>;
737
718
  }`;
738
719
 
@@ -816,7 +797,7 @@ const items=[1,2,3];
816
797
  */
817
798
  const format = async (code, options = {}) => {
818
799
  return await prettier.format(code, {
819
- parser: 'ripple',
800
+ parser: 'tsrx',
820
801
  plugins: [join(__dirname, 'index.js')],
821
802
  ...options,
822
803
  });
@@ -829,7 +810,7 @@ const items=[1,2,3];
829
810
  */
830
811
  const formatWithCursorHelper = async (code, options) =>
831
812
  await prettier.formatWithCursor(code, {
832
- parser: 'ripple',
813
+ parser: 'tsrx',
833
814
  plugins: [join(__dirname, 'index.js')],
834
815
  ...options,
835
816
  });
@@ -882,13 +863,14 @@ const items=[1,2,3];
882
863
  });
883
864
 
884
865
  it('registers .tsrx as a supported file extension', () => {
885
- const ripple_language = languages?.[0];
866
+ const tsrx_language = languages?.[0];
886
867
 
887
- if (!ripple_language) {
888
- throw new Error('Missing Ripple language metadata');
868
+ if (!tsrx_language) {
869
+ throw new Error('Missing TSRX language metadata');
889
870
  }
890
871
 
891
- expect(ripple_language.extensions).toContain('.tsrx');
872
+ expect(tsrx_language.extensions).toContain('.tsrx');
873
+ expect(tsrx_language.parsers).toContain('tsrx');
892
874
  });
893
875
 
894
876
  it('should format a simple component', async () => {
@@ -966,23 +948,12 @@ const items=[1,2,3];
966
948
  expect(result).toBeWithNewline(expected);
967
949
  });
968
950
 
969
- it('should format a function with a dynamic function using props member access', async () => {
970
- const expected = `function Card(props) {
971
- <div class="card">
972
- <@props.children />
973
- </div>
974
- }`;
975
-
976
- const result = await format(expected, { singleQuote: true });
977
- expect(result).toBeWithNewline(expected);
978
- });
979
-
980
951
  it('should respect print width when using ternary expressions', async () => {
981
952
  const input = `function printMemberExpressionSimple(node, options, computed = false) {
982
953
  if (node.type === 'MemberExpression') {
983
954
  const prop = node.computed
984
- ? (node.property.tracked ? '.@[' : '[') + printMemberExpressionSimple(node.property, options, node.computed) + ']'
985
- : (node.property.tracked ? '.@' : '.') + printMemberExpressionSimple(node.property, options, node.computed);
955
+ ? (node.optional ? '?.[' : '[') + printMemberExpressionSimple(node.property, options, node.computed) + ']'
956
+ : (node.optional ? '?.' : '.') + printMemberExpressionSimple(node.property, options, node.computed);
986
957
  }
987
958
  }`;
988
959
 
@@ -993,14 +964,14 @@ const items=[1,2,3];
993
964
  ) {
994
965
  if (node.type === 'MemberExpression') {
995
966
  const prop = node.computed
996
- ? (node.property.tracked ? '.@[' : '[') +
967
+ ? (node.optional ? '?.[' : '[') +
997
968
  printMemberExpressionSimple(
998
969
  node.property,
999
970
  options,
1000
971
  node.computed,
1001
972
  ) +
1002
973
  ']'
1003
- : (node.property.tracked ? '.@' : '.') +
974
+ : (node.optional ? '?.' : '.') +
1004
975
  printMemberExpressionSimple(
1005
976
  node.property,
1006
977
  options,
@@ -1398,11 +1369,11 @@ export function Test({ a, b }: Props) {}`;
1398
1369
 
1399
1370
  it('should not force attribute-less elements to break with singleAttributePerLine', async () => {
1400
1371
  const input = `function One() @{
1401
- <div>"Hello"</div>
1372
+ <div>Hello</div>
1402
1373
  }`;
1403
1374
 
1404
1375
  const expected = `function One() @{
1405
- <div>"Hello"</div>
1376
+ <div>Hello</div>
1406
1377
  }`;
1407
1378
 
1408
1379
  const result = await format(input, {
@@ -1462,18 +1433,6 @@ export function Test({ a, b }: Props) {}`;
1462
1433
  expect(result).toBeWithNewline(expected);
1463
1434
  });
1464
1435
 
1465
- it('should not strip @ from dynamic @tag', async () => {
1466
- const expected = `export function Four() {
1467
- let tag = track('div');
1468
-
1469
- <@tag {href} {...props}>
1470
- <@children />
1471
- </@tag>
1472
- }`;
1473
- const result = await format(expected, { singleQuote: true, printWidth: 100 });
1474
- expect(result).toBeWithNewline(expected);
1475
- });
1476
-
1477
1436
  it('should not include a comma after the last rest parameter', async () => {
1478
1437
  const expected = `function Foo({
1479
1438
  lorem,
@@ -1490,15 +1449,6 @@ export function Test({ a, b }: Props) {}`;
1490
1449
  expect(result).toBeWithNewline(expected);
1491
1450
  });
1492
1451
 
1493
- it('should not strip @ from dynamic self-closing components', async () => {
1494
- const expected = `function App() {
1495
- <@ripple_object.tracked_basic />
1496
- }`;
1497
-
1498
- const result = await format(expected, { singleQuote: true, printWidth: 100 });
1499
- expect(result).toBeWithNewline(expected);
1500
- });
1501
-
1502
1452
  it('keeps a new line between comments above and code if one is present', async () => {
1503
1453
  const expected = `// comment
1504
1454
 
@@ -5604,7 +5554,7 @@ render(App);`;
5604
5554
  expect(result).toBeWithNewline(expected);
5605
5555
  });
5606
5556
 
5607
- it('should preserve the order of try / pending / catch block', async () => {
5557
+ it('should preserve the order of try / pending / catch blocks', async () => {
5608
5558
  const expected = `function Test() {
5609
5559
  let items: RippleArray<string> | null = null;
5610
5560
  let error: string | null = null;
@@ -5622,8 +5572,6 @@ render(App);`;
5622
5572
  <div>{'Loading...'}</div>
5623
5573
  } @catch (e) {
5624
5574
  error = (e as Error).message;
5625
- } finally {
5626
- <div>finally block</div>
5627
5575
  };
5628
5576
  }`;
5629
5577