@ripple-ts/prettier-plugin 0.2.157 → 0.2.159
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 +114 -21
- package/src/index.test.js +102 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ripple-ts/prettier-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.159",
|
|
4
4
|
"description": "Ripple plugin for Prettier",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"prettier": "^3.6.2",
|
|
28
|
-
"ripple": "0.2.
|
|
28
|
+
"ripple": "0.2.159"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {},
|
|
31
31
|
"files": [
|
package/src/index.js
CHANGED
|
@@ -1168,6 +1168,11 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1168
1168
|
break;
|
|
1169
1169
|
}
|
|
1170
1170
|
|
|
1171
|
+
case 'JSXExpressionContainer': {
|
|
1172
|
+
nodeContent = concat(['{', path.call(print, 'expression'), '}']);
|
|
1173
|
+
break;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1171
1176
|
case 'NewExpression':
|
|
1172
1177
|
nodeContent = printNewExpression(node, path, options, print);
|
|
1173
1178
|
break;
|
|
@@ -3641,6 +3646,45 @@ function printProperty(node, path, options, print) {
|
|
|
3641
3646
|
|
|
3642
3647
|
const parts = [];
|
|
3643
3648
|
|
|
3649
|
+
// Handle getter/setter methods
|
|
3650
|
+
if (node.kind === 'get' || node.kind === 'set') {
|
|
3651
|
+
const methodParts = [];
|
|
3652
|
+
const funcValue = node.value;
|
|
3653
|
+
|
|
3654
|
+
// Add get/set keyword
|
|
3655
|
+
methodParts.push(node.kind, ' ');
|
|
3656
|
+
|
|
3657
|
+
// Print key (with computed property brackets if needed)
|
|
3658
|
+
if (node.computed) {
|
|
3659
|
+
methodParts.push('[', path.call(print, 'key'), ']');
|
|
3660
|
+
} else if (node.key.type === 'Literal' && typeof node.key.value === 'string') {
|
|
3661
|
+
const key = node.key.value;
|
|
3662
|
+
const isValidIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key);
|
|
3663
|
+
if (isValidIdentifier) {
|
|
3664
|
+
methodParts.push(key);
|
|
3665
|
+
} else {
|
|
3666
|
+
methodParts.push(formatStringLiteral(key, options));
|
|
3667
|
+
}
|
|
3668
|
+
} else {
|
|
3669
|
+
methodParts.push(path.call(print, 'key'));
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
// Print parameters by calling into the value path
|
|
3673
|
+
const paramsPart = path.call(
|
|
3674
|
+
(valuePath) => printFunctionParameters(valuePath, options, print),
|
|
3675
|
+
'value',
|
|
3676
|
+
);
|
|
3677
|
+
methodParts.push(group(paramsPart));
|
|
3678
|
+
|
|
3679
|
+
// Handle return type annotation
|
|
3680
|
+
if (funcValue.returnType) {
|
|
3681
|
+
methodParts.push(': ', path.call(print, 'value', 'returnType'));
|
|
3682
|
+
}
|
|
3683
|
+
|
|
3684
|
+
methodParts.push(' ', path.call(print, 'value', 'body'));
|
|
3685
|
+
return concat(methodParts);
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3644
3688
|
// Handle method shorthand: increment() {} instead of increment: function() {}
|
|
3645
3689
|
if (node.method && node.value.type === 'FunctionExpression') {
|
|
3646
3690
|
const methodParts = [];
|
|
@@ -4325,27 +4369,57 @@ function printTsxCompat(node, path, options, print) {
|
|
|
4325
4369
|
}
|
|
4326
4370
|
|
|
4327
4371
|
// Print JSXElement children - they remain as JSX
|
|
4328
|
-
// Filter out whitespace-only JSXText nodes
|
|
4372
|
+
// Filter out whitespace-only JSXText nodes and merge adjacent text-like nodes
|
|
4329
4373
|
const finalChildren = [];
|
|
4374
|
+
let accumulatedText = '';
|
|
4330
4375
|
|
|
4331
4376
|
for (let i = 0; i < node.children.length; i++) {
|
|
4332
4377
|
const child = node.children[i];
|
|
4333
4378
|
|
|
4334
|
-
//
|
|
4335
|
-
|
|
4336
|
-
continue;
|
|
4337
|
-
}
|
|
4379
|
+
// Check if this is a text-like node (JSXText or Identifier in JSX context)
|
|
4380
|
+
const isTextLike = child.type === 'JSXText' || child.type === 'Identifier';
|
|
4338
4381
|
|
|
4339
|
-
|
|
4340
|
-
|
|
4382
|
+
if (isTextLike) {
|
|
4383
|
+
// Get the text content
|
|
4384
|
+
let text;
|
|
4385
|
+
if (child.type === 'JSXText') {
|
|
4386
|
+
text = child.value.trim();
|
|
4387
|
+
} else if (child.type === 'Identifier') {
|
|
4388
|
+
text = child.name;
|
|
4389
|
+
}
|
|
4341
4390
|
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4391
|
+
if (text) {
|
|
4392
|
+
if (accumulatedText) {
|
|
4393
|
+
accumulatedText += ' ' + text;
|
|
4394
|
+
} else {
|
|
4395
|
+
accumulatedText = text;
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
} else {
|
|
4399
|
+
// Before adding non-text node, flush accumulated text
|
|
4400
|
+
if (accumulatedText) {
|
|
4401
|
+
if (finalChildren.length > 0) {
|
|
4402
|
+
finalChildren.push(hardline);
|
|
4403
|
+
}
|
|
4404
|
+
finalChildren.push(accumulatedText);
|
|
4405
|
+
accumulatedText = '';
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
if (finalChildren.length > 0) {
|
|
4346
4409
|
finalChildren.push(hardline);
|
|
4347
4410
|
}
|
|
4411
|
+
|
|
4412
|
+
const printedChild = path.call(print, 'children', i);
|
|
4413
|
+
finalChildren.push(printedChild);
|
|
4414
|
+
}
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4417
|
+
// Don't forget any remaining accumulated text
|
|
4418
|
+
if (accumulatedText) {
|
|
4419
|
+
if (finalChildren.length > 0) {
|
|
4420
|
+
finalChildren.push(hardline);
|
|
4348
4421
|
}
|
|
4422
|
+
finalChildren.push(accumulatedText);
|
|
4349
4423
|
}
|
|
4350
4424
|
|
|
4351
4425
|
// Format the TsxCompat element
|
|
@@ -4404,26 +4478,45 @@ function printJSXElement(node, path, options, print) {
|
|
|
4404
4478
|
return concat(['<', tagName, attributesDoc, '></', tagName, '>']);
|
|
4405
4479
|
}
|
|
4406
4480
|
|
|
4407
|
-
// Format children - filter out empty text nodes
|
|
4481
|
+
// Format children - filter out empty text nodes and merge adjacent text nodes
|
|
4408
4482
|
const childrenDocs = [];
|
|
4483
|
+
let currentText = '';
|
|
4484
|
+
|
|
4409
4485
|
for (let i = 0; i < node.children.length; i++) {
|
|
4410
4486
|
const child = node.children[i];
|
|
4411
4487
|
|
|
4412
4488
|
if (child.type === 'JSXText') {
|
|
4413
|
-
//
|
|
4414
|
-
const
|
|
4415
|
-
if (
|
|
4416
|
-
|
|
4489
|
+
// Accumulate text content, preserving spaces between words
|
|
4490
|
+
const trimmed = child.value.trim();
|
|
4491
|
+
if (trimmed) {
|
|
4492
|
+
if (currentText) {
|
|
4493
|
+
currentText += ' ' + trimmed;
|
|
4494
|
+
} else {
|
|
4495
|
+
currentText = trimmed;
|
|
4496
|
+
}
|
|
4417
4497
|
}
|
|
4418
|
-
} else if (child.type === 'JSXExpressionContainer') {
|
|
4419
|
-
// Handle JSX expression containers
|
|
4420
|
-
childrenDocs.push(concat(['{', path.call(print, 'children', i, 'expression'), '}']));
|
|
4421
4498
|
} else {
|
|
4422
|
-
//
|
|
4423
|
-
|
|
4499
|
+
// If we have accumulated text, push it before the non-text node
|
|
4500
|
+
if (currentText) {
|
|
4501
|
+
childrenDocs.push(currentText);
|
|
4502
|
+
currentText = '';
|
|
4503
|
+
}
|
|
4504
|
+
|
|
4505
|
+
if (child.type === 'JSXExpressionContainer') {
|
|
4506
|
+
// Handle JSX expression containers
|
|
4507
|
+
childrenDocs.push(concat(['{', path.call(print, 'children', i, 'expression'), '}']));
|
|
4508
|
+
} else {
|
|
4509
|
+
// Handle nested JSX elements
|
|
4510
|
+
childrenDocs.push(path.call(print, 'children', i));
|
|
4511
|
+
}
|
|
4424
4512
|
}
|
|
4425
4513
|
}
|
|
4426
4514
|
|
|
4515
|
+
// Don't forget any remaining text
|
|
4516
|
+
if (currentText) {
|
|
4517
|
+
childrenDocs.push(currentText);
|
|
4518
|
+
}
|
|
4519
|
+
|
|
4427
4520
|
// Check if content can be inlined (single text node or single expression)
|
|
4428
4521
|
if (childrenDocs.length === 1 && typeof childrenDocs[0] === 'string') {
|
|
4429
4522
|
return concat(['<', tagName, attributesDoc, '>', childrenDocs[0], '</', tagName, '>']);
|
package/src/index.test.js
CHANGED
|
@@ -3812,6 +3812,108 @@ component Polygon() {
|
|
|
3812
3812
|
const result = await format(input, { singleQuote: true });
|
|
3813
3813
|
expect(result).toBeWithNewline(expected);
|
|
3814
3814
|
});
|
|
3815
|
+
|
|
3816
|
+
it('should format JSXExpressionContainer with function calls', async () => {
|
|
3817
|
+
const input = `function foo(){return 123}component App(){<div><tsx:react>{foo()}</tsx:react></div>}`;
|
|
3818
|
+
|
|
3819
|
+
const expected = `function foo() {
|
|
3820
|
+
return 123;
|
|
3821
|
+
}
|
|
3822
|
+
component App() {
|
|
3823
|
+
<div>
|
|
3824
|
+
<tsx:react>
|
|
3825
|
+
{foo()}
|
|
3826
|
+
</tsx:react>
|
|
3827
|
+
</div>
|
|
3828
|
+
}`;
|
|
3829
|
+
|
|
3830
|
+
const result = await format(input);
|
|
3831
|
+
expect(result).toBeWithNewline(expected);
|
|
3832
|
+
});
|
|
3833
|
+
|
|
3834
|
+
it('should format JSXExpressionContainer with function calls', async () => {
|
|
3835
|
+
const input = `function foo(){return 123}component App(){<div><tsx:react>{foo()}<div>Hello world</div>Hello world</tsx:react></div>}`;
|
|
3836
|
+
|
|
3837
|
+
const expected = `function foo() {
|
|
3838
|
+
return 123;
|
|
3839
|
+
}
|
|
3840
|
+
component App() {
|
|
3841
|
+
<div>
|
|
3842
|
+
<tsx:react>
|
|
3843
|
+
{foo()}
|
|
3844
|
+
<div>Hello world</div>
|
|
3845
|
+
Hello world
|
|
3846
|
+
</tsx:react>
|
|
3847
|
+
</div>
|
|
3848
|
+
}`;
|
|
3849
|
+
|
|
3850
|
+
const result = await format(input);
|
|
3851
|
+
expect(result).toBeWithNewline(expected);
|
|
3852
|
+
});
|
|
3853
|
+
|
|
3854
|
+
it('should format JSXExpressionContainer with function calls #2', async () => {
|
|
3855
|
+
const input = `export component App() {
|
|
3856
|
+
<tsx:react>
|
|
3857
|
+
Hello world
|
|
3858
|
+
<DemoContext.Provider value={"Hello from Context!"}>
|
|
3859
|
+
<Child count={@count} />
|
|
3860
|
+
</DemoContext.Provider>
|
|
3861
|
+
</tsx:react>
|
|
3862
|
+
}`;
|
|
3863
|
+
const expected = `export component App() {
|
|
3864
|
+
<tsx:react>
|
|
3865
|
+
Hello world
|
|
3866
|
+
<DemoContext.Provider value={"Hello from Context!"}>
|
|
3867
|
+
<Child count={@count} />
|
|
3868
|
+
</DemoContext.Provider>
|
|
3869
|
+
</tsx:react>
|
|
3870
|
+
}`;
|
|
3871
|
+
|
|
3872
|
+
const result = await format(input);
|
|
3873
|
+
expect(result).toBeWithNewline(expected);
|
|
3874
|
+
});
|
|
3875
|
+
it('should format JSXExpressionContainer with complex expressions', async () => {
|
|
3876
|
+
const input = `component App(){let count=track(0);<tsx:react><div>{count*2+10}</div>{getMessage("test")}</tsx:react>}`;
|
|
3877
|
+
|
|
3878
|
+
const expected = `component App() {
|
|
3879
|
+
let count = track(0);
|
|
3880
|
+
<tsx:react>
|
|
3881
|
+
<div>
|
|
3882
|
+
{count * 2 + 10}
|
|
3883
|
+
</div>
|
|
3884
|
+
{getMessage('test')}
|
|
3885
|
+
</tsx:react>
|
|
3886
|
+
}`;
|
|
3887
|
+
|
|
3888
|
+
const result = await format(input, { singleQuote: true });
|
|
3889
|
+
expect(result).toBeWithNewline(expected);
|
|
3890
|
+
});
|
|
3891
|
+
});
|
|
3892
|
+
|
|
3893
|
+
describe('object getters and setters', () => {
|
|
3894
|
+
it('should preserve get and set keywords in object methods', async () => {
|
|
3895
|
+
const input = `const foo = {
|
|
3896
|
+
get bar() {
|
|
3897
|
+
return 0
|
|
3898
|
+
},
|
|
3899
|
+
|
|
3900
|
+
set baz(arg: 0) {
|
|
3901
|
+
//
|
|
3902
|
+
}
|
|
3903
|
+
}`;
|
|
3904
|
+
const expected = `const foo = {
|
|
3905
|
+
get bar() {
|
|
3906
|
+
return 0;
|
|
3907
|
+
},
|
|
3908
|
+
|
|
3909
|
+
set baz(arg: 0) {
|
|
3910
|
+
//
|
|
3911
|
+
},
|
|
3912
|
+
};`;
|
|
3913
|
+
|
|
3914
|
+
const result = await format(input);
|
|
3915
|
+
expect(result).toBeWithNewline(expected);
|
|
3916
|
+
});
|
|
3815
3917
|
});
|
|
3816
3918
|
});
|
|
3817
3919
|
});
|