@aforemendude/prettier-plugin-wrap-comments 1.0.6 → 1.1.1

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.
Files changed (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +85 -8
  3. package/dist/comments/comment-body.d.ts +4 -0
  4. package/dist/comments/comment-body.js +36 -0
  5. package/dist/comments/comment-directives.d.ts +2 -0
  6. package/dist/comments/comment-directives.js +52 -0
  7. package/dist/comments/comment-eligibility.d.ts +5 -0
  8. package/dist/comments/comment-eligibility.js +23 -0
  9. package/dist/comments/comment-location.d.ts +9 -0
  10. package/dist/comments/comment-location.js +39 -0
  11. package/dist/comments/comment-ranges.d.ts +24 -0
  12. package/dist/comments/comment-ranges.js +36 -0
  13. package/dist/comments/embedded-expression-ranges.d.ts +12 -0
  14. package/dist/comments/embedded-expression-ranges.js +117 -0
  15. package/dist/comments/jsx-expression-layout.d.ts +10 -0
  16. package/dist/comments/jsx-expression-layout.js +114 -0
  17. package/dist/comments/line-comment-groups.d.ts +6 -0
  18. package/dist/comments/line-comment-groups.js +28 -0
  19. package/dist/comments/prettier-ignore.d.ts +9 -0
  20. package/dist/comments/prettier-ignore.js +239 -0
  21. package/dist/comments/printer-layout.d.ts +18 -0
  22. package/dist/comments/printer-layout.js +65 -0
  23. package/dist/comments/{block.d.ts → wrap-block-comment.d.ts} +5 -1
  24. package/dist/comments/{block.js → wrap-block-comment.js} +18 -15
  25. package/dist/comments/wrap-comments.d.ts +9 -0
  26. package/dist/comments/wrap-comments.js +169 -0
  27. package/dist/comments/wrap-line-comment-group.d.ts +4 -0
  28. package/dist/comments/wrap-line-comment-group.js +39 -0
  29. package/dist/comments/wrap-trailing-line-comment.d.ts +9 -0
  30. package/dist/comments/wrap-trailing-line-comment.js +78 -0
  31. package/dist/index.d.ts +2 -2
  32. package/dist/index.js +4 -4
  33. package/dist/plugin/create-parsers.d.ts +2 -0
  34. package/dist/plugin/create-parsers.js +60 -0
  35. package/dist/plugin/create-printers.d.ts +2 -0
  36. package/dist/plugin/create-printers.js +59 -0
  37. package/dist/plugin/get-printer-layout-source.d.ts +4 -0
  38. package/dist/plugin/get-printer-layout-source.js +35 -0
  39. package/dist/plugin/jsx-comment-rewrite-metadata.d.ts +8 -0
  40. package/dist/plugin/jsx-comment-rewrite-metadata.js +40 -0
  41. package/dist/plugin/parser-names.d.ts +2 -0
  42. package/dist/plugin/parser-names.js +1 -0
  43. package/dist/utils/ast.d.ts +12 -0
  44. package/dist/utils/ast.js +95 -0
  45. package/dist/utils/display-width.d.ts +2 -0
  46. package/dist/utils/display-width.js +19 -0
  47. package/dist/{shared/markdown.d.ts → utils/format-markdown.d.ts} +1 -1
  48. package/dist/utils/format-markdown.js +69 -0
  49. package/dist/utils/indentation.d.ts +4 -0
  50. package/dist/utils/indentation.js +21 -0
  51. package/dist/utils/replacements.d.ts +6 -0
  52. package/dist/utils/replacements.js +21 -0
  53. package/dist/utils/source-lines.d.ts +7 -0
  54. package/dist/utils/source-lines.js +43 -0
  55. package/dist/utils/type-guards.d.ts +2 -0
  56. package/dist/utils/type-guards.js +6 -0
  57. package/dist/utils/whitespace.d.ts +3 -0
  58. package/dist/utils/whitespace.js +26 -0
  59. package/dist/{shared/options.d.ts → utils/wrap-options.d.ts} +2 -1
  60. package/package.json +27 -11
  61. package/dist/comments/core.d.ts +0 -8
  62. package/dist/comments/core.js +0 -114
  63. package/dist/comments/line.d.ts +0 -6
  64. package/dist/comments/line.js +0 -108
  65. package/dist/comments/wrap.d.ts +0 -3
  66. package/dist/comments/wrap.js +0 -439
  67. package/dist/plugin/parsers.d.ts +0 -2
  68. package/dist/plugin/parsers.js +0 -35
  69. package/dist/plugin/printers.d.ts +0 -2
  70. package/dist/plugin/printers.js +0 -39
  71. package/dist/shared/markdown.js +0 -20
  72. package/dist/shared/text.d.ts +0 -15
  73. package/dist/shared/text.js +0 -99
  74. package/dist/shared/types.d.ts +0 -30
  75. package/dist/shared/types.js +0 -1
  76. /package/dist/{shared/options.js → utils/wrap-options.js} +0 -0
@@ -0,0 +1,114 @@
1
+ import { isStandaloneBlockComment } from './comment-location.js';
2
+ import { getAstNodeRange, visitAstNodes } from '../utils/ast.js';
3
+ import { getColumns } from '../utils/display-width.js';
4
+ import { getLeadingIndent } from '../utils/indentation.js';
5
+ import { getLinePrefix, getLineStart } from '../utils/source-lines.js';
6
+ import { isRecord } from '../utils/type-guards.js';
7
+ import { skipWhitespace, trimWhitespaceEnd } from '../utils/whitespace.js';
8
+ export function collectJsxExpressionContainerRanges(ast) {
9
+ const ranges = [];
10
+ visitAstNodes(ast, (node) => {
11
+ if (node['type'] !== 'JSXExpressionContainer') {
12
+ return;
13
+ }
14
+ const range = getAstNodeRange(node);
15
+ if (range === undefined) {
16
+ return;
17
+ }
18
+ const expressionNode = node['expression'];
19
+ const expression = isRecord(expressionNode) && expressionNode['type'] !== 'JSXEmptyExpression'
20
+ ? getAstNodeRange(expressionNode)
21
+ : undefined;
22
+ ranges.push({ ...range, expression });
23
+ });
24
+ return ranges.sort((left, right) => left.start - right.start || right.end - left.end);
25
+ }
26
+ export function getPrintedJsxCommentMarkerColumn(text, container, tabWidth) {
27
+ const linePrefix = getLinePrefix(text, container.start);
28
+ const lineIndent = getLeadingIndent(linePrefix);
29
+ return getColumns(lineIndent, tabWidth) + tabWidth;
30
+ }
31
+ export function getJsxExpressionBlockCommentLayout(text, comment, previousComment, containerMatch, tabWidth, outputCommentLayout, outputCommentMarkerColumns) {
32
+ if (containerMatch === undefined) {
33
+ return undefined;
34
+ }
35
+ const container = containerMatch.range;
36
+ if (text[container.start] !== '{' || text[container.end - 1] !== '}') {
37
+ return undefined;
38
+ }
39
+ const hasExpressionBeforeComment = container.expression !== undefined && container.expression.start < comment.start;
40
+ const hasExpressionAfterComment = container.expression !== undefined && container.expression.end > comment.end;
41
+ const multilineMarkerColumn = outputCommentMarkerColumns[containerMatch.index] ??
42
+ getJsxExpressionContainerOutputColumn(text, container, tabWidth) + tabWidth;
43
+ const markerColumn = outputCommentLayout?.markerColumn ?? multilineMarkerColumn;
44
+ const contentColumn = multilineMarkerColumn + 3;
45
+ if (!hasExpressionBeforeComment && !hasExpressionAfterComment) {
46
+ return {
47
+ contentColumn,
48
+ markerColumn,
49
+ multilineIndent: '',
50
+ placement: 'standalone',
51
+ singleLineSuffixWidth: outputCommentLayout?.suffixWidth ?? 1,
52
+ };
53
+ }
54
+ if (hasExpressionBeforeComment && !hasExpressionAfterComment) {
55
+ const hasEarlierCommentInContainer = previousComment !== undefined && previousComment.start > container.start && previousComment.end < container.end;
56
+ if (hasEarlierCommentInContainer) {
57
+ return {
58
+ contentColumn,
59
+ markerColumn,
60
+ multilineIndent: '',
61
+ placement: 'standalone',
62
+ singleLineSuffixWidth: outputCommentLayout?.suffixWidth ?? 1,
63
+ };
64
+ }
65
+ const expressionStart = skipWhitespace(text, container.start + 1);
66
+ const expressionEnd = trimWhitespaceEnd(text, container.start + 1, comment.start);
67
+ const removalEnd = Math.min(skipWhitespace(text, comment.end), container.end - 1);
68
+ return {
69
+ contentColumn,
70
+ markerColumn,
71
+ multilineIndent: '',
72
+ placement: 'trailing',
73
+ singleLineSuffixWidth: outputCommentLayout?.suffixWidth ?? 1,
74
+ trailingMove: {
75
+ insertAt: expressionStart,
76
+ removeEnd: removalEnd,
77
+ removeStart: expressionEnd,
78
+ },
79
+ };
80
+ }
81
+ if (!hasExpressionBeforeComment) {
82
+ if (isStandaloneBlockComment(text, comment)) {
83
+ return {
84
+ contentColumn,
85
+ markerColumn,
86
+ multilineIndent: '',
87
+ placement: 'standalone',
88
+ preserveMultiline: getLineStart(text, comment.start) !== getLineStart(text, comment.end),
89
+ singleLineSuffixWidth: outputCommentLayout?.suffixWidth ?? 0,
90
+ };
91
+ }
92
+ const expressionStart = skipWhitespace(text, comment.end);
93
+ return {
94
+ contentColumn,
95
+ leadingMove: {
96
+ removeEnd: expressionStart,
97
+ removeStart: comment.end,
98
+ },
99
+ markerColumn,
100
+ multilineIndent: '',
101
+ placement: 'standalone',
102
+ singleLineSuffixWidth: outputCommentLayout?.suffixWidth ?? getColumns(text.slice(comment.end, container.end), tabWidth),
103
+ };
104
+ }
105
+ return { placement: 'inline' };
106
+ }
107
+ function getJsxExpressionContainerOutputColumn(text, container, tabWidth) {
108
+ const linePrefix = getLinePrefix(text, container.start);
109
+ if (/^[ \t]*$/u.test(linePrefix)) {
110
+ return getColumns(linePrefix, tabWidth);
111
+ }
112
+ const lineIndent = getLeadingIndent(linePrefix);
113
+ return getColumns(lineIndent, tabWidth) + tabWidth;
114
+ }
@@ -0,0 +1,6 @@
1
+ import type { CommentRange } from './comment-ranges.js';
2
+ export type LineCommentGroup = {
3
+ comments: CommentRange[];
4
+ endIndex: number;
5
+ };
6
+ export declare function collectLineCommentGroup(text: string, comments: CommentRange[], startIndex: number, tabWidth: number): LineCommentGroup;
@@ -0,0 +1,28 @@
1
+ import { shouldSkipLineComment } from './comment-eligibility.js';
2
+ import { areCommentsOnAdjacentLines, isStandaloneLineComment } from './comment-location.js';
3
+ import { getColumnAt } from '../utils/display-width.js';
4
+ export function collectLineCommentGroup(text, comments, startIndex, tabWidth) {
5
+ const firstComment = comments[startIndex];
6
+ if (firstComment === undefined) {
7
+ return { comments: [], endIndex: startIndex };
8
+ }
9
+ const group = [firstComment];
10
+ const markerColumn = getColumnAt(text, firstComment.start, tabWidth);
11
+ let endIndex = startIndex;
12
+ let previousComment = firstComment;
13
+ while (endIndex + 1 < comments.length) {
14
+ const nextComment = comments[endIndex + 1];
15
+ if (nextComment === undefined ||
16
+ nextComment.kind !== 'line' ||
17
+ !isStandaloneLineComment(text, nextComment) ||
18
+ shouldSkipLineComment(text, nextComment) ||
19
+ !areCommentsOnAdjacentLines(text, previousComment, nextComment) ||
20
+ markerColumn !== getColumnAt(text, nextComment.start, tabWidth)) {
21
+ break;
22
+ }
23
+ group.push(nextComment);
24
+ previousComment = nextComment;
25
+ endIndex += 1;
26
+ }
27
+ return { comments: group, endIndex };
28
+ }
@@ -0,0 +1,9 @@
1
+ import type { CommentEntry, CommentRange } from './comment-ranges.js';
2
+ import type { SourceRange } from '../utils/ast.js';
3
+ export declare function neutralizePrettierIgnoreForIgnoredComments<T>(text: string, ast: T): T;
4
+ export declare function getNeutralizedPrettierIgnoreOriginalText(comment: unknown): string | undefined;
5
+ export declare function collectPrettierIgnoredLineRanges(text: string, ast: unknown, comments: CommentEntry[]): SourceRange[];
6
+ export declare function isCommentInIgnoredLineRange(comment: CommentRange, ignoredLineRange: SourceRange | undefined): boolean;
7
+ export declare function isPrettierIgnoredBlockComment(text: string, comments: CommentEntry[], index: number): boolean;
8
+ export declare function isPrettierIgnoredStandaloneLineComment(text: string, comments: CommentEntry[], index: number): boolean;
9
+ export declare function isPrettierIgnoredTrailingLineComment(text: string, comments: CommentEntry[], index: number): boolean;
@@ -0,0 +1,239 @@
1
+ import { getCommentBody } from './comment-body.js';
2
+ import { isPrettierIgnoreComment } from './comment-directives.js';
3
+ import { shouldSkipBlockComment, shouldSkipLineComment } from './comment-eligibility.js';
4
+ import { areCommentsOnAdjacentLines, isCommentAdjacentBeforeIndex, isStandaloneBlockComment, isStandaloneComment, isStandaloneLineComment, } from './comment-location.js';
5
+ import { collectCommentEntries } from './comment-ranges.js';
6
+ import { collectAstNodeRangesByStart, getAstNodeRange, visitAstNodes } from '../utils/ast.js';
7
+ import { getLineEnd, getLineStart } from '../utils/source-lines.js';
8
+ import { isRecord } from '../utils/type-guards.js';
9
+ import { skipWhitespace } from '../utils/whitespace.js';
10
+ const NEUTRALIZED_PRETTIER_IGNORE_COMMENT = 'prettier-ignore wrap-comments';
11
+ const neutralizedPrettierIgnoreOriginalTextKey = Symbol('neutralizedPrettierIgnoreOriginalText');
12
+ export function neutralizePrettierIgnoreForIgnoredComments(text, ast) {
13
+ const comments = collectCommentEntries(ast, text);
14
+ for (let index = 0; index < comments.length; index += 1) {
15
+ const entry = comments[index];
16
+ const previousEntry = comments[index - 1];
17
+ const shouldNeutralize = entry !== undefined &&
18
+ previousEntry !== undefined &&
19
+ ((isPrettierIgnoredBlockComment(text, comments, index) && !shouldSkipBlockComment(text, entry.range)) ||
20
+ (isPrettierIgnoredStandaloneLineComment(text, comments, index) && !shouldSkipLineComment(text, entry.range)));
21
+ if (shouldNeutralize) {
22
+ if (previousEntry.range.kind === 'block') {
23
+ const originalText = text.slice(previousEntry.range.start, previousEntry.range.end);
24
+ previousEntry.raw[neutralizedPrettierIgnoreOriginalTextKey] =
25
+ originalText;
26
+ }
27
+ previousEntry.raw.value = NEUTRALIZED_PRETTIER_IGNORE_COMMENT;
28
+ }
29
+ }
30
+ return ast;
31
+ }
32
+ export function getNeutralizedPrettierIgnoreOriginalText(comment) {
33
+ if (!isRecord(comment)) {
34
+ return undefined;
35
+ }
36
+ const originalText = comment[neutralizedPrettierIgnoreOriginalTextKey];
37
+ return typeof originalText === 'string' ? originalText : undefined;
38
+ }
39
+ export function collectPrettierIgnoredLineRanges(text, ast, comments) {
40
+ const nodeRangesByStart = collectAstNodeRangesByStart(ast);
41
+ const jsxTargetRangesByIgnoreStart = collectJsxPrettierIgnoreTargetRanges(text, ast, comments);
42
+ const ignoredLineRanges = [];
43
+ for (let index = 0; index < comments.length; index += 1) {
44
+ const comment = comments[index]?.range;
45
+ const jsxTargetRange = comment === undefined ? undefined : jsxTargetRangesByIgnoreStart.get(comment.start);
46
+ if (comment === undefined ||
47
+ (!isStandaloneComment(text, comment) && jsxTargetRange === undefined) ||
48
+ !isPrettierIgnoreComment(getCommentBody(text, comment))) {
49
+ continue;
50
+ }
51
+ let targetRange = jsxTargetRange;
52
+ if (targetRange === undefined) {
53
+ const targetStart = getPrettierIgnoreTargetStart(text, comments, index);
54
+ if (targetStart === undefined) {
55
+ continue;
56
+ }
57
+ targetRange = nodeRangesByStart.get(targetStart);
58
+ }
59
+ if (targetRange === undefined) {
60
+ continue;
61
+ }
62
+ appendMergedRange(ignoredLineRanges, {
63
+ end: getLineEnd(text, targetRange.end),
64
+ start: getLineStart(text, targetRange.start),
65
+ });
66
+ }
67
+ return ignoredLineRanges;
68
+ }
69
+ export function isCommentInIgnoredLineRange(comment, ignoredLineRange) {
70
+ return (ignoredLineRange !== undefined && comment.start >= ignoredLineRange.start && comment.start < ignoredLineRange.end);
71
+ }
72
+ export function isPrettierIgnoredBlockComment(text, comments, index) {
73
+ const comment = comments[index]?.range;
74
+ const previousComment = comments[index - 1]?.range;
75
+ if (comment === undefined ||
76
+ comment.kind !== 'block' ||
77
+ !isStandaloneBlockComment(text, comment) ||
78
+ previousComment === undefined) {
79
+ return false;
80
+ }
81
+ if (!isStandaloneComment(text, previousComment) || !areCommentsOnAdjacentLines(text, previousComment, comment)) {
82
+ return false;
83
+ }
84
+ return isPrettierIgnoreComment(getCommentBody(text, previousComment));
85
+ }
86
+ export function isPrettierIgnoredStandaloneLineComment(text, comments, index) {
87
+ const comment = comments[index]?.range;
88
+ const previousComment = comments[index - 1]?.range;
89
+ if (comment === undefined ||
90
+ comment.kind !== 'line' ||
91
+ !isStandaloneLineComment(text, comment) ||
92
+ previousComment === undefined ||
93
+ previousComment.kind !== 'line') {
94
+ return false;
95
+ }
96
+ if (!isStandaloneComment(text, previousComment) || !areCommentsOnAdjacentLines(text, previousComment, comment)) {
97
+ return false;
98
+ }
99
+ return isPrettierIgnoreComment(getCommentBody(text, previousComment));
100
+ }
101
+ export function isPrettierIgnoredTrailingLineComment(text, comments, index) {
102
+ const comment = comments[index]?.range;
103
+ if (comment === undefined || comment.kind !== 'line' || isStandaloneLineComment(text, comment)) {
104
+ return false;
105
+ }
106
+ let cursor = getLineStart(text, comment.start);
107
+ for (let previousIndex = index - 1; previousIndex >= 0; previousIndex -= 1) {
108
+ const previousComment = comments[previousIndex]?.range;
109
+ if (previousComment !== undefined && previousComment.end > cursor) {
110
+ continue;
111
+ }
112
+ if (previousComment === undefined || !isStandaloneComment(text, previousComment)) {
113
+ return false;
114
+ }
115
+ if (!isCommentAdjacentBeforeIndex(text, previousComment, cursor)) {
116
+ return false;
117
+ }
118
+ const body = getCommentBody(text, previousComment);
119
+ if (isPrettierIgnoreComment(body)) {
120
+ return true;
121
+ }
122
+ if (!isSkippableCommentBetweenIgnoreAndTarget(text, previousComment)) {
123
+ return false;
124
+ }
125
+ cursor = getLineStart(text, previousComment.start);
126
+ }
127
+ return false;
128
+ }
129
+ function collectJsxPrettierIgnoreTargetRanges(text, ast, comments) {
130
+ const commentsByStart = new Map(comments.map((entry) => [entry.range.start, entry.range]));
131
+ const targetRangesByIgnoreStart = new Map();
132
+ visitAstNodes(ast, (node) => {
133
+ if (!isJsxElementOrFragment(node)) {
134
+ return;
135
+ }
136
+ const children = node['children'];
137
+ if (!Array.isArray(children)) {
138
+ return;
139
+ }
140
+ for (let ignoreIndex = 0; ignoreIndex < children.length; ignoreIndex += 1) {
141
+ const ignoreContainer = children[ignoreIndex];
142
+ if (!isRecord(ignoreContainer)) {
143
+ continue;
144
+ }
145
+ const ignoreComment = getCommentOnlyJsxExpressionContainerComment(text, ignoreContainer, commentsByStart);
146
+ if (ignoreComment === undefined || !isPrettierIgnoreComment(getCommentBody(text, ignoreComment))) {
147
+ continue;
148
+ }
149
+ const target = getNextSignificantJsxChild(text, children, ignoreIndex);
150
+ if (target === undefined || !isJsxElementOrFragment(target)) {
151
+ continue;
152
+ }
153
+ const targetRange = getAstNodeRange(target);
154
+ if (targetRange !== undefined) {
155
+ targetRangesByIgnoreStart.set(ignoreComment.start, targetRange);
156
+ }
157
+ }
158
+ });
159
+ return targetRangesByIgnoreStart;
160
+ }
161
+ function getNextSignificantJsxChild(text, children, ignoreIndex) {
162
+ for (let index = ignoreIndex + 1; index < children.length; index += 1) {
163
+ const child = children[index];
164
+ if (!isRecord(child)) {
165
+ return undefined;
166
+ }
167
+ if (isMultilineWhitespaceJsxText(text, child)) {
168
+ continue;
169
+ }
170
+ return child;
171
+ }
172
+ return undefined;
173
+ }
174
+ function isMultilineWhitespaceJsxText(text, node) {
175
+ if (node['type'] !== 'JSXText') {
176
+ return false;
177
+ }
178
+ const range = getAstNodeRange(node);
179
+ if (range === undefined) {
180
+ return false;
181
+ }
182
+ const raw = text.slice(range.start, range.end);
183
+ return raw.includes('\n') && /^[ \t\r\n]*$/u.test(raw);
184
+ }
185
+ function getCommentOnlyJsxExpressionContainerComment(text, container, commentsByStart) {
186
+ const expression = container['expression'];
187
+ if (container['type'] !== 'JSXExpressionContainer' ||
188
+ !isRecord(expression) ||
189
+ expression['type'] !== 'JSXEmptyExpression') {
190
+ return undefined;
191
+ }
192
+ const range = getAstNodeRange(container);
193
+ if (range === undefined || text[range.start] !== '{' || text[range.end - 1] !== '}') {
194
+ return undefined;
195
+ }
196
+ const commentStart = skipWhitespace(text, range.start + 1);
197
+ const comment = commentsByStart.get(commentStart);
198
+ if (comment === undefined || comment.kind !== 'block' || skipWhitespace(text, comment.end) !== range.end - 1) {
199
+ return undefined;
200
+ }
201
+ return comment;
202
+ }
203
+ function isJsxElementOrFragment(node) {
204
+ return node['type'] === 'JSXElement' || node['type'] === 'JSXFragment';
205
+ }
206
+ function getPrettierIgnoreTargetStart(text, comments, ignoreCommentIndex) {
207
+ const ignoreComment = comments[ignoreCommentIndex]?.range;
208
+ if (ignoreComment === undefined) {
209
+ return undefined;
210
+ }
211
+ let cursor = ignoreComment.end;
212
+ for (let index = ignoreCommentIndex + 1; index < comments.length; index += 1) {
213
+ cursor = skipWhitespace(text, cursor);
214
+ const comment = comments[index]?.range;
215
+ if (comment === undefined || comment.start !== cursor) {
216
+ break;
217
+ }
218
+ if (!isStandaloneComment(text, comment) || !isSkippableCommentBetweenIgnoreAndTarget(text, comment)) {
219
+ return undefined;
220
+ }
221
+ cursor = comment.end;
222
+ }
223
+ const targetStart = skipWhitespace(text, cursor);
224
+ return targetStart >= text.length ? undefined : targetStart;
225
+ }
226
+ function isSkippableCommentBetweenIgnoreAndTarget(text, comment) {
227
+ if (comment.kind === 'block') {
228
+ return shouldSkipBlockComment(text, comment);
229
+ }
230
+ return shouldSkipLineComment(text, comment) && !isPrettierIgnoreComment(getCommentBody(text, comment));
231
+ }
232
+ function appendMergedRange(ranges, range) {
233
+ const previousRange = ranges[ranges.length - 1];
234
+ if (previousRange === undefined || range.start > previousRange.end) {
235
+ ranges.push(range);
236
+ return;
237
+ }
238
+ previousRange.end = Math.max(previousRange.end, range.end);
239
+ }
@@ -0,0 +1,18 @@
1
+ import type { CommentEntry } from './comment-ranges.js';
2
+ import type { JsxExpressionContainerRange } from './jsx-expression-layout.js';
3
+ export type PrinterLayoutSource = {
4
+ ast: unknown;
5
+ text: string;
6
+ };
7
+ export type PrinterCommentLayout = {
8
+ lineIndentColumn: number;
9
+ lineStart: number;
10
+ lineWidth: number;
11
+ markerColumn: number;
12
+ suffixWidth: number;
13
+ };
14
+ export type PrinterLayout = {
15
+ comments: Array<PrinterCommentLayout | undefined>;
16
+ jsxCommentMarkerColumns: Array<number | undefined>;
17
+ };
18
+ export declare function getPrinterLayout(text: string, commentEntries: CommentEntry[], jsxExpressionContainers: JsxExpressionContainerRange[], source: PrinterLayoutSource | undefined, tabWidth: number): PrinterLayout;
@@ -0,0 +1,65 @@
1
+ import { collectCommentEntries } from './comment-ranges.js';
2
+ import { collectJsxExpressionContainerRanges, getPrintedJsxCommentMarkerColumn } from './jsx-expression-layout.js';
3
+ import { getColumns } from '../utils/display-width.js';
4
+ import { getLeadingIndent } from '../utils/indentation.js';
5
+ import { getLineEnd, getLineStart } from '../utils/source-lines.js';
6
+ export function getPrinterLayout(text, commentEntries, jsxExpressionContainers, source, tabWidth) {
7
+ if (source === undefined) {
8
+ return {
9
+ comments: [],
10
+ jsxCommentMarkerColumns: [],
11
+ };
12
+ }
13
+ const outputCommentEntries = collectCommentEntries(source.ast, source.text);
14
+ const alignedOutputComments = alignOutputComments(text, commentEntries, source.text, outputCommentEntries);
15
+ const outputJsxExpressionContainers = collectJsxExpressionContainerRanges(source.ast);
16
+ const jsxCommentMarkerColumns = outputJsxExpressionContainers.length === jsxExpressionContainers.length
17
+ ? outputJsxExpressionContainers.map((container) => getPrintedJsxCommentMarkerColumn(source.text, container, tabWidth))
18
+ : [];
19
+ return {
20
+ comments: alignedOutputComments.map((comment) => comment === undefined ? undefined : getPrinterCommentLayout(source.text, comment.range, tabWidth)),
21
+ jsxCommentMarkerColumns,
22
+ };
23
+ }
24
+ function alignOutputComments(text, comments, outputText, outputComments) {
25
+ if (comments.length === outputComments.length &&
26
+ comments.every((comment, index) => comment.range.kind === outputComments[index]?.range.kind)) {
27
+ return outputComments;
28
+ }
29
+ const alignedComments = [];
30
+ let outputIndex = 0;
31
+ for (const comment of comments) {
32
+ const raw = normalizeCommentForMatching(text.slice(comment.range.start, comment.range.end));
33
+ let matchingComment;
34
+ while (outputIndex < outputComments.length) {
35
+ const candidate = outputComments[outputIndex];
36
+ outputIndex += 1;
37
+ if (candidate !== undefined &&
38
+ candidate.range.kind === comment.range.kind &&
39
+ normalizeCommentForMatching(outputText.slice(candidate.range.start, candidate.range.end)) === raw) {
40
+ matchingComment = candidate;
41
+ break;
42
+ }
43
+ }
44
+ alignedComments.push(matchingComment);
45
+ }
46
+ return alignedComments;
47
+ }
48
+ function normalizeCommentForMatching(raw) {
49
+ return raw.replace(/\r\n?/gu, '\n');
50
+ }
51
+ function getPrinterCommentLayout(text, comment, tabWidth) {
52
+ const lineStart = getLineStart(text, comment.start);
53
+ const lineEnd = getLineEnd(text, comment.end);
54
+ const linePrefix = text.slice(lineStart, comment.start);
55
+ const lineIndent = getLeadingIndent(linePrefix);
56
+ const lineText = text.slice(lineStart, lineEnd).replace(/[ \t]+$/u, '');
57
+ const suffix = text.slice(comment.end, lineEnd).replace(/[ \t]+$/u, '');
58
+ return {
59
+ lineIndentColumn: getColumns(lineIndent, tabWidth),
60
+ lineStart,
61
+ lineWidth: getColumns(lineText, tabWidth),
62
+ markerColumn: getColumns(linePrefix, tabWidth),
63
+ suffixWidth: getColumns(suffix, tabWidth),
64
+ };
65
+ }
@@ -1,12 +1,16 @@
1
- import type { CommentRange, Replacement, WrapOptions } from '../shared/types.js';
1
+ import type { CommentRange } from './comment-ranges.js';
2
+ import type { Replacement } from '../utils/replacements.js';
3
+ import type { WrapOptions } from '../utils/wrap-options.js';
2
4
  export type BlockCommentLayout = {
3
5
  contentColumn?: number;
4
6
  leadingMove?: {
5
7
  removeEnd: number;
6
8
  removeStart: number;
7
9
  };
10
+ markerColumn?: number;
8
11
  multilineIndent?: string;
9
12
  placement: 'inline' | 'standalone' | 'trailing';
13
+ preserveMultiline?: boolean;
10
14
  singleLineSuffixWidth?: number;
11
15
  trailingMove?: {
12
16
  insertAt: number;
@@ -1,18 +1,18 @@
1
- import { hasPreserveCommentMarker, isDirectiveComment, normalizeBlockCommentBody } from './core.js';
2
- import { formatMarkdownLines } from '../shared/markdown.js';
3
- import { getAvailableContentWidth, getPrintWidth, getTabWidth } from '../shared/options.js';
4
- import { getColumnAt, getColumns, getLinePrefix, getPreferredNewline, isStandaloneBlockComment, } from '../shared/text.js';
1
+ import { normalizeBlockCommentBody } from './comment-body.js';
2
+ import { shouldSkipBlockComment } from './comment-eligibility.js';
3
+ import { isStandaloneBlockComment } from './comment-location.js';
4
+ import { getColumnAt, getColumns } from '../utils/display-width.js';
5
+ import { formatMarkdownLines } from '../utils/format-markdown.js';
6
+ import { getLinePrefix, getPreferredNewline } from '../utils/source-lines.js';
7
+ import { getAvailableContentWidth, getPrintWidth, getTabWidth } from '../utils/wrap-options.js';
5
8
  export async function wrapBlockComment(text, comment, options, layout = getDefaultBlockCommentLayout(text, comment)) {
6
- const raw = text.slice(comment.start, comment.end);
7
- if (raw.startsWith('/**') || hasPreserveCommentMarker(raw)) {
9
+ if (shouldSkipBlockComment(text, comment)) {
8
10
  return undefined;
9
11
  }
12
+ const raw = text.slice(comment.start, comment.end);
10
13
  const markdown = normalizeBlockCommentBody(raw);
11
- if (markdown.trim() === '' || isDirectiveComment(markdown)) {
12
- return undefined;
13
- }
14
14
  const tabWidth = getTabWidth(options);
15
- const markerColumn = getColumnAt(text, comment.start, tabWidth);
15
+ const markerColumn = layout.markerColumn ?? getColumnAt(text, comment.start, tabWidth);
16
16
  const availableWidth = getAvailableContentWidth(options, layout.contentColumn ?? markerColumn + 3);
17
17
  const formattedLines = await formatMarkdownLines(markdown, availableWidth, options);
18
18
  const replacement = buildBlockReplacement(text, comment, formattedLines, options, layout);
@@ -33,11 +33,13 @@ export async function wrapBlockComment(text, comment, options, layout = getDefau
33
33
  }
34
34
  function buildBlockReplacement(text, comment, formattedLines, options, layout) {
35
35
  const tabWidth = getTabWidth(options);
36
- const markerColumn = getColumnAt(text, comment.start, tabWidth);
36
+ const markerColumn = layout.markerColumn ?? getColumnAt(text, comment.start, tabWidth);
37
37
  const singleLine = `/* ${formattedLines.join(' ')} */`;
38
38
  const singleLineWidth = getColumns(singleLine, tabWidth);
39
39
  const singleLineSuffixWidth = layout.singleLineSuffixWidth ?? 0;
40
- if (formattedLines.length === 1 && markerColumn + singleLineWidth + singleLineSuffixWidth <= getPrintWidth(options)) {
40
+ if (layout.preserveMultiline !== true &&
41
+ formattedLines.length === 1 &&
42
+ markerColumn + singleLineWidth + singleLineSuffixWidth <= getPrintWidth(options)) {
41
43
  return singleLine;
42
44
  }
43
45
  if (layout.placement === 'inline') {
@@ -46,12 +48,13 @@ function buildBlockReplacement(text, comment, formattedLines, options, layout) {
46
48
  const newline = getPreferredNewline(text, options);
47
49
  const indent = layout.multilineIndent ?? getLinePrefix(text, comment.start);
48
50
  const replacementText = buildMultilineBlockReplacement(formattedLines, newline, indent);
51
+ const replacementTextWithNewline = [replacementText, ''].join(newline);
49
52
  if (layout.trailingMove !== undefined) {
50
53
  return [
51
54
  {
52
55
  end: layout.trailingMove.insertAt,
53
56
  start: layout.trailingMove.insertAt,
54
- text: `${replacementText}${newline}`,
57
+ text: replacementTextWithNewline,
55
58
  },
56
59
  {
57
60
  end: layout.trailingMove.removeEnd,
@@ -65,7 +68,7 @@ function buildBlockReplacement(text, comment, formattedLines, options, layout) {
65
68
  {
66
69
  end: comment.end,
67
70
  start: comment.start,
68
- text: `${replacementText}${newline}`,
71
+ text: replacementTextWithNewline,
69
72
  },
70
73
  {
71
74
  end: layout.leadingMove.removeEnd,
@@ -78,7 +81,7 @@ function buildBlockReplacement(text, comment, formattedLines, options, layout) {
78
81
  }
79
82
  function buildMultilineBlockReplacement(formattedLines, newline, indent) {
80
83
  const body = formattedLines.map((line) => `${indent} *${line.length === 0 ? '' : ` ${line}`}`).join(newline);
81
- return `/*${newline}${body}${newline}${indent} */`;
84
+ return ['/*', body, `${indent} */`].join(newline);
82
85
  }
83
86
  function getDefaultBlockCommentLayout(text, comment) {
84
87
  return {
@@ -0,0 +1,9 @@
1
+ import type { PrinterLayoutSource } from './printer-layout.js';
2
+ import type { JsxBlockCommentRewrite } from '../plugin/jsx-comment-rewrite-metadata.js';
3
+ import type { WrapOptions } from '../utils/wrap-options.js';
4
+ export type WrapCommentsResult = {
5
+ jsxBlockCommentRewrites: JsxBlockCommentRewrite[];
6
+ text: string;
7
+ };
8
+ export declare function wrapComments<T>(text: string, ast: T, options: WrapOptions, printerLayoutSource?: PrinterLayoutSource): Promise<string>;
9
+ export declare function wrapCommentsWithMetadata<T>(text: string, ast: T, options: WrapOptions, printerLayoutSource?: PrinterLayoutSource): Promise<WrapCommentsResult>;