@tsrx/prettier-plugin 0.3.64 → 0.3.65
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 +2 -2
- package/src/index.js +42 -18
- package/src/index.test.js +107 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsrx/prettier-plugin",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.65",
|
|
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.
|
|
30
|
+
"@tsrx/core": "0.1.13"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"src/"
|
package/src/index.js
CHANGED
|
@@ -1506,6 +1506,15 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1506
1506
|
break;
|
|
1507
1507
|
}
|
|
1508
1508
|
|
|
1509
|
+
case 'TSSatisfiesExpression': {
|
|
1510
|
+
nodeContent = [
|
|
1511
|
+
path.call(print, 'expression'),
|
|
1512
|
+
' satisfies ',
|
|
1513
|
+
path.call(print, 'typeAnnotation'),
|
|
1514
|
+
];
|
|
1515
|
+
break;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1509
1518
|
case 'TSNonNullExpression': {
|
|
1510
1519
|
nodeContent = [path.call(print, 'expression'), '!'];
|
|
1511
1520
|
break;
|
|
@@ -1930,21 +1939,21 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1930
1939
|
(node.left.type === 'CallExpression' ||
|
|
1931
1940
|
node.left.type === 'ChainExpression' ||
|
|
1932
1941
|
node.left.type === 'NewExpression');
|
|
1933
|
-
|
|
1934
|
-
if (args?.isConditionalTest) {
|
|
1942
|
+
if (shouldKeepNullishFallbackInline) {
|
|
1935
1943
|
logicalResult = group([
|
|
1936
|
-
path.call(
|
|
1944
|
+
path.call(print, 'left'),
|
|
1937
1945
|
' ',
|
|
1938
1946
|
node.operator,
|
|
1939
|
-
|
|
1947
|
+
' ',
|
|
1948
|
+
path.call(print, 'right'),
|
|
1940
1949
|
]);
|
|
1941
|
-
} else if (
|
|
1950
|
+
} else if (args?.isConditionalTest) {
|
|
1951
|
+
// Don't add indent if we're in a conditional test context
|
|
1942
1952
|
logicalResult = group([
|
|
1943
|
-
path.call(print, 'left'),
|
|
1953
|
+
path.call((childPath) => print(childPath, { isConditionalTest: true }), 'left'),
|
|
1944
1954
|
' ',
|
|
1945
1955
|
node.operator,
|
|
1946
|
-
|
|
1947
|
-
path.call(print, 'right'),
|
|
1956
|
+
[line, path.call((childPath) => print(childPath, { isConditionalTest: true }), 'right')],
|
|
1948
1957
|
]);
|
|
1949
1958
|
} else {
|
|
1950
1959
|
logicalResult = group([
|
|
@@ -2839,20 +2848,15 @@ function printArrowFunction(node, path, options, print, args) {
|
|
|
2839
2848
|
// to avoid ambiguity with block statements or to clarify intent
|
|
2840
2849
|
const bodyDoc = path.call(print, 'body');
|
|
2841
2850
|
const groupId = Symbol('arrow');
|
|
2842
|
-
const shouldBreakBody = shouldBreakArrowExpressionBody(node.body, options);
|
|
2851
|
+
const shouldBreakBody = shouldBreakArrowExpressionBody(node.body, options, args);
|
|
2843
2852
|
/** @type {Doc | Doc[]} */
|
|
2844
2853
|
let bodyContent;
|
|
2845
2854
|
if (
|
|
2846
2855
|
node.body.type === 'ObjectExpression' ||
|
|
2847
2856
|
node.body.type === 'AssignmentExpression' ||
|
|
2848
|
-
node.body.type === 'SequenceExpression'
|
|
2849
|
-
(args?.isInAttribute && isTemplateExpression(node.body))
|
|
2857
|
+
node.body.type === 'SequenceExpression'
|
|
2850
2858
|
) {
|
|
2851
|
-
|
|
2852
|
-
bodyContent = ['(', indent([hardline, bodyDoc]), hardline, ')'];
|
|
2853
|
-
} else {
|
|
2854
|
-
bodyContent = ['(', bodyDoc, ')'];
|
|
2855
|
-
}
|
|
2859
|
+
bodyContent = ['(', bodyDoc, ')'];
|
|
2856
2860
|
} else {
|
|
2857
2861
|
bodyContent = bodyDoc;
|
|
2858
2862
|
}
|
|
@@ -2885,6 +2889,15 @@ function isTemplateExpression(node) {
|
|
|
2885
2889
|
);
|
|
2886
2890
|
}
|
|
2887
2891
|
|
|
2892
|
+
/**
|
|
2893
|
+
* Check whether a braced attribute expression should close on its own line.
|
|
2894
|
+
* @param {AST.Node} node - The expression inside the attribute braces
|
|
2895
|
+
* @returns {boolean}
|
|
2896
|
+
*/
|
|
2897
|
+
function shouldBreakAttributeExpressionClosingBrace(node) {
|
|
2898
|
+
return node.type === 'ArrowFunctionExpression' && node.body && isTemplateExpression(node.body);
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2888
2901
|
/**
|
|
2889
2902
|
* Print an export default declaration
|
|
2890
2903
|
* @param {AST.ExportDefaultDeclaration} node - The export default node
|
|
@@ -3095,9 +3108,13 @@ function sourceSpanExceedsPrintWidth(node, options) {
|
|
|
3095
3108
|
* Check if an arrow expression body should break immediately after `=>`.
|
|
3096
3109
|
* @param {AST.Expression} node - The arrow body expression
|
|
3097
3110
|
* @param {RippleFormatOptions} options - Prettier options
|
|
3111
|
+
* @param {PrintArgs} [args] - Additional context arguments
|
|
3098
3112
|
* @returns {boolean}
|
|
3099
3113
|
*/
|
|
3100
|
-
function shouldBreakArrowExpressionBody(node, options) {
|
|
3114
|
+
function shouldBreakArrowExpressionBody(node, options, args) {
|
|
3115
|
+
if (args?.isInAttribute && isTemplateExpression(node)) {
|
|
3116
|
+
return true;
|
|
3117
|
+
}
|
|
3101
3118
|
return (
|
|
3102
3119
|
(node.type === 'BinaryExpression' || node.type === 'LogicalExpression') &&
|
|
3103
3120
|
sourceSpanExceedsPrintWidth(/** @type {AST.NodeWithLocation} */ (node), options)
|
|
@@ -5778,7 +5795,7 @@ function printTsx(node, path, options, print) {
|
|
|
5778
5795
|
return [tagName, closingTagName];
|
|
5779
5796
|
}
|
|
5780
5797
|
|
|
5781
|
-
if (printedChildren.length > 1) {
|
|
5798
|
+
if (!is_fragment || printedChildren.length > 1) {
|
|
5782
5799
|
return group([
|
|
5783
5800
|
tagName,
|
|
5784
5801
|
indent([hardline, join(hardline, printedChildren)]),
|
|
@@ -6192,11 +6209,15 @@ function printJSXAttribute(attr, path, options, print) {
|
|
|
6192
6209
|
}
|
|
6193
6210
|
|
|
6194
6211
|
if (attr.value.type === 'JSXExpressionContainer') {
|
|
6212
|
+
const expression = attr.value.expression;
|
|
6195
6213
|
const exprDoc = path.call(
|
|
6196
6214
|
(valuePath) => print(valuePath, { isInAttribute: true }),
|
|
6197
6215
|
'value',
|
|
6198
6216
|
'expression',
|
|
6199
6217
|
);
|
|
6218
|
+
if (shouldBreakAttributeExpressionClosingBrace(expression)) {
|
|
6219
|
+
return [name, '={', exprDoc, hardline, '}'];
|
|
6220
|
+
}
|
|
6200
6221
|
return [name, '={', exprDoc, '}'];
|
|
6201
6222
|
}
|
|
6202
6223
|
|
|
@@ -6774,6 +6795,9 @@ function printAttribute(node, path, options, print) {
|
|
|
6774
6795
|
parts.push('={');
|
|
6775
6796
|
// Pass inline context for attribute values (keep objects compact)
|
|
6776
6797
|
parts.push(path.call((attrPath) => print(attrPath, { isInAttribute: true }), 'value'));
|
|
6798
|
+
if (shouldBreakAttributeExpressionClosingBrace(node.value)) {
|
|
6799
|
+
parts.push(hardline);
|
|
6800
|
+
}
|
|
6777
6801
|
parts.push('}');
|
|
6778
6802
|
}
|
|
6779
6803
|
}
|
package/src/index.test.js
CHANGED
|
@@ -200,6 +200,58 @@ describe('prettier-plugin', () => {
|
|
|
200
200
|
expect(result).toBeWithNewline(expected);
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
+
it('should format explicit tsx arrow returns like tsrx blocks', async () => {
|
|
204
|
+
const input = `component Test(props) {
|
|
205
|
+
const func = (item) => <tsx><ItemView item={item} onSelect={props.onSelect} /></tsx>;
|
|
206
|
+
|
|
207
|
+
<List
|
|
208
|
+
items={props.items}
|
|
209
|
+
renderItem={(item) => <tsx><ItemView item={item} onSelect={props.onSelect} /></tsx>}
|
|
210
|
+
/>
|
|
211
|
+
}`;
|
|
212
|
+
const expected = `component Test(props) {
|
|
213
|
+
const func = (item) => <tsx>
|
|
214
|
+
<ItemView item={item} onSelect={props.onSelect} />
|
|
215
|
+
</tsx>;
|
|
216
|
+
|
|
217
|
+
<List
|
|
218
|
+
items={props.items}
|
|
219
|
+
renderItem={(item) =>
|
|
220
|
+
<tsx>
|
|
221
|
+
<ItemView item={item} onSelect={props.onSelect} />
|
|
222
|
+
</tsx>
|
|
223
|
+
}
|
|
224
|
+
/>
|
|
225
|
+
}`;
|
|
226
|
+
const result = await format(input);
|
|
227
|
+
expect(result).toBeWithNewline(expected);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should format template arrow returns in tsx attributes like ripple attributes', async () => {
|
|
231
|
+
const input = `component Test(props) {
|
|
232
|
+
const view = <tsx>
|
|
233
|
+
<List
|
|
234
|
+
items={props.items}
|
|
235
|
+
renderItem={(item) => <tsx><ItemView item={item} onSelect={props.onSelect} /></tsx>}
|
|
236
|
+
/>
|
|
237
|
+
</tsx>;
|
|
238
|
+
}`;
|
|
239
|
+
const expected = `component Test(props) {
|
|
240
|
+
const view = <tsx>
|
|
241
|
+
<List
|
|
242
|
+
items={props.items}
|
|
243
|
+
renderItem={(item) =>
|
|
244
|
+
<tsx>
|
|
245
|
+
<ItemView item={item} onSelect={props.onSelect} />
|
|
246
|
+
</tsx>
|
|
247
|
+
}
|
|
248
|
+
/>
|
|
249
|
+
</tsx>;
|
|
250
|
+
}`;
|
|
251
|
+
const result = await format(input);
|
|
252
|
+
expect(result).toBeWithNewline(expected);
|
|
253
|
+
});
|
|
254
|
+
|
|
203
255
|
it('should preserve comments before expressions after nested tsx and tsrx blocks', async () => {
|
|
204
256
|
const input = `component App() {
|
|
205
257
|
const content = <tsx>
|
|
@@ -255,7 +307,7 @@ describe('prettier-plugin', () => {
|
|
|
255
307
|
}`,
|
|
256
308
|
expected: `component Test() {
|
|
257
309
|
<A
|
|
258
|
-
fallback={(error) =>
|
|
310
|
+
fallback={(error) =>
|
|
259
311
|
<>
|
|
260
312
|
<B
|
|
261
313
|
id="xyz"
|
|
@@ -265,7 +317,7 @@ describe('prettier-plugin', () => {
|
|
|
265
317
|
otherProp={2}
|
|
266
318
|
/>
|
|
267
319
|
</>
|
|
268
|
-
|
|
320
|
+
}
|
|
269
321
|
/>
|
|
270
322
|
}`,
|
|
271
323
|
},
|
|
@@ -279,7 +331,7 @@ describe('prettier-plugin', () => {
|
|
|
279
331
|
}`,
|
|
280
332
|
expected: `component Test() {
|
|
281
333
|
<A
|
|
282
|
-
fallback={(error) =>
|
|
334
|
+
fallback={(error) =>
|
|
283
335
|
<tsx>
|
|
284
336
|
<B
|
|
285
337
|
id="xyz"
|
|
@@ -289,7 +341,7 @@ describe('prettier-plugin', () => {
|
|
|
289
341
|
otherProp={2}
|
|
290
342
|
/>
|
|
291
343
|
</tsx>
|
|
292
|
-
|
|
344
|
+
}
|
|
293
345
|
/>
|
|
294
346
|
}`,
|
|
295
347
|
},
|
|
@@ -303,7 +355,7 @@ describe('prettier-plugin', () => {
|
|
|
303
355
|
}`,
|
|
304
356
|
expected: `component Test() {
|
|
305
357
|
<A
|
|
306
|
-
fallback={(error) =>
|
|
358
|
+
fallback={(error) =>
|
|
307
359
|
<tsrx>
|
|
308
360
|
<B
|
|
309
361
|
id="xyz"
|
|
@@ -313,7 +365,7 @@ describe('prettier-plugin', () => {
|
|
|
313
365
|
otherProp={2}
|
|
314
366
|
/>
|
|
315
367
|
</tsrx>
|
|
316
|
-
|
|
368
|
+
}
|
|
317
369
|
/>
|
|
318
370
|
}`,
|
|
319
371
|
},
|
|
@@ -327,7 +379,7 @@ describe('prettier-plugin', () => {
|
|
|
327
379
|
}`,
|
|
328
380
|
expected: `component Test() {
|
|
329
381
|
<A
|
|
330
|
-
fallback={(error) =>
|
|
382
|
+
fallback={(error) =>
|
|
331
383
|
<tsx:react>
|
|
332
384
|
<B
|
|
333
385
|
id="xyz"
|
|
@@ -337,7 +389,7 @@ describe('prettier-plugin', () => {
|
|
|
337
389
|
otherProp={2}
|
|
338
390
|
/>
|
|
339
391
|
</tsx:react>
|
|
340
|
-
|
|
392
|
+
}
|
|
341
393
|
/>
|
|
342
394
|
}`,
|
|
343
395
|
},
|
|
@@ -1015,7 +1067,9 @@ import { Something, type Props, track } from 'ripple';`;
|
|
|
1015
1067
|
const foo = <tsx><Bar {...props} /></tsx>;`;
|
|
1016
1068
|
|
|
1017
1069
|
const expected = `const props = {};
|
|
1018
|
-
const foo = <tsx
|
|
1070
|
+
const foo = <tsx>
|
|
1071
|
+
<Bar {...props} />
|
|
1072
|
+
</tsx>;`;
|
|
1019
1073
|
|
|
1020
1074
|
const result = await format(input, { singleQuote: true });
|
|
1021
1075
|
expect(result).toBeWithNewline(expected);
|
|
@@ -1393,6 +1447,18 @@ import { effect, track } from 'ripple';`;
|
|
|
1393
1447
|
expect(result).toBeWithNewline(expected);
|
|
1394
1448
|
});
|
|
1395
1449
|
|
|
1450
|
+
it('keeps nullish fallback inline in a conditional test', async () => {
|
|
1451
|
+
const input = `const test = menuRef.current?.querySelector<HTMLElement>('[role="menuitem"]:not([aria-disabled="true"])') ?? null ? a : b;`;
|
|
1452
|
+
const expected = `const test =
|
|
1453
|
+
menuRef.current?.querySelector<HTMLElement>(
|
|
1454
|
+
'[role="menuitem"]:not([aria-disabled="true"])',
|
|
1455
|
+
) ?? null
|
|
1456
|
+
? a
|
|
1457
|
+
: b;`;
|
|
1458
|
+
const result = await format(input, { singleQuote: true });
|
|
1459
|
+
expect(result).toBeWithNewline(expected);
|
|
1460
|
+
});
|
|
1461
|
+
|
|
1396
1462
|
it('does not add spaces around inlined array elements in destructured arguments', async () => {
|
|
1397
1463
|
const expected = `for (const [key, value] of Object.entries(attributes).filter(([_key, value]) => value !== '')) {
|
|
1398
1464
|
}
|
|
@@ -2267,7 +2333,9 @@ files = [...(files ?? []), ...dt.files];`;
|
|
|
2267
2333
|
|
|
2268
2334
|
const expected = `class Foo {
|
|
2269
2335
|
bar() {
|
|
2270
|
-
return <tsx>
|
|
2336
|
+
return <tsx>
|
|
2337
|
+
{'Hello'}
|
|
2338
|
+
</tsx>;
|
|
2271
2339
|
}
|
|
2272
2340
|
}`;
|
|
2273
2341
|
|
|
@@ -2626,6 +2694,35 @@ component Child({ something }) {
|
|
|
2626
2694
|
expect(result).toBeWithNewline(expected);
|
|
2627
2695
|
});
|
|
2628
2696
|
|
|
2697
|
+
it('prints satisfies expressions in switch default cases', async () => {
|
|
2698
|
+
const input = `export component Test(props: { status: "ok" | "error" }) {
|
|
2699
|
+
switch (props.status) {
|
|
2700
|
+
case "ok":
|
|
2701
|
+
<div>"ok"</div>
|
|
2702
|
+
return
|
|
2703
|
+
case "error":
|
|
2704
|
+
<div>"error"</div>
|
|
2705
|
+
return
|
|
2706
|
+
default:
|
|
2707
|
+
props.status satisfies never
|
|
2708
|
+
}
|
|
2709
|
+
}`;
|
|
2710
|
+
const expected = `export component Test(props: { status: "ok" | "error" }) {
|
|
2711
|
+
switch (props.status) {
|
|
2712
|
+
case "ok":
|
|
2713
|
+
<div>"ok"</div>
|
|
2714
|
+
return;
|
|
2715
|
+
case "error":
|
|
2716
|
+
<div>"error"</div>
|
|
2717
|
+
return;
|
|
2718
|
+
default:
|
|
2719
|
+
props.status satisfies never;
|
|
2720
|
+
}
|
|
2721
|
+
}`;
|
|
2722
|
+
const result = await format(input);
|
|
2723
|
+
expect(result).toBeWithNewline(expected);
|
|
2724
|
+
});
|
|
2725
|
+
|
|
2629
2726
|
it('prints function with a rest parameter correctly', async () => {
|
|
2630
2727
|
const expected = `function TestRest(...args: string[]) {
|
|
2631
2728
|
console.log(args);
|