@aforemendude/prettier-plugin-wrap-comments 1.0.2 → 1.0.3
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/README.md +51 -26
- package/dist/comments/block.js +2 -2
- package/dist/comments/core.d.ts +1 -0
- package/dist/comments/core.js +46 -1
- package/dist/comments/line.js +2 -2
- package/dist/shared/text.js +13 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
# @aforemendude/prettier-plugin-wrap-comments
|
|
2
2
|
|
|
3
|
-
A Prettier plugin that wraps non-JSDoc JavaScript and TypeScript comments as Markdown. It uses
|
|
4
|
-
column to calculate the available content width, so nested comments wrap more narrowly than top-level comments.
|
|
3
|
+
A Prettier plugin that wraps non-JSDoc JavaScript and TypeScript comments as Markdown. It uses each comment marker's
|
|
4
|
+
real column to calculate the available content width, so nested comments wrap more narrowly than top-level comments.
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
- Node.js 18 or newer
|
|
9
|
+
- Prettier 3 or newer
|
|
5
10
|
|
|
6
11
|
## Install
|
|
7
12
|
|
|
@@ -27,8 +32,17 @@ npx prettier --write .
|
|
|
27
32
|
|
|
28
33
|
## Behavior
|
|
29
34
|
|
|
30
|
-
The plugin wraps
|
|
31
|
-
Prettier
|
|
35
|
+
The plugin wraps comments for Prettier's `babel`, `babel-ts`, and `typescript` parsers. It runs during parser
|
|
36
|
+
preprocessing: the underlying Prettier parser preprocesses and parses the source first, the plugin rewrites eligible
|
|
37
|
+
comments from that parsed comment list, and Prettier then formats the rewritten source with its built-in JavaScript and
|
|
38
|
+
TypeScript printers. If the parser cannot parse the preprocessed source, the plugin leaves the source unchanged.
|
|
39
|
+
|
|
40
|
+
Comment text is normalized and reflowed with Prettier's Markdown parser. The available content width is based on
|
|
41
|
+
Prettier's `printWidth` minus the column where the comment text starts. `tabWidth`, `useTabs`, and `endOfLine` are used
|
|
42
|
+
when measuring and rebuilding comments.
|
|
43
|
+
|
|
44
|
+
Standalone `//` comments are wrapped in place. Adjacent standalone line comments are combined and reflowed as one
|
|
45
|
+
Markdown block when they are directly next to each other and their `//` markers start in the same column.
|
|
32
46
|
|
|
33
47
|
```ts
|
|
34
48
|
function example() {
|
|
@@ -38,18 +52,39 @@ function example() {
|
|
|
38
52
|
}
|
|
39
53
|
```
|
|
40
54
|
|
|
41
|
-
|
|
55
|
+
Trailing `//` comments stay in place when the full source line fits within `printWidth`. If the source line is too long,
|
|
56
|
+
the comment is moved above the code and wrapped using the code line's indentation.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
function example() {
|
|
60
|
+
// This trailing comment moved above the statement because the original line
|
|
61
|
+
// was too long.
|
|
62
|
+
const value = 1;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Non-JSDoc `/* ... */` comments are also normalized as Markdown. A block comment may stay on one line if the normalized
|
|
67
|
+
comment fits within `printWidth`; otherwise, only standalone block comments are expanded into star-prefixed blocks. Long
|
|
68
|
+
inline block comments are left unchanged when they cannot fit on one line.
|
|
42
69
|
|
|
43
70
|
```ts
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
71
|
+
if (ready) {
|
|
72
|
+
/*
|
|
73
|
+
* This block comment is wrapped with the nested indentation included in the
|
|
74
|
+
* available width calculation.
|
|
75
|
+
*/
|
|
76
|
+
run();
|
|
77
|
+
}
|
|
47
78
|
```
|
|
48
79
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
80
|
+
The plugin leaves these comments unchanged:
|
|
81
|
+
|
|
82
|
+
- JSDoc comments that start with `/**`
|
|
83
|
+
- bang-preserved comments that start with `/*!` or `//!`
|
|
84
|
+
- TypeScript-style triple-slash line comments that start with `///`
|
|
85
|
+
- empty comment bodies
|
|
86
|
+
- directive comments such as `@license`, `@preserve`, JSX and TypeScript pragmas, source map directives, `#__PURE__`,
|
|
87
|
+
`@__PURE__`, lint/coverage/formatter directives, `vite-ignore`, and webpack magic comments
|
|
53
88
|
|
|
54
89
|
## Supported Parsers
|
|
55
90
|
|
|
@@ -61,19 +96,9 @@ and wrapped there.
|
|
|
61
96
|
|
|
62
97
|
```sh
|
|
63
98
|
npm install
|
|
64
|
-
npm run check
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
## Publishing
|
|
68
|
-
|
|
69
|
-
The npm package name is `@aforemendude/prettier-plugin-wrap-comments`.
|
|
70
|
-
|
|
71
|
-
Before publishing, make sure the version in `package.json` has been updated, then run:
|
|
72
|
-
|
|
73
|
-
```sh
|
|
74
|
-
npm run check
|
|
75
|
-
npm publish --access public
|
|
99
|
+
npm run format:check
|
|
100
|
+
npm run test
|
|
76
101
|
```
|
|
77
102
|
|
|
78
|
-
|
|
79
|
-
|
|
103
|
+
`npm run test` builds `dist` before running the Node test suite. `npm run verify` runs `npm install`,
|
|
104
|
+
`npm run format:check`, and `npm run test`.
|
package/dist/comments/block.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isDirectiveComment, normalizeBlockCommentBody } from './core.js';
|
|
1
|
+
import { hasPreserveCommentMarker, isDirectiveComment, normalizeBlockCommentBody } from './core.js';
|
|
2
2
|
import { formatMarkdownLines } from '../shared/markdown.js';
|
|
3
3
|
import { getAvailableContentWidth, getPrintWidth, getTabWidth } from '../shared/options.js';
|
|
4
4
|
import { getColumnAt, getColumns, getLinePrefix, getPreferredNewline, isStandaloneBlockComment, } from '../shared/text.js';
|
|
5
5
|
export async function wrapBlockComment(text, comment, options) {
|
|
6
6
|
const raw = text.slice(comment.start, comment.end);
|
|
7
|
-
if (raw.startsWith('/**')) {
|
|
7
|
+
if (raw.startsWith('/**') || hasPreserveCommentMarker(raw)) {
|
|
8
8
|
return undefined;
|
|
9
9
|
}
|
|
10
10
|
const markdown = normalizeBlockCommentBody(raw);
|
package/dist/comments/core.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function toCommentRange(comment: RawComment, text: string): Comme
|
|
|
4
4
|
export declare function normalizeLineCommentBody(rawBody: string): string;
|
|
5
5
|
export declare function normalizeBlockCommentBody(rawComment: string): string;
|
|
6
6
|
export declare function isDirectiveComment(body: string): boolean;
|
|
7
|
+
export declare function hasPreserveCommentMarker(rawComment: string): boolean;
|
package/dist/comments/core.js
CHANGED
|
@@ -63,8 +63,53 @@ export function normalizeBlockCommentBody(rawComment) {
|
|
|
63
63
|
})
|
|
64
64
|
.join('\n');
|
|
65
65
|
}
|
|
66
|
+
const PRAGMA_DIRECTIVE_COMMENT_PATTERNS = [
|
|
67
|
+
/^@(?:license|preserve)\b/u,
|
|
68
|
+
/^@(?:jsxFrag|jsxImportSource|jsxRuntime|jsx)\b/u,
|
|
69
|
+
/^@(?:ts-check|ts-expect-error|ts-ignore|ts-nocheck)\b/u,
|
|
70
|
+
/^[@#]__(?:NO_SIDE_EFFECTS|PURE)__\b/u,
|
|
71
|
+
];
|
|
72
|
+
const SOURCE_MAP_DIRECTIVE_COMMENT_PATTERNS = [
|
|
73
|
+
/^[#@][ \t]*sourceMappingURL=/u,
|
|
74
|
+
/^[#@][ \t]*sourceURL=/u,
|
|
75
|
+
/^sourceMappingURL=/u,
|
|
76
|
+
/^sourceURL=/u,
|
|
77
|
+
];
|
|
78
|
+
const TOOL_DIRECTIVE_COMMENT_PATTERNS = [
|
|
79
|
+
/^biome-ignore\b/u,
|
|
80
|
+
/^c8\b/u,
|
|
81
|
+
/^deno-lint-ignore\b/u,
|
|
82
|
+
/^eslint\b/u,
|
|
83
|
+
/^eslint-/u,
|
|
84
|
+
/^exported\b/u,
|
|
85
|
+
/^globals?\b/u,
|
|
86
|
+
/^istanbul\b/u,
|
|
87
|
+
/^jshint\b/u,
|
|
88
|
+
/^nyc\b/u,
|
|
89
|
+
/^oxlint\b/u,
|
|
90
|
+
/^prettier-ignore\b/u,
|
|
91
|
+
/^prettier-ignore-start\b/u,
|
|
92
|
+
/^prettier-ignore-end\b/u,
|
|
93
|
+
/^stylelint\b/u,
|
|
94
|
+
/^tslint\b/u,
|
|
95
|
+
/^v8\b/u,
|
|
96
|
+
/^vite-ignore\b/u,
|
|
97
|
+
];
|
|
98
|
+
const BUNDLER_DIRECTIVE_COMMENT_PATTERNS = [
|
|
99
|
+
/^webpack(?:ChunkName|Exclude|Ignore|Include|Mode|Prefetch|Preload)\b/u,
|
|
100
|
+
];
|
|
101
|
+
const DIRECTIVE_COMMENT_PATTERNS = [
|
|
102
|
+
...PRAGMA_DIRECTIVE_COMMENT_PATTERNS,
|
|
103
|
+
...SOURCE_MAP_DIRECTIVE_COMMENT_PATTERNS,
|
|
104
|
+
...TOOL_DIRECTIVE_COMMENT_PATTERNS,
|
|
105
|
+
...BUNDLER_DIRECTIVE_COMMENT_PATTERNS,
|
|
106
|
+
];
|
|
66
107
|
export function isDirectiveComment(body) {
|
|
67
|
-
|
|
108
|
+
const normalizedBody = body.trimStart();
|
|
109
|
+
return DIRECTIVE_COMMENT_PATTERNS.some((pattern) => pattern.test(normalizedBody));
|
|
110
|
+
}
|
|
111
|
+
export function hasPreserveCommentMarker(rawComment) {
|
|
112
|
+
return rawComment.startsWith('/*!') || rawComment.startsWith('//!');
|
|
68
113
|
}
|
|
69
114
|
function isBlankLine(line) {
|
|
70
115
|
return line !== undefined && line.trim() === '';
|
package/dist/comments/line.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isDirectiveComment, normalizeLineCommentBody } from './core.js';
|
|
1
|
+
import { hasPreserveCommentMarker, isDirectiveComment, normalizeLineCommentBody } from './core.js';
|
|
2
2
|
import { formatMarkdownLines } from '../shared/markdown.js';
|
|
3
3
|
import { getAvailableContentWidth, getPrintWidth, getTabWidth } from '../shared/options.js';
|
|
4
4
|
import { getColumnAt, getColumns, getContinuationIndent, getLineEnd, getLinePrefix, getLineStart, getPreferredNewline, } from '../shared/text.js';
|
|
@@ -67,7 +67,7 @@ export async function wrapTrailingLineComment(text, comment, options) {
|
|
|
67
67
|
}
|
|
68
68
|
export function shouldSkipLineComment(text, comment) {
|
|
69
69
|
const raw = text.slice(comment.start, comment.end);
|
|
70
|
-
if (raw.startsWith('///')) {
|
|
70
|
+
if (raw.startsWith('///') || hasPreserveCommentMarker(raw)) {
|
|
71
71
|
return true;
|
|
72
72
|
}
|
|
73
73
|
return isDirectiveComment(normalizeLineCommentBody(raw.slice(2)));
|
package/dist/shared/text.js
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { getTabWidth } from './options.js';
|
|
2
2
|
export function applyReplacements(text, replacements) {
|
|
3
3
|
let result = text;
|
|
4
|
-
for (const replacement of
|
|
4
|
+
for (const replacement of getNonOverlappingReplacements(replacements).sort((left, right) => right.start - left.start)) {
|
|
5
5
|
result = result.slice(0, replacement.start) + replacement.text + result.slice(replacement.end);
|
|
6
6
|
}
|
|
7
7
|
return result;
|
|
8
8
|
}
|
|
9
|
+
function getNonOverlappingReplacements(replacements) {
|
|
10
|
+
return [...replacements]
|
|
11
|
+
.sort((left, right) => left.start - right.start || right.end - left.end)
|
|
12
|
+
.reduce((accepted, replacement) => {
|
|
13
|
+
const previous = accepted.at(-1);
|
|
14
|
+
if (previous === undefined || previous.end <= replacement.start) {
|
|
15
|
+
accepted.push(replacement);
|
|
16
|
+
return accepted;
|
|
17
|
+
}
|
|
18
|
+
return accepted;
|
|
19
|
+
}, []);
|
|
20
|
+
}
|
|
9
21
|
export function getPreferredNewline(text, options) {
|
|
10
22
|
if (options.endOfLine === 'crlf') {
|
|
11
23
|
return '\r\n';
|
package/package.json
CHANGED