@tsrx/prettier-plugin 0.3.66 → 0.3.68
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 +46 -9
- package/src/index.test.js +99 -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.68",
|
|
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.16"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"src/"
|
package/src/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
/** @typedef {Partial<Pick<ParserOptions, 'singleQuote' | 'jsxSingleQuote' | 'semi' | 'trailingComma' | 'useTabs' | 'tabWidth' | 'singleAttributePerLine' | 'bracketSameLine' | 'bracketSpacing' | 'arrowParens' | 'originalText' | 'printWidth'>> & { locStart: (node: AST.NodeWithLocation) => number, locEnd: (node: AST.NodeWithLocation) => number }} RippleFormatOptions */
|
|
18
18
|
|
|
19
|
-
/** @typedef {{ isInAttribute?: boolean, isInArray?: boolean, allowInlineObject?: boolean, isConditionalTest?: boolean, isNestedConditional?: boolean, suppressLeadingComments?: boolean, suppressExpressionLeadingComments?: boolean, isInlineContext?: boolean, isStatement?: boolean, isLogicalAndOr?: boolean, allowShorthandProperty?: boolean, isFirstChild?: boolean, skipComponentLabel?: boolean, noBreakInside?: boolean, expandLastArg?: boolean }} PrintArgs */
|
|
19
|
+
/** @typedef {{ isInAttribute?: boolean, isInArray?: boolean, allowInlineObject?: boolean, isConditionalTest?: boolean, isNestedConditional?: boolean, suppressLeadingComments?: boolean, suppressExpressionLeadingComments?: boolean, isInlineContext?: boolean, isStatement?: boolean, isLogicalAndOr?: boolean, allowShorthandProperty?: boolean, isFirstChild?: boolean, skipComponentLabel?: boolean, noBreakInside?: boolean, expandLastArg?: boolean, preferInlineSimpleUnionType?: boolean }} PrintArgs */
|
|
20
20
|
|
|
21
21
|
import { parseModule } from '@tsrx/core';
|
|
22
22
|
import { doc } from 'prettier';
|
|
@@ -35,6 +35,7 @@ const {
|
|
|
35
35
|
breakParent,
|
|
36
36
|
indentIfBreak,
|
|
37
37
|
lineSuffix,
|
|
38
|
+
align,
|
|
38
39
|
} = builders;
|
|
39
40
|
const { replaceEndOfLine, willBreak } = utils;
|
|
40
41
|
|
|
@@ -1502,16 +1503,24 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
1502
1503
|
break;
|
|
1503
1504
|
|
|
1504
1505
|
case 'TSAsExpression': {
|
|
1505
|
-
|
|
1506
|
+
const typeAnnotation = path.call(
|
|
1507
|
+
(typePath) => print(typePath, { preferInlineSimpleUnionType: true }),
|
|
1508
|
+
'typeAnnotation',
|
|
1509
|
+
);
|
|
1510
|
+
nodeContent = willBreak(typeAnnotation)
|
|
1511
|
+
? [path.call(print, 'expression'), ' as', indent([line, typeAnnotation])]
|
|
1512
|
+
: [path.call(print, 'expression'), ' as ', typeAnnotation];
|
|
1506
1513
|
break;
|
|
1507
1514
|
}
|
|
1508
1515
|
|
|
1509
1516
|
case 'TSSatisfiesExpression': {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
'
|
|
1513
|
-
|
|
1514
|
-
|
|
1517
|
+
const typeAnnotation = path.call(
|
|
1518
|
+
(typePath) => print(typePath, { preferInlineSimpleUnionType: true }),
|
|
1519
|
+
'typeAnnotation',
|
|
1520
|
+
);
|
|
1521
|
+
nodeContent = willBreak(typeAnnotation)
|
|
1522
|
+
? [path.call(print, 'expression'), ' satisfies', indent([line, typeAnnotation])]
|
|
1523
|
+
: [path.call(print, 'expression'), ' satisfies ', typeAnnotation];
|
|
1515
1524
|
break;
|
|
1516
1525
|
}
|
|
1517
1526
|
|
|
@@ -2137,8 +2146,7 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
2137
2146
|
break;
|
|
2138
2147
|
|
|
2139
2148
|
case 'TSUnionType': {
|
|
2140
|
-
|
|
2141
|
-
nodeContent = join(' | ', types);
|
|
2149
|
+
nodeContent = printTSUnionType(node, path, print, args);
|
|
2142
2150
|
break;
|
|
2143
2151
|
}
|
|
2144
2152
|
|
|
@@ -4418,6 +4426,35 @@ function printTSTypeAliasDeclaration(node, path, options, print) {
|
|
|
4418
4426
|
return group([head, ' =', indent([line, path.call(print, 'typeAnnotation')]), semi(options)]);
|
|
4419
4427
|
}
|
|
4420
4428
|
|
|
4429
|
+
/**
|
|
4430
|
+
* Print a TypeScript union type
|
|
4431
|
+
* @param {AST.TSUnionType} node - The union node
|
|
4432
|
+
* @param {AstPath<AST.TSUnionType>} path - The AST path
|
|
4433
|
+
* @param {PrintFn} print - Print callback
|
|
4434
|
+
* @param {PrintArgs} [args] - Additional context arguments
|
|
4435
|
+
* @returns {Doc}
|
|
4436
|
+
*/
|
|
4437
|
+
function printTSUnionType(node, path, print, args) {
|
|
4438
|
+
const types = path.map(print, 'types');
|
|
4439
|
+
const inlineDoc = join(' | ', types);
|
|
4440
|
+
const multilineDoc = [
|
|
4441
|
+
'| ',
|
|
4442
|
+
join(
|
|
4443
|
+
[hardline, '| '],
|
|
4444
|
+
types.map((typeDoc) => align(2, typeDoc)),
|
|
4445
|
+
),
|
|
4446
|
+
];
|
|
4447
|
+
const shouldBreak = node.types.some(
|
|
4448
|
+
(typeNode, index) => !wasOriginallySingleLine(typeNode) || willBreak(types[index]),
|
|
4449
|
+
);
|
|
4450
|
+
|
|
4451
|
+
if (args?.preferInlineSimpleUnionType && !types.some((typeDoc) => willBreak(typeDoc))) {
|
|
4452
|
+
return inlineDoc;
|
|
4453
|
+
}
|
|
4454
|
+
|
|
4455
|
+
return shouldBreak ? group(multilineDoc) : conditionalGroup([inlineDoc, multilineDoc]);
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4421
4458
|
/**
|
|
4422
4459
|
* Print a TypeScript enum declaration
|
|
4423
4460
|
* @param {AST.TSEnumDeclaration} node - The enum declaration node
|
package/src/index.test.js
CHANGED
|
@@ -3035,6 +3035,41 @@ function test() {
|
|
|
3035
3035
|
expect(result).toBeWithNewline(expected);
|
|
3036
3036
|
});
|
|
3037
3037
|
|
|
3038
|
+
it('should preserve comments in destructured typed component parameters', async () => {
|
|
3039
|
+
const expected = `component Child({
|
|
3040
|
+
tr: &[count, tr],
|
|
3041
|
+
// test,
|
|
3042
|
+
}: {
|
|
3043
|
+
tr: [number, Tracked<number>];
|
|
3044
|
+
// test: (node: HTMLDivElement) => void;
|
|
3045
|
+
}) {
|
|
3046
|
+
<button
|
|
3047
|
+
onClick={() => {
|
|
3048
|
+
count++;
|
|
3049
|
+
tr[0]++;
|
|
3050
|
+
}}
|
|
3051
|
+
>
|
|
3052
|
+
{count}
|
|
3053
|
+
</button>
|
|
3054
|
+
}`;
|
|
3055
|
+
|
|
3056
|
+
const result = await format(expected);
|
|
3057
|
+
expect(result).toBeWithNewline(expected);
|
|
3058
|
+
});
|
|
3059
|
+
|
|
3060
|
+
it('should preserve comments in destructured typed function parameters', async () => {
|
|
3061
|
+
const expected = `function Child({
|
|
3062
|
+
tr: &[count, tr],
|
|
3063
|
+
// test,
|
|
3064
|
+
}: {
|
|
3065
|
+
tr: [number, Tracked<number>];
|
|
3066
|
+
// test: (node: HTMLDivElement) => void;
|
|
3067
|
+
}) {}`;
|
|
3068
|
+
|
|
3069
|
+
const result = await format(expected);
|
|
3070
|
+
expect(result).toBeWithNewline(expected);
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3038
3073
|
it('should preserve trailing comments in call arguments', async () => {
|
|
3039
3074
|
const expected = `fn(
|
|
3040
3075
|
arg1,
|
|
@@ -3782,6 +3817,70 @@ second"</pre>
|
|
|
3782
3817
|
expect(result).toBeWithNewline(expected);
|
|
3783
3818
|
});
|
|
3784
3819
|
|
|
3820
|
+
it('should normalize simple cast union types at print width 100', async () => {
|
|
3821
|
+
const input = `const alphaLink = container.querySelector('[data-route-id="alpha"]') as HTMLAnchorElement | null;
|
|
3822
|
+
const saveButton = container.querySelector('[data-action-id="save"]') as HTMLButtonElement | null;
|
|
3823
|
+
const deleteButton = container.querySelector('[data-action-id="delete"]') as | HTMLButtonElement
|
|
3824
|
+
| null;`;
|
|
3825
|
+
|
|
3826
|
+
const expected = `const alphaLink = container.querySelector('[data-route-id="alpha"]') as HTMLAnchorElement | null;
|
|
3827
|
+
const saveButton = container.querySelector('[data-action-id="save"]') as HTMLButtonElement | null;
|
|
3828
|
+
const deleteButton = container.querySelector(
|
|
3829
|
+
'[data-action-id="delete"]',
|
|
3830
|
+
) as HTMLButtonElement | null;`;
|
|
3831
|
+
|
|
3832
|
+
const result = await format(input, { printWidth: 100, singleQuote: true });
|
|
3833
|
+
expect(result).toBeWithNewline(expected);
|
|
3834
|
+
});
|
|
3835
|
+
|
|
3836
|
+
it('should normalize simple cast union types at print width 80', async () => {
|
|
3837
|
+
const input = `const alphaLink = container.querySelector('[data-route-id="alpha"]') as HTMLAnchorElement | null;
|
|
3838
|
+
const saveButton = container.querySelector('[data-action-id="save"]') as HTMLButtonElement | null;
|
|
3839
|
+
const deleteButton = container.querySelector('[data-action-id="delete"]') as | HTMLButtonElement
|
|
3840
|
+
| null;`;
|
|
3841
|
+
|
|
3842
|
+
const expected = `const alphaLink = container.querySelector(
|
|
3843
|
+
'[data-route-id="alpha"]',
|
|
3844
|
+
) as HTMLAnchorElement | null;
|
|
3845
|
+
const saveButton = container.querySelector(
|
|
3846
|
+
'[data-action-id="save"]',
|
|
3847
|
+
) as HTMLButtonElement | null;
|
|
3848
|
+
const deleteButton = container.querySelector(
|
|
3849
|
+
'[data-action-id="delete"]',
|
|
3850
|
+
) as HTMLButtonElement | null;`;
|
|
3851
|
+
|
|
3852
|
+
const result = await format(input, { printWidth: 80, singleQuote: true });
|
|
3853
|
+
expect(result).toBeWithNewline(expected);
|
|
3854
|
+
});
|
|
3855
|
+
|
|
3856
|
+
it('should format multiline TypeScript union object types like Prettier TypeScript', async () => {
|
|
3857
|
+
const input = `type SvgIconSource = { name: SvgIconName; data?: never } | {
|
|
3858
|
+
data: SvgIconData;
|
|
3859
|
+
name?: never;
|
|
3860
|
+
}`;
|
|
3861
|
+
|
|
3862
|
+
const expected = `type SvgIconSource =
|
|
3863
|
+
| { name: SvgIconName; data?: never }
|
|
3864
|
+
| {
|
|
3865
|
+
data: SvgIconData;
|
|
3866
|
+
name?: never;
|
|
3867
|
+
};`;
|
|
3868
|
+
|
|
3869
|
+
const result = await format(input);
|
|
3870
|
+
expect(result).toBeWithNewline(expected);
|
|
3871
|
+
});
|
|
3872
|
+
|
|
3873
|
+
it('should break long TypeScript union types with leading operators', async () => {
|
|
3874
|
+
const input = `type Source = SomeVeryLongTypeNameThatWillDefinitelyNotFit | AnotherVeryLongTypeNameThatWillDefinitelyNotFit;`;
|
|
3875
|
+
|
|
3876
|
+
const expected = `type Source =
|
|
3877
|
+
| SomeVeryLongTypeNameThatWillDefinitelyNotFit
|
|
3878
|
+
| AnotherVeryLongTypeNameThatWillDefinitelyNotFit;`;
|
|
3879
|
+
|
|
3880
|
+
const result = await format(input, { printWidth: 50 });
|
|
3881
|
+
expect(result).toBeWithNewline(expected);
|
|
3882
|
+
});
|
|
3883
|
+
|
|
3785
3884
|
it('should not overindent multiline object type aliases', async () => {
|
|
3786
3885
|
const input = `type ModuleShape = {
|
|
3787
3886
|
default: ComponentType<{ value: string }>;
|