@tsrx/prettier-plugin 0.3.62 → 0.3.63
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 +69 -2
- package/src/index.test.js +65 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsrx/prettier-plugin",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.63",
|
|
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.12"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"src/"
|
package/src/index.js
CHANGED
|
@@ -360,6 +360,49 @@ function binaryExpressionNeedsParens(node, parent) {
|
|
|
360
360
|
return false;
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Check if a parenthesized AssignmentExpression needs its parentheses preserved.
|
|
365
|
+
* @param {AST.AssignmentExpression} node - The expression node
|
|
366
|
+
* @param {AST.Node | null} parent - The parent node
|
|
367
|
+
* @returns {boolean} - True if parentheses are needed
|
|
368
|
+
*/
|
|
369
|
+
function assignmentExpressionNeedsParens(node, parent) {
|
|
370
|
+
if (!node.metadata?.parenthesized || !parent) {
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (parent.type === 'BinaryExpression' || parent.type === 'LogicalExpression') {
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (parent.type === 'ConditionalExpression') {
|
|
379
|
+
return parent.test === node;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (parent.type === 'AwaitExpression' || parent.type === 'YieldExpression') {
|
|
383
|
+
return parent.argument === node;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (parent.type === 'CallExpression' || parent.type === 'NewExpression') {
|
|
387
|
+
return parent.callee === node;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (parent.type === 'TaggedTemplateExpression') {
|
|
391
|
+
return parent.tag === node;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (
|
|
395
|
+
parent.type === 'TSAsExpression' ||
|
|
396
|
+
parent.type === 'TSSatisfiesExpression' ||
|
|
397
|
+
parent.type === 'TSNonNullExpression' ||
|
|
398
|
+
parent.type === 'TSInstantiationExpression'
|
|
399
|
+
) {
|
|
400
|
+
return parent.expression === node;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
|
|
363
406
|
/**
|
|
364
407
|
* Create a function that skips specified characters in text
|
|
365
408
|
* @param {string | RegExp} characters - Characters to skip
|
|
@@ -718,11 +761,13 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
718
761
|
const isInlineContext = args && args.isInlineContext;
|
|
719
762
|
const suppressLeadingComments = args && args.suppressLeadingComments;
|
|
720
763
|
const suppressExpressionLeadingComments = args && args.suppressExpressionLeadingComments;
|
|
764
|
+
const parentNode = /** @type {AST.Node | null} */ (path.getParentNode());
|
|
721
765
|
|
|
722
766
|
// For TSRXExpression, Text, and Html nodes, don't add leading comments here - they should be handled
|
|
723
|
-
// as separate children within
|
|
767
|
+
// as separate children within elements, not as part of the expression.
|
|
724
768
|
const shouldSkipLeadingComments =
|
|
725
|
-
|
|
769
|
+
parentNode?.type === 'Element' &&
|
|
770
|
+
(node.type === 'TSRXExpression' || node.type === 'Text' || node.type === 'Html');
|
|
726
771
|
|
|
727
772
|
// Handle leading comments
|
|
728
773
|
if (node.leadingComments && !shouldSkipLeadingComments && !suppressLeadingComments) {
|
|
@@ -1335,6 +1380,10 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1335
1380
|
group(indent(line), { id: groupId }),
|
|
1336
1381
|
indentIfBreak(rightSide, { groupId }),
|
|
1337
1382
|
]);
|
|
1383
|
+
const parent = path.getParentNode();
|
|
1384
|
+
if (assignmentExpressionNeedsParens(node, parent)) {
|
|
1385
|
+
nodeContent = ['(', nodeContent, ')'];
|
|
1386
|
+
}
|
|
1338
1387
|
break;
|
|
1339
1388
|
}
|
|
1340
1389
|
|
|
@@ -5930,6 +5979,24 @@ function printJSXElement(node, path, options, print) {
|
|
|
5930
5979
|
// Accumulate text content, preserving spaces between words
|
|
5931
5980
|
const trimmed = child.value.trim();
|
|
5932
5981
|
if (trimmed) {
|
|
5982
|
+
const nextChild = node.children[i + 1];
|
|
5983
|
+
const afterNextChild = node.children[i + 2];
|
|
5984
|
+
const nextText = afterNextChild?.type === 'JSXText' ? afterNextChild.value.trim() : '';
|
|
5985
|
+
if (
|
|
5986
|
+
tagName === 'tsrx' &&
|
|
5987
|
+
trimmed.endsWith('=') &&
|
|
5988
|
+
nextChild?.type === 'JSXElement' &&
|
|
5989
|
+
nextText === ';'
|
|
5990
|
+
) {
|
|
5991
|
+
if (currentText) {
|
|
5992
|
+
childrenDocs.push(currentText);
|
|
5993
|
+
currentText = '';
|
|
5994
|
+
}
|
|
5995
|
+
childrenDocs.push([trimmed, ' ', path.call(print, 'children', i + 1), ';']);
|
|
5996
|
+
i += 2;
|
|
5997
|
+
continue;
|
|
5998
|
+
}
|
|
5999
|
+
|
|
5933
6000
|
if (currentText) {
|
|
5934
6001
|
currentText += ' ' + trimmed;
|
|
5935
6002
|
} else {
|
package/src/index.test.js
CHANGED
|
@@ -200,6 +200,49 @@ describe('prettier-plugin', () => {
|
|
|
200
200
|
expect(result).toBeWithNewline(expected);
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
+
it('should preserve comments before expressions after nested tsx and tsrx blocks', async () => {
|
|
204
|
+
const input = `component App() {
|
|
205
|
+
const content = <tsx>
|
|
206
|
+
{<tsrx>
|
|
207
|
+
const nested =
|
|
208
|
+
<tsx>
|
|
209
|
+
<span class="nested-tsx">
|
|
210
|
+
{'inside nested tsx'}
|
|
211
|
+
</span>
|
|
212
|
+
</tsx>
|
|
213
|
+
;
|
|
214
|
+
<div class="native">{nested}</div>
|
|
215
|
+
</tsrx>}
|
|
216
|
+
</tsx>;
|
|
217
|
+
|
|
218
|
+
// const content = <tsrx>
|
|
219
|
+
// <div>{hey()}</div>
|
|
220
|
+
// </tsrx>;
|
|
221
|
+
|
|
222
|
+
{content}
|
|
223
|
+
}`;
|
|
224
|
+
const expected = `component App() {
|
|
225
|
+
const content = <tsx>
|
|
226
|
+
{<tsrx>
|
|
227
|
+
const nested = <tsx>
|
|
228
|
+
<span class="nested-tsx">
|
|
229
|
+
{'inside nested tsx'}
|
|
230
|
+
</span>
|
|
231
|
+
</tsx>;
|
|
232
|
+
<div class="native">{nested}</div>
|
|
233
|
+
</tsrx>}
|
|
234
|
+
</tsx>;
|
|
235
|
+
|
|
236
|
+
// const content = <tsrx>
|
|
237
|
+
// <div>{hey()}</div>
|
|
238
|
+
// </tsrx>;
|
|
239
|
+
|
|
240
|
+
{content}
|
|
241
|
+
}`;
|
|
242
|
+
const result = await format(input, { singleQuote: true });
|
|
243
|
+
expect(result).toBeWithNewline(expected);
|
|
244
|
+
});
|
|
245
|
+
|
|
203
246
|
it('should break nested TSX element attributes inside expression props', async () => {
|
|
204
247
|
const cases = [
|
|
205
248
|
{
|
|
@@ -762,6 +805,28 @@ function test() {
|
|
|
762
805
|
expect(result).toBeWithNewline(expected);
|
|
763
806
|
});
|
|
764
807
|
|
|
808
|
+
it('should preserve required parentheses around assignment expressions', async () => {
|
|
809
|
+
const input = `const openSignal = useRef<Signal<boolean> | null>(null)
|
|
810
|
+
const open = props.open ?? (openSignal.current ??= signal(false))
|
|
811
|
+
const sum = a + (b = c)
|
|
812
|
+
const condition = (a = b) ? c : d
|
|
813
|
+
const called = (factory = getFactory())()
|
|
814
|
+
async function load() {
|
|
815
|
+
await (promise = getPromise())
|
|
816
|
+
}`;
|
|
817
|
+
const expected = `const openSignal = useRef<Signal<boolean> | null>(null);
|
|
818
|
+
const open = props.open ?? (openSignal.current ??= signal(false));
|
|
819
|
+
const sum = a + (b = c);
|
|
820
|
+
const condition = (a = b) ? c : d;
|
|
821
|
+
const called = (factory = getFactory())();
|
|
822
|
+
async function load() {
|
|
823
|
+
await (promise = getPromise());
|
|
824
|
+
}`;
|
|
825
|
+
|
|
826
|
+
const result = await format(input, { singleQuote: true });
|
|
827
|
+
expect(result).toBeWithNewline(expected);
|
|
828
|
+
});
|
|
829
|
+
|
|
765
830
|
it('should not change formatting for function object properties and properties in square brackets', async () => {
|
|
766
831
|
const expected = `export component App() {
|
|
767
832
|
const SYMBOL_PROP = Symbol();
|