@ripple-ts/prettier-plugin 0.2.157 → 0.2.158

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": "@ripple-ts/prettier-plugin",
3
- "version": "0.2.157",
3
+ "version": "0.2.158",
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.157"
28
+ "ripple": "0.2.158"
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;
@@ -4325,29 +4330,59 @@ function printTsxCompat(node, path, options, print) {
4325
4330
  }
4326
4331
 
4327
4332
  // Print JSXElement children - they remain as JSX
4328
- // Filter out whitespace-only JSXText nodes
4333
+ // Filter out whitespace-only JSXText nodes and merge adjacent text-like nodes
4329
4334
  const finalChildren = [];
4335
+ let accumulatedText = '';
4330
4336
 
4331
4337
  for (let i = 0; i < node.children.length; i++) {
4332
4338
  const child = node.children[i];
4333
4339
 
4334
- // Skip whitespace-only JSXText nodes
4335
- if (child.type === 'JSXText' && !child.value.trim()) {
4336
- continue;
4337
- }
4340
+ // Check if this is a text-like node (JSXText or Identifier in JSX context)
4341
+ const isTextLike = child.type === 'JSXText' || child.type === 'Identifier';
4338
4342
 
4339
- const printedChild = path.call(print, 'children', i);
4340
- finalChildren.push(printedChild);
4343
+ if (isTextLike) {
4344
+ // Get the text content
4345
+ let text;
4346
+ if (child.type === 'JSXText') {
4347
+ text = child.value.trim();
4348
+ } else if (child.type === 'Identifier') {
4349
+ text = child.name;
4350
+ }
4341
4351
 
4342
- if (i < node.children.length - 1) {
4343
- // Only add hardline if the next child is not whitespace-only
4344
- const nextChild = node.children[i + 1];
4345
- if (nextChild && !(nextChild.type === 'JSXText' && !nextChild.value.trim())) {
4352
+ if (text) {
4353
+ if (accumulatedText) {
4354
+ accumulatedText += ' ' + text;
4355
+ } else {
4356
+ accumulatedText = text;
4357
+ }
4358
+ }
4359
+ } else {
4360
+ // Before adding non-text node, flush accumulated text
4361
+ if (accumulatedText) {
4362
+ if (finalChildren.length > 0) {
4363
+ finalChildren.push(hardline);
4364
+ }
4365
+ finalChildren.push(accumulatedText);
4366
+ accumulatedText = '';
4367
+ }
4368
+
4369
+ if (finalChildren.length > 0) {
4346
4370
  finalChildren.push(hardline);
4347
4371
  }
4372
+
4373
+ const printedChild = path.call(print, 'children', i);
4374
+ finalChildren.push(printedChild);
4348
4375
  }
4349
4376
  }
4350
4377
 
4378
+ // Don't forget any remaining accumulated text
4379
+ if (accumulatedText) {
4380
+ if (finalChildren.length > 0) {
4381
+ finalChildren.push(hardline);
4382
+ }
4383
+ finalChildren.push(accumulatedText);
4384
+ }
4385
+
4351
4386
  // Format the TsxCompat element
4352
4387
  const elementOutput = group([
4353
4388
  tagName,
@@ -4404,26 +4439,45 @@ function printJSXElement(node, path, options, print) {
4404
4439
  return concat(['<', tagName, attributesDoc, '></', tagName, '>']);
4405
4440
  }
4406
4441
 
4407
- // Format children - filter out empty text nodes
4442
+ // Format children - filter out empty text nodes and merge adjacent text nodes
4408
4443
  const childrenDocs = [];
4444
+ let currentText = '';
4445
+
4409
4446
  for (let i = 0; i < node.children.length; i++) {
4410
4447
  const child = node.children[i];
4411
4448
 
4412
4449
  if (child.type === 'JSXText') {
4413
- // Handle JSX text nodes - only include if not just whitespace
4414
- const text = child.value;
4415
- if (text.trim()) {
4416
- childrenDocs.push(text);
4450
+ // Accumulate text content, preserving spaces between words
4451
+ const trimmed = child.value.trim();
4452
+ if (trimmed) {
4453
+ if (currentText) {
4454
+ currentText += ' ' + trimmed;
4455
+ } else {
4456
+ currentText = trimmed;
4457
+ }
4417
4458
  }
4418
- } else if (child.type === 'JSXExpressionContainer') {
4419
- // Handle JSX expression containers
4420
- childrenDocs.push(concat(['{', path.call(print, 'children', i, 'expression'), '}']));
4421
4459
  } else {
4422
- // Handle nested JSX elements
4423
- childrenDocs.push(path.call(print, 'children', i));
4460
+ // If we have accumulated text, push it before the non-text node
4461
+ if (currentText) {
4462
+ childrenDocs.push(currentText);
4463
+ currentText = '';
4464
+ }
4465
+
4466
+ if (child.type === 'JSXExpressionContainer') {
4467
+ // Handle JSX expression containers
4468
+ childrenDocs.push(concat(['{', path.call(print, 'children', i, 'expression'), '}']));
4469
+ } else {
4470
+ // Handle nested JSX elements
4471
+ childrenDocs.push(path.call(print, 'children', i));
4472
+ }
4424
4473
  }
4425
4474
  }
4426
4475
 
4476
+ // Don't forget any remaining text
4477
+ if (currentText) {
4478
+ childrenDocs.push(currentText);
4479
+ }
4480
+
4427
4481
  // Check if content can be inlined (single text node or single expression)
4428
4482
  if (childrenDocs.length === 1 && typeof childrenDocs[0] === 'string') {
4429
4483
  return concat(['<', tagName, attributesDoc, '>', childrenDocs[0], '</', tagName, '>']);
package/src/index.test.js CHANGED
@@ -3812,6 +3812,82 @@ 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
+ });
3815
3891
  });
3816
3892
  });
3817
3893
  });