@tsrx/prettier-plugin 0.3.40 → 0.3.42

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.40",
3
+ "version": "0.3.42",
4
4
  "description": "Ripple plugin for Prettier",
5
5
  "type": "module",
6
6
  "module": "src/index.js",
@@ -26,11 +26,11 @@
26
26
  "devDependencies": {
27
27
  "@types/node": "^24.3.0",
28
28
  "prettier": "^3.8.3",
29
- "ripple": "0.3.40"
29
+ "ripple": "0.3.42"
30
30
  },
31
31
  "dependencies": {
32
- "@tsrx/core": "0.0.20",
33
- "@tsrx/ripple": "0.0.22"
32
+ "@tsrx/core": "0.0.22",
33
+ "@tsrx/ripple": "0.0.24"
34
34
  },
35
35
  "files": [
36
36
  "src/"
package/src/index.js CHANGED
@@ -5748,6 +5748,12 @@ function printJSXElement(node, path, options, print) {
5748
5748
  const hasAttributes = openingElement.attributes && openingElement.attributes.length > 0;
5749
5749
  const hasChildren = node.children && node.children.length > 0;
5750
5750
 
5751
+ /** @type {Doc} */
5752
+ let typeArgsDoc = '';
5753
+ if (openingElement.typeArguments) {
5754
+ typeArgsDoc = path.call(print, 'openingElement', 'typeArguments');
5755
+ }
5756
+
5751
5757
  // Format attributes
5752
5758
  /** @type {Doc} */
5753
5759
  let attributesDoc = '';
@@ -5778,11 +5784,11 @@ function printJSXElement(node, path, options, print) {
5778
5784
  }
5779
5785
 
5780
5786
  if (isSelfClosing) {
5781
- return ['<', tagName, attributesDoc, ' />'];
5787
+ return ['<', tagName, typeArgsDoc, attributesDoc, ' />'];
5782
5788
  }
5783
5789
 
5784
5790
  if (!hasChildren) {
5785
- return ['<', tagName, attributesDoc, '></', tagName, '>'];
5791
+ return ['<', tagName, typeArgsDoc, attributesDoc, '></', tagName, '>'];
5786
5792
  }
5787
5793
 
5788
5794
  // Format children - filter out empty text nodes and merge adjacent text nodes
@@ -5826,7 +5832,7 @@ function printJSXElement(node, path, options, print) {
5826
5832
 
5827
5833
  // Check if content can be inlined (single text node or single expression)
5828
5834
  if (childrenDocs.length === 1 && typeof childrenDocs[0] === 'string') {
5829
- return ['<', tagName, attributesDoc, '>', childrenDocs[0], '</', tagName, '>'];
5835
+ return ['<', tagName, typeArgsDoc, attributesDoc, '>', childrenDocs[0], '</', tagName, '>'];
5830
5836
  }
5831
5837
 
5832
5838
  // Multiple children or complex children - format with line breaks
@@ -5842,6 +5848,7 @@ function printJSXElement(node, path, options, print) {
5842
5848
  return group([
5843
5849
  '<',
5844
5850
  tagName,
5851
+ typeArgsDoc,
5845
5852
  attributesDoc,
5846
5853
  '>',
5847
5854
  indent([hardline, ...formattedChildren]),
@@ -6019,6 +6026,12 @@ function is_attribute_value_breakable(value, is_nested_in_object = false) {
6019
6026
  function printElement(element, path, options, print) {
6020
6027
  const node = /** @type {AST.Element & AST.NodeWithLocation} */ (element);
6021
6028
  const tagName = printMemberExpressionSimple(node.id, options);
6029
+ const openingElement = /** @type {any} */ (node.openingElement);
6030
+ /** @type {Doc} */
6031
+ let typeArgsDoc = '';
6032
+ if (openingElement?.typeArguments) {
6033
+ typeArgsDoc = path.call(print, 'openingElement', 'typeArguments');
6034
+ }
6022
6035
  const elementLeadingComments = getElementLeadingComments(node);
6023
6036
 
6024
6037
  // `metadata.elementLeadingComments` may include comments that actually appear *inside* the element
@@ -6095,7 +6108,7 @@ function printElement(element, path, options, print) {
6095
6108
  }
6096
6109
 
6097
6110
  if (isSelfClosing && !hasInnerComments && !hasAttributes) {
6098
- const elementDoc = group(['<', tagName, ' />']);
6111
+ const elementDoc = group(['<', tagName, typeArgsDoc, ' />']);
6099
6112
  return metadataCommentParts.length > 0 ? [...metadataCommentParts, elementDoc] : elementDoc;
6100
6113
  }
6101
6114
 
@@ -6146,6 +6159,7 @@ function printElement(element, path, options, print) {
6146
6159
  const openingTag = group([
6147
6160
  '<',
6148
6161
  tagName,
6162
+ typeArgsDoc,
6149
6163
  hasAttributes
6150
6164
  ? indent([
6151
6165
  ...attrDocs,
package/src/index.test.js CHANGED
@@ -3477,6 +3477,46 @@ declare function processData<T>(data: T): Promise<T>;`;
3477
3477
  expect(result).toBeWithNewline(expected);
3478
3478
  });
3479
3479
 
3480
+ it('should preserve generic type arguments on JSX component tags', async () => {
3481
+ const input = `type User = { name: string };
3482
+ component RenderProp<Item>(props: { children: (item: Item) => any }) {}
3483
+ export component App() {
3484
+ <RenderProp<User>>
3485
+ {(item) => item.name}
3486
+ </RenderProp>
3487
+ }`;
3488
+
3489
+ const expected = `type User = { name: string };
3490
+ component RenderProp<Item>(props: { children: (item: Item) => any }) {}
3491
+ export component App() {
3492
+ <RenderProp<User>>
3493
+ {(item) => item.name}
3494
+ </RenderProp>
3495
+ }`;
3496
+
3497
+ const result = await format(input);
3498
+ expect(result).toBeWithNewline(expected);
3499
+ });
3500
+
3501
+ it('should preserve generic type arguments on self-closing JSX component tags', async () => {
3502
+ const input = `component Box<T>({ value }: { value: T }) {
3503
+ <div>{String(value)}</div>
3504
+ }
3505
+ export component App() {
3506
+ <Box<string> value="hi" />
3507
+ }`;
3508
+
3509
+ const expected = `component Box<T>({ value }: { value: T }) {
3510
+ <div>{String(value)}</div>
3511
+ }
3512
+ export component App() {
3513
+ <Box<string> value="hi" />
3514
+ }`;
3515
+
3516
+ const result = await format(input);
3517
+ expect(result).toBeWithNewline(expected);
3518
+ });
3519
+
3480
3520
  it('should preserve multiple generics on method shorthand', async () => {
3481
3521
  const input = `const obj = {
3482
3522
  method<V, T, U>(): { build: () => V; data: T; key: U } {