@tsrx/prettier-plugin 0.3.86 → 0.3.87
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 +108 -58
- package/src/index.test.js +83 -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.87",
|
|
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.4"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@tsrx/core": "0.1.
|
|
30
|
+
"@tsrx/core": "0.1.34"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"src/"
|
package/src/index.js
CHANGED
|
@@ -223,6 +223,32 @@ function hasComment(node) {
|
|
|
223
223
|
return !!(node.leadingComments || node.trailingComments || node.innerComments);
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Check whether a comment is a `prettier-ignore` directive.
|
|
228
|
+
* @param {AST.Comment | undefined} comment - The comment to check
|
|
229
|
+
* @returns {boolean} - True if the comment reads exactly `prettier-ignore`
|
|
230
|
+
*/
|
|
231
|
+
function isPrettierIgnoreComment(comment) {
|
|
232
|
+
if (!comment || (comment.type !== 'Line' && comment.type !== 'Block')) {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
return comment.value.trim() === 'prettier-ignore';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Check whether a node is immediately preceded by a `prettier-ignore` directive.
|
|
240
|
+
* Only the last leading comment counts, matching Prettier core.
|
|
241
|
+
* @param {AST.Node & AST.NodeWithMaybeComments} node - The AST node to check
|
|
242
|
+
* @returns {boolean} - True if the node should be printed verbatim
|
|
243
|
+
*/
|
|
244
|
+
function hasPrettierIgnore(node) {
|
|
245
|
+
const comments = node.leadingComments;
|
|
246
|
+
if (!comments || comments.length === 0) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
return isPrettierIgnoreComment(comments[comments.length - 1]);
|
|
250
|
+
}
|
|
251
|
+
|
|
226
252
|
/**
|
|
227
253
|
* @param {AST.FunctionDeclaration | AST.FunctionExpression | AST.ArrowFunctionExpression | AST.TSDeclareFunction} node - The function node
|
|
228
254
|
* @returns {Array<AST.Pattern | AST.Parameter>} - Array of parameter patterns
|
|
@@ -722,6 +748,70 @@ function printKey(node, path, options, print) {
|
|
|
722
748
|
return parts;
|
|
723
749
|
}
|
|
724
750
|
|
|
751
|
+
/**
|
|
752
|
+
* Combine already-printed leading comment parts, a node's printed body, and its
|
|
753
|
+
* trailing comments into the final Doc returned by {@link printRippleNode}.
|
|
754
|
+
* @param {AST.Node} node - The AST node
|
|
755
|
+
* @param {Doc[]} parts - Leading-comment parts already collected for the node
|
|
756
|
+
* @param {Doc[] | Doc} nodeContent - The printed body of the node
|
|
757
|
+
* @returns {Doc[] | Doc}
|
|
758
|
+
*/
|
|
759
|
+
function finishRippleNode(node, parts, nodeContent) {
|
|
760
|
+
// Handle trailing comments
|
|
761
|
+
if (node.trailingComments) {
|
|
762
|
+
const trailingParts = [];
|
|
763
|
+
let previousComment = null;
|
|
764
|
+
|
|
765
|
+
for (let i = 0; i < node.trailingComments.length; i++) {
|
|
766
|
+
const comment = node.trailingComments[i];
|
|
767
|
+
const isInlineComment = Boolean(
|
|
768
|
+
node.loc && comment.loc && node.loc.end.line === comment.loc.start.line,
|
|
769
|
+
);
|
|
770
|
+
|
|
771
|
+
const commentDoc =
|
|
772
|
+
comment.type === 'Line' ? '//' + comment.value : '/*' + comment.value + '*/';
|
|
773
|
+
|
|
774
|
+
if (isInlineComment) {
|
|
775
|
+
if (comment.type === 'Line') {
|
|
776
|
+
trailingParts.push(lineSuffix([' ', commentDoc]));
|
|
777
|
+
trailingParts.push(breakParent);
|
|
778
|
+
} else {
|
|
779
|
+
trailingParts.push(' ' + commentDoc);
|
|
780
|
+
}
|
|
781
|
+
} else {
|
|
782
|
+
const refs = [];
|
|
783
|
+
refs.push(hardline);
|
|
784
|
+
|
|
785
|
+
const blankLinesBetween = previousComment
|
|
786
|
+
? getBlankLinesBetweenNodes(previousComment, comment)
|
|
787
|
+
: getBlankLinesBetweenNodes(node, comment);
|
|
788
|
+
if (blankLinesBetween > 0) {
|
|
789
|
+
refs.push(hardline);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
refs.push(commentDoc);
|
|
793
|
+
trailingParts.push(lineSuffix(refs));
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
previousComment = comment;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
if (trailingParts.length > 0) {
|
|
800
|
+
parts.push(nodeContent);
|
|
801
|
+
parts.push(...trailingParts);
|
|
802
|
+
return parts;
|
|
803
|
+
}
|
|
804
|
+
} // Return with or without leading comments
|
|
805
|
+
if (parts.length > 0) {
|
|
806
|
+
// Don't add blank line between leading comments and node
|
|
807
|
+
// because they're meant to be attached together
|
|
808
|
+
parts.push(nodeContent);
|
|
809
|
+
return parts;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
return nodeContent;
|
|
813
|
+
}
|
|
814
|
+
|
|
725
815
|
/**
|
|
726
816
|
* Main print function for Ripple AST nodes
|
|
727
817
|
* @param {AST.Node | AST.CSS.StyleSheet} node - The AST node to print
|
|
@@ -812,6 +902,23 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
812
902
|
}
|
|
813
903
|
}
|
|
814
904
|
|
|
905
|
+
// A `prettier-ignore` directive keeps the node's original source verbatim.
|
|
906
|
+
const commentNode = /** @type {AST.Node & AST.NodeWithMaybeComments} */ (node);
|
|
907
|
+
const ignoreStart = /** @type {AST.NodeWithLocation} */ (node).start;
|
|
908
|
+
const ignoreEnd = /** @type {AST.NodeWithLocation} */ (node).end;
|
|
909
|
+
if (
|
|
910
|
+
hasPrettierIgnore(commentNode) &&
|
|
911
|
+
typeof options.originalText === 'string' &&
|
|
912
|
+
typeof ignoreStart === 'number' &&
|
|
913
|
+
typeof ignoreEnd === 'number'
|
|
914
|
+
) {
|
|
915
|
+
return finishRippleNode(
|
|
916
|
+
commentNode,
|
|
917
|
+
parts,
|
|
918
|
+
replaceEndOfLine(options.originalText.slice(ignoreStart, ignoreEnd)),
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
|
|
815
922
|
/** @type {Doc[] | Doc} */
|
|
816
923
|
let nodeContent;
|
|
817
924
|
|
|
@@ -2338,64 +2445,7 @@ function printRippleNode(node, path, options, print, args) {
|
|
|
2338
2445
|
break;
|
|
2339
2446
|
}
|
|
2340
2447
|
|
|
2341
|
-
|
|
2342
|
-
if (node.trailingComments) {
|
|
2343
|
-
const trailingParts = [];
|
|
2344
|
-
let previousComment = null;
|
|
2345
|
-
|
|
2346
|
-
for (let i = 0; i < node.trailingComments.length; i++) {
|
|
2347
|
-
const comment = node.trailingComments[i];
|
|
2348
|
-
const isInlineComment = Boolean(
|
|
2349
|
-
node.loc && comment.loc && node.loc.end.line === comment.loc.start.line,
|
|
2350
|
-
);
|
|
2351
|
-
|
|
2352
|
-
const commentDoc =
|
|
2353
|
-
comment.type === 'Line' ? '//' + comment.value : '/*' + comment.value + '*/';
|
|
2354
|
-
|
|
2355
|
-
if (isInlineComment) {
|
|
2356
|
-
if (comment.type === 'Line') {
|
|
2357
|
-
trailingParts.push(lineSuffix([' ', commentDoc]));
|
|
2358
|
-
trailingParts.push(breakParent);
|
|
2359
|
-
} else {
|
|
2360
|
-
trailingParts.push(' ' + commentDoc);
|
|
2361
|
-
}
|
|
2362
|
-
} else {
|
|
2363
|
-
const refs = [];
|
|
2364
|
-
refs.push(hardline);
|
|
2365
|
-
|
|
2366
|
-
const blankLinesBetween = previousComment
|
|
2367
|
-
? getBlankLinesBetweenNodes(previousComment, comment)
|
|
2368
|
-
: getBlankLinesBetweenNodes(node, comment);
|
|
2369
|
-
if (blankLinesBetween > 0) {
|
|
2370
|
-
refs.push(hardline);
|
|
2371
|
-
}
|
|
2372
|
-
|
|
2373
|
-
if (comment.type === 'Line') {
|
|
2374
|
-
refs.push(commentDoc);
|
|
2375
|
-
trailingParts.push(lineSuffix(refs));
|
|
2376
|
-
} else {
|
|
2377
|
-
refs.push(commentDoc);
|
|
2378
|
-
trailingParts.push(lineSuffix(refs));
|
|
2379
|
-
}
|
|
2380
|
-
}
|
|
2381
|
-
|
|
2382
|
-
previousComment = comment;
|
|
2383
|
-
}
|
|
2384
|
-
|
|
2385
|
-
if (trailingParts.length > 0) {
|
|
2386
|
-
parts.push(nodeContent);
|
|
2387
|
-
parts.push(...trailingParts);
|
|
2388
|
-
return parts;
|
|
2389
|
-
}
|
|
2390
|
-
} // Return with or without leading comments
|
|
2391
|
-
if (parts.length > 0) {
|
|
2392
|
-
// Don't add blank line between leading comments and node
|
|
2393
|
-
// because they're meant to be attached together
|
|
2394
|
-
parts.push(nodeContent);
|
|
2395
|
-
return parts;
|
|
2396
|
-
}
|
|
2397
|
-
|
|
2398
|
-
return nodeContent;
|
|
2448
|
+
return finishRippleNode(/** @type {AST.Node} */ (node), parts, nodeContent);
|
|
2399
2449
|
}
|
|
2400
2450
|
|
|
2401
2451
|
/**
|
package/src/index.test.js
CHANGED
|
@@ -851,6 +851,89 @@ const items=[1,2,3];
|
|
|
851
851
|
expect(result).toBeWithNewline(expected);
|
|
852
852
|
});
|
|
853
853
|
|
|
854
|
+
describe('prettier-ignore', () => {
|
|
855
|
+
it('preserves a statement verbatim after a line directive', async () => {
|
|
856
|
+
const input = `export function App() {
|
|
857
|
+
// prettier-ignore
|
|
858
|
+
const matrix = [1,0,0,
|
|
859
|
+
0,1,0,
|
|
860
|
+
0,0,1];
|
|
861
|
+
return <div>{matrix.length}</div>;
|
|
862
|
+
}`;
|
|
863
|
+
const expected = `export function App() {
|
|
864
|
+
// prettier-ignore
|
|
865
|
+
const matrix = [1,0,0,
|
|
866
|
+
0,1,0,
|
|
867
|
+
0,0,1];
|
|
868
|
+
return <div>{matrix.length}</div>;
|
|
869
|
+
}`;
|
|
870
|
+
const result = await format(input);
|
|
871
|
+
expect(result).toBeWithNewline(expected);
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
it('preserves a statement verbatim after a block directive', async () => {
|
|
875
|
+
const input = `export function App() {
|
|
876
|
+
/* prettier-ignore */
|
|
877
|
+
const obj = {a:1, b:2};
|
|
878
|
+
return <div>{obj.a}</div>;
|
|
879
|
+
}`;
|
|
880
|
+
const expected = `export function App() {
|
|
881
|
+
/* prettier-ignore */
|
|
882
|
+
const obj = {a:1, b:2};
|
|
883
|
+
return <div>{obj.a}</div>;
|
|
884
|
+
}`;
|
|
885
|
+
const result = await format(input);
|
|
886
|
+
expect(result).toBeWithNewline(expected);
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
it('preserves a JSX element verbatim', async () => {
|
|
890
|
+
const input = `export function App() @{
|
|
891
|
+
// prettier-ignore
|
|
892
|
+
<div class="x" id="y">
|
|
893
|
+
hello
|
|
894
|
+
</div>
|
|
895
|
+
}`;
|
|
896
|
+
const expected = `export function App() @{
|
|
897
|
+
// prettier-ignore
|
|
898
|
+
<div class="x" id="y">
|
|
899
|
+
hello
|
|
900
|
+
</div>
|
|
901
|
+
}`;
|
|
902
|
+
const result = await format(input);
|
|
903
|
+
expect(result).toBeWithNewline(expected);
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
it('preserves a whitespace-only fragment verbatim', async () => {
|
|
907
|
+
const input = `function WhitespaceOnlyApp() @{
|
|
908
|
+
// prettier-ignore
|
|
909
|
+
<>
|
|
910
|
+
</>
|
|
911
|
+
}`;
|
|
912
|
+
const expected = `function WhitespaceOnlyApp() @{
|
|
913
|
+
// prettier-ignore
|
|
914
|
+
<>
|
|
915
|
+
</>
|
|
916
|
+
}`;
|
|
917
|
+
const result = await format(input);
|
|
918
|
+
expect(result).toBeWithNewline(expected);
|
|
919
|
+
});
|
|
920
|
+
|
|
921
|
+
it('still formats when the comment is not a prettier-ignore directive', async () => {
|
|
922
|
+
const input = `export function App() {
|
|
923
|
+
// this is a normal comment
|
|
924
|
+
const obj = {a:1, b:2};
|
|
925
|
+
return <div>{obj.a}</div>;
|
|
926
|
+
}`;
|
|
927
|
+
const expected = `export function App() {
|
|
928
|
+
// this is a normal comment
|
|
929
|
+
const obj = { a: 1, b: 2 };
|
|
930
|
+
return <div>{obj.a}</div>;
|
|
931
|
+
}`;
|
|
932
|
+
const result = await format(input);
|
|
933
|
+
expect(result).toBeWithNewline(expected);
|
|
934
|
+
});
|
|
935
|
+
});
|
|
936
|
+
|
|
854
937
|
describe('recovered', () => {
|
|
855
938
|
/**
|
|
856
939
|
* @param {string} code
|