@tsrx/prettier-plugin 0.3.76 → 0.3.78
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 +22 -3
- package/src/index.test.js +110 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsrx/prettier-plugin",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.78",
|
|
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.26"
|
|
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 === '
|
|
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, '}'];
|
|
@@ -5864,7 +5870,12 @@ function printJSXElement(node, path, options, print) {
|
|
|
5864
5870
|
const openingElement = node.openingElement;
|
|
5865
5871
|
const closingElement = node.closingElement;
|
|
5866
5872
|
|
|
5867
|
-
|
|
5873
|
+
// Dynamic tags (`<{expr}>`) print the opening expression for both tags so
|
|
5874
|
+
// they stay textually identical; static names print as plain strings.
|
|
5875
|
+
const tagName =
|
|
5876
|
+
/** @type {any} */ (openingElement.name).type === 'JSXExpressionContainer'
|
|
5877
|
+
? ['{', path.call(print, 'openingElement', 'name', 'expression'), '}']
|
|
5878
|
+
: printJSXElementName(openingElement.name);
|
|
5868
5879
|
|
|
5869
5880
|
const isSelfClosing = openingElement.selfClosing;
|
|
5870
5881
|
const hasAttributes = openingElement.attributes && openingElement.attributes.length > 0;
|
|
@@ -6079,11 +6090,19 @@ function printJSXElement(node, path, options, print) {
|
|
|
6079
6090
|
return Array.isArray(leadingComments) && leadingComments.length > 0;
|
|
6080
6091
|
});
|
|
6081
6092
|
const forceMultiline = hasClosingComments || hasChildLeadingComments;
|
|
6093
|
+
const singleChildNode = childNodes.length === 1 ? childNodes[0] : null;
|
|
6094
|
+
const hasAuthoredMultilineSingleTextChild =
|
|
6095
|
+
singleChildNode?.type === 'JSXText' && /[\r\n]/u.test(singleChildNode.value);
|
|
6082
6096
|
|
|
6083
6097
|
// Check if content can be inlined (single text node or single expression).
|
|
6084
6098
|
// Trailing or child-leading comments force the multi-line layout. A single
|
|
6085
6099
|
// text child stays inline when it fits and otherwise fills/wraps to printWidth.
|
|
6086
|
-
if (
|
|
6100
|
+
if (
|
|
6101
|
+
!forceMultiline &&
|
|
6102
|
+
!hasAuthoredMultilineSingleTextChild &&
|
|
6103
|
+
childrenDocs.length === 1 &&
|
|
6104
|
+
typeof childrenDocs[0] === 'string'
|
|
6105
|
+
) {
|
|
6087
6106
|
// The open tag breaks for attributes independently; the text+closing get
|
|
6088
6107
|
// their own group so the text only drops to its own (filled) lines when it
|
|
6089
6108
|
// itself overflows — otherwise it hugs `>text</tag>`.
|
package/src/index.test.js
CHANGED
|
@@ -74,6 +74,34 @@ describe('prettier-plugin', () => {
|
|
|
74
74
|
expect(result).toBeWithNewline(expected);
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
+
it('formats dynamic element tags', async () => {
|
|
78
|
+
const input = `function App(props){const Child='div';return <{Child} {...props} class="card"><span>Hello</span></{Child}>}`;
|
|
79
|
+
const expected = `function App(props) {
|
|
80
|
+
const Child = "div";
|
|
81
|
+
return <{Child} {...props} class="card">
|
|
82
|
+
<span>Hello</span>
|
|
83
|
+
</{Child}>;
|
|
84
|
+
}`;
|
|
85
|
+
|
|
86
|
+
const result = await format(input);
|
|
87
|
+
expect(result).toBeWithNewline(expected);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('formats dynamic element tag expressions', async () => {
|
|
91
|
+
const input = `function App(){return <><{registry.item}/><{items[0]}/><{'section'}/><{\`article\`}/></>;}`;
|
|
92
|
+
const expected = `function App() {
|
|
93
|
+
return <>
|
|
94
|
+
<{registry.item} />
|
|
95
|
+
<{items[0]} />
|
|
96
|
+
<{"section"} />
|
|
97
|
+
<{\`article\`} />
|
|
98
|
+
</>;
|
|
99
|
+
}`;
|
|
100
|
+
|
|
101
|
+
const result = await format(input);
|
|
102
|
+
expect(result).toBeWithNewline(expected);
|
|
103
|
+
});
|
|
104
|
+
|
|
77
105
|
it('formats a fragment code block with setup and template control flow', async () => {
|
|
78
106
|
const input = `function App(){return <>@{
|
|
79
107
|
const items=[1,2,3];
|
|
@@ -298,6 +326,39 @@ const items=[1,2,3];
|
|
|
298
326
|
expect(result).toBeWithNewline(expected);
|
|
299
327
|
});
|
|
300
328
|
|
|
329
|
+
it('preserves authored multiline whitespace around a single JSXText child', async () => {
|
|
330
|
+
const input = `function Foo() @{
|
|
331
|
+
@if (props.onRemove) {
|
|
332
|
+
<button
|
|
333
|
+
class={\`\${styles.actionButton} \${styles.actionButtonDanger}\`}
|
|
334
|
+
type="button"
|
|
335
|
+
onClick={() => {
|
|
336
|
+
void props.onRemove?.();
|
|
337
|
+
}}
|
|
338
|
+
>
|
|
339
|
+
Remove shortcut
|
|
340
|
+
</button>
|
|
341
|
+
}
|
|
342
|
+
}`;
|
|
343
|
+
|
|
344
|
+
const expected = `function Foo() @{
|
|
345
|
+
@if (props.onRemove) {
|
|
346
|
+
<button
|
|
347
|
+
class={\`\${styles.actionButton} \${styles.actionButtonDanger}\`}
|
|
348
|
+
type="button"
|
|
349
|
+
onClick={() => {
|
|
350
|
+
void props.onRemove?.();
|
|
351
|
+
}}
|
|
352
|
+
>
|
|
353
|
+
Remove shortcut
|
|
354
|
+
</button>
|
|
355
|
+
}
|
|
356
|
+
}`;
|
|
357
|
+
|
|
358
|
+
const result = await format(input);
|
|
359
|
+
expect(result).toBeWithNewline(expected);
|
|
360
|
+
});
|
|
361
|
+
|
|
301
362
|
it('preserves inline text spaces around expression children', async () => {
|
|
302
363
|
const input = `function Test(){return <div><p class="status">Visible: {String(visible)}</p><p>{name} is visible</p><p>Hello {name}!</p></div>}`;
|
|
303
364
|
const expected = `function Test() {
|
|
@@ -2495,6 +2556,51 @@ files = [...(files ?? []), ...dt.files];`;
|
|
|
2495
2556
|
expect(result).toBeWithNewline(expected);
|
|
2496
2557
|
});
|
|
2497
2558
|
|
|
2559
|
+
it('expands empty braces for template control-flow blocks', async () => {
|
|
2560
|
+
const input = `const App=()=> <>@if (ready) {} @else {}@for (const item of items) {} @empty {}</>;`;
|
|
2561
|
+
const expected = `const App = () => <>
|
|
2562
|
+
@if (ready) {
|
|
2563
|
+
} @else {
|
|
2564
|
+
}
|
|
2565
|
+
@for (const item of items) {
|
|
2566
|
+
} @empty {
|
|
2567
|
+
}
|
|
2568
|
+
</>;`;
|
|
2569
|
+
const result = await format(input);
|
|
2570
|
+
expect(result).toBeWithNewline(expected);
|
|
2571
|
+
});
|
|
2572
|
+
|
|
2573
|
+
it('expands empty braces for try family blocks', async () => {
|
|
2574
|
+
const input = `function Foo() @{ @try {} @pending {} @catch {} }
|
|
2575
|
+
function Bar() @{ @try {} @catch {} }
|
|
2576
|
+
function Baz() { try {} catch {} finally {} }
|
|
2577
|
+
function Qux() { try {} catch {} }`;
|
|
2578
|
+
const expected = `function Foo() @{
|
|
2579
|
+
@try {
|
|
2580
|
+
} @pending {
|
|
2581
|
+
} @catch {
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
function Bar() @{
|
|
2585
|
+
@try {
|
|
2586
|
+
} @catch {
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
function Baz() {
|
|
2590
|
+
try {
|
|
2591
|
+
} catch {
|
|
2592
|
+
} finally {
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
function Qux() {
|
|
2596
|
+
try {
|
|
2597
|
+
} catch {
|
|
2598
|
+
}
|
|
2599
|
+
}`;
|
|
2600
|
+
const result = await format(input);
|
|
2601
|
+
expect(result).toBeWithNewline(expected);
|
|
2602
|
+
});
|
|
2603
|
+
|
|
2498
2604
|
it('prints function with a rest parameter correctly', async () => {
|
|
2499
2605
|
const expected = `function TestRest(...args: string[]) {
|
|
2500
2606
|
console.log(args);
|
|
@@ -5686,7 +5792,8 @@ render(App);`;
|
|
|
5686
5792
|
// <div>
|
|
5687
5793
|
@try {
|
|
5688
5794
|
<div>b is true</div>
|
|
5689
|
-
} @catch (e) {
|
|
5795
|
+
} @catch (e) {
|
|
5796
|
+
}
|
|
5690
5797
|
// <div>
|
|
5691
5798
|
// <div>
|
|
5692
5799
|
// @if (b) {
|
|
@@ -5704,7 +5811,8 @@ render(App);`;
|
|
|
5704
5811
|
// <div>
|
|
5705
5812
|
@try {
|
|
5706
5813
|
<div>b is true</div>
|
|
5707
|
-
} @catch (e) {
|
|
5814
|
+
} @catch (e) {
|
|
5815
|
+
}
|
|
5708
5816
|
// <div>
|
|
5709
5817
|
// <div>
|
|
5710
5818
|
// @if (b) {
|