@tsrx/prettier-plugin 0.3.76 → 0.3.77

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.76",
3
+ "version": "0.3.77",
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.24"
30
+ "@tsrx/core": "0.1.25"
31
31
  },
32
32
  "files": [
33
33
  "src/"
package/src/index.js CHANGED
@@ -1851,7 +1851,13 @@ function printRippleNode(node, path, options, print, args) {
1851
1851
  blockParent.type === 'ForOfStatement' ||
1852
1852
  blockParent.type === 'WhileStatement' ||
1853
1853
  blockParent.type === 'DoWhileStatement' ||
1854
- blockParent.type === 'SwitchCase');
1854
+ blockParent.type === 'TryStatement' ||
1855
+ blockParent.type === 'CatchClause' ||
1856
+ blockParent.type === 'SwitchCase' ||
1857
+ blockParent.type === 'JSXIfExpression' ||
1858
+ blockParent.type === 'JSXForExpression' ||
1859
+ blockParent.type === 'JSXTryExpression' ||
1860
+ blockParent.type === 'JSXSwitchExpression');
1855
1861
 
1856
1862
  if (isControlFlow) {
1857
1863
  nodeContent = ['{', hardline, '}'];
@@ -6079,11 +6085,19 @@ function printJSXElement(node, path, options, print) {
6079
6085
  return Array.isArray(leadingComments) && leadingComments.length > 0;
6080
6086
  });
6081
6087
  const forceMultiline = hasClosingComments || hasChildLeadingComments;
6088
+ const singleChildNode = childNodes.length === 1 ? childNodes[0] : null;
6089
+ const hasAuthoredMultilineSingleTextChild =
6090
+ singleChildNode?.type === 'JSXText' && /[\r\n]/u.test(singleChildNode.value);
6082
6091
 
6083
6092
  // Check if content can be inlined (single text node or single expression).
6084
6093
  // Trailing or child-leading comments force the multi-line layout. A single
6085
6094
  // text child stays inline when it fits and otherwise fills/wraps to printWidth.
6086
- if (!forceMultiline && childrenDocs.length === 1 && typeof childrenDocs[0] === 'string') {
6095
+ if (
6096
+ !forceMultiline &&
6097
+ !hasAuthoredMultilineSingleTextChild &&
6098
+ childrenDocs.length === 1 &&
6099
+ typeof childrenDocs[0] === 'string'
6100
+ ) {
6087
6101
  // The open tag breaks for attributes independently; the text+closing get
6088
6102
  // their own group so the text only drops to its own (filled) lines when it
6089
6103
  // itself overflows — otherwise it hugs `>text</tag>`.
package/src/index.test.js CHANGED
@@ -298,6 +298,39 @@ const items=[1,2,3];
298
298
  expect(result).toBeWithNewline(expected);
299
299
  });
300
300
 
301
+ it('preserves authored multiline whitespace around a single JSXText child', async () => {
302
+ const input = `function Foo() @{
303
+ @if (props.onRemove) {
304
+ <button
305
+ class={\`\${styles.actionButton} \${styles.actionButtonDanger}\`}
306
+ type="button"
307
+ onClick={() => {
308
+ void props.onRemove?.();
309
+ }}
310
+ >
311
+ Remove shortcut
312
+ </button>
313
+ }
314
+ }`;
315
+
316
+ const expected = `function Foo() @{
317
+ @if (props.onRemove) {
318
+ <button
319
+ class={\`\${styles.actionButton} \${styles.actionButtonDanger}\`}
320
+ type="button"
321
+ onClick={() => {
322
+ void props.onRemove?.();
323
+ }}
324
+ >
325
+ Remove shortcut
326
+ </button>
327
+ }
328
+ }`;
329
+
330
+ const result = await format(input);
331
+ expect(result).toBeWithNewline(expected);
332
+ });
333
+
301
334
  it('preserves inline text spaces around expression children', async () => {
302
335
  const input = `function Test(){return <div><p class="status">Visible: {String(visible)}</p><p>{name} is visible</p><p>Hello {name}!</p></div>}`;
303
336
  const expected = `function Test() {
@@ -2495,6 +2528,51 @@ files = [...(files ?? []), ...dt.files];`;
2495
2528
  expect(result).toBeWithNewline(expected);
2496
2529
  });
2497
2530
 
2531
+ it('expands empty braces for template control-flow blocks', async () => {
2532
+ const input = `const App=()=> <>@if (ready) {} @else {}@for (const item of items) {} @empty {}</>;`;
2533
+ const expected = `const App = () => <>
2534
+ @if (ready) {
2535
+ } @else {
2536
+ }
2537
+ @for (const item of items) {
2538
+ } @empty {
2539
+ }
2540
+ </>;`;
2541
+ const result = await format(input);
2542
+ expect(result).toBeWithNewline(expected);
2543
+ });
2544
+
2545
+ it('expands empty braces for try family blocks', async () => {
2546
+ const input = `function Foo() @{ @try {} @pending {} @catch {} }
2547
+ function Bar() @{ @try {} @catch {} }
2548
+ function Baz() { try {} catch {} finally {} }
2549
+ function Qux() { try {} catch {} }`;
2550
+ const expected = `function Foo() @{
2551
+ @try {
2552
+ } @pending {
2553
+ } @catch {
2554
+ }
2555
+ }
2556
+ function Bar() @{
2557
+ @try {
2558
+ } @catch {
2559
+ }
2560
+ }
2561
+ function Baz() {
2562
+ try {
2563
+ } catch {
2564
+ } finally {
2565
+ }
2566
+ }
2567
+ function Qux() {
2568
+ try {
2569
+ } catch {
2570
+ }
2571
+ }`;
2572
+ const result = await format(input);
2573
+ expect(result).toBeWithNewline(expected);
2574
+ });
2575
+
2498
2576
  it('prints function with a rest parameter correctly', async () => {
2499
2577
  const expected = `function TestRest(...args: string[]) {
2500
2578
  console.log(args);
@@ -5686,7 +5764,8 @@ render(App);`;
5686
5764
  // <div>
5687
5765
  @try {
5688
5766
  <div>b is true</div>
5689
- } @catch (e) {}
5767
+ } @catch (e) {
5768
+ }
5690
5769
  // <div>
5691
5770
  // <div>
5692
5771
  // @if (b) {
@@ -5704,7 +5783,8 @@ render(App);`;
5704
5783
  // <div>
5705
5784
  @try {
5706
5785
  <div>b is true</div>
5707
- } @catch (e) {}
5786
+ } @catch (e) {
5787
+ }
5708
5788
  // <div>
5709
5789
  // <div>
5710
5790
  // @if (b) {