Skip to content

Commit 02a2102

Browse files
author
Eli Skeggs
committed
feat: add require-asterisk-prefix rule
This rule checks that each line of the jsdoc comment starts with an asterisk. For composability with other rules, this does not check the alignment or indentation of the comment content. fix #199
1 parent 6014360 commit 02a2102

File tree

7 files changed

+181
-14
lines changed

7 files changed

+181
-14
lines changed

.README/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Finally, enable all of the rules that you would like to use.
4444
"jsdoc/check-examples": 1,
4545
"jsdoc/check-indentation": 1,
4646
"jsdoc/check-param-names": 1, // Recommended
47+
"jsdoc/require-asterisk-prefix": 1,
4748
"jsdoc/check-syntax": 1,
4849
"jsdoc/check-tag-names": 1, // Recommended
4950
"jsdoc/check-types": 1, // Recommended
@@ -337,6 +338,7 @@ only (e.g., to match `Array` if the type is `Array` vs. `Array.<string>`).
337338
{"gitdown": "include", "file": "./rules/newline-after-description.md"}
338339
{"gitdown": "include", "file": "./rules/no-types.md"}
339340
{"gitdown": "include", "file": "./rules/no-undefined-types.md"}
341+
{"gitdown": "include", "file": "./rules/require-asterisk-prefix.md"}
340342
{"gitdown": "include", "file": "./rules/require-description-complete-sentence.md"}
341343
{"gitdown": "include", "file": "./rules/require-description.md"}
342344
{"gitdown": "include", "file": "./rules/require-example.md"}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
### `require-asterisk-prefix`
2+
3+
Requires that each JSDoc line starts with an `*`.
4+
5+
#### Options
6+
7+
This rule allows one optional string argument. If it is `"always"` then a problem is raised when there is no asterisk prefix on a given jsdoc line. If it is `"never"` then a problem is raised when there is an asterisk present. The default value is `"always"`.
8+
9+
|||
10+
|---|---|
11+
|Context|everywhere|
12+
|Tags|N/a|

README.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ JSDoc linting rules for ESLint.
3434
* [`newline-after-description`](#eslint-plugin-jsdoc-rules-newline-after-description)
3535
* [`no-types`](#eslint-plugin-jsdoc-rules-no-types)
3636
* [`no-undefined-types`](#eslint-plugin-jsdoc-rules-no-undefined-types)
37+
* [`require-asterisk-prefix`](#eslint-plugin-jsdoc-rules-require-asterisk-prefix)
3738
* [`require-description-complete-sentence`](#eslint-plugin-jsdoc-rules-require-description-complete-sentence)
3839
* [`require-description`](#eslint-plugin-jsdoc-rules-require-description)
3940
* [`require-example`](#eslint-plugin-jsdoc-rules-require-example)
@@ -87,6 +88,7 @@ Finally, enable all of the rules that you would like to use.
8788
"jsdoc/check-examples": 1,
8889
"jsdoc/check-indentation": 1,
8990
"jsdoc/check-param-names": 1, // Recommended
91+
"jsdoc/require-asterisk-prefix": 1,
9092
"jsdoc/check-syntax": 1,
9193
"jsdoc/check-tag-names": 1, // Recommended
9294
"jsdoc/check-types": 1, // Recommended
@@ -5107,6 +5109,21 @@ function quux () {}
51075109
````
51085110
51095111
5112+
<a name="eslint-plugin-jsdoc-rules-require-asterisk-prefix"></a>
5113+
### <code>require-asterisk-prefix</code>
5114+
5115+
Requires that each JSDoc line starts with an `*`.
5116+
5117+
<a name="eslint-plugin-jsdoc-rules-require-asterisk-prefix-options-10"></a>
5118+
#### Options
5119+
5120+
This rule allows one optional string argument. If it is `"always"` then a problem is raised when there is no asterisk prefix on a given jsdoc line. If it is `"never"` then a problem is raised when there is an asterisk present. The default value is `"always"`.
5121+
5122+
|||
5123+
|---|---|
5124+
|Context|everywhere|
5125+
|Tags|N/a|
5126+
51105127
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence"></a>
51115128
### <code>require-description-complete-sentence</code>
51125129
@@ -5121,10 +5138,10 @@ tag descriptions are written in complete sentences, i.e.,
51215138
* A colon or semi-colon followed by two line breaks is still part of the
51225139
containing paragraph (unlike normal dual line breaks).
51235140
5124-
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-10"></a>
5141+
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-11"></a>
51255142
#### Options
51265143
5127-
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-10-tags-2"></a>
5144+
<a name="eslint-plugin-jsdoc-rules-require-description-complete-sentence-options-11-tags-2"></a>
51285145
##### <code>tags</code>
51295146
51305147
If you want additional tags to be checked for their descriptions, you may
@@ -5612,7 +5629,7 @@ Requires that all functions have a description.
56125629
`"tag"`) must have a non-empty description that explains the purpose of the
56135630
method.
56145631
5615-
<a name="eslint-plugin-jsdoc-rules-require-description-options-11"></a>
5632+
<a name="eslint-plugin-jsdoc-rules-require-description-options-12"></a>
56165633
#### Options
56175634
56185635
An options object may have any of the following properties:
@@ -5897,25 +5914,25 @@ Requires that all functions have examples.
58975914
* All functions must have one or more `@example` tags.
58985915
* Every example tag must have a non-empty description that explains the method's usage.
58995916
5900-
<a name="eslint-plugin-jsdoc-rules-require-example-options-12"></a>
5917+
<a name="eslint-plugin-jsdoc-rules-require-example-options-13"></a>
59015918
#### Options
59025919
59035920
This rule has an object option.
59045921
5905-
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-exemptedby"></a>
5922+
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-exemptedby"></a>
59065923
##### <code>exemptedBy</code>
59075924
59085925
Array of tags (e.g., `['type']`) whose presence on the document
59095926
block avoids the need for an `@example`. Defaults to an empty array.
59105927
5911-
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-avoidexampleonconstructors"></a>
5928+
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-avoidexampleonconstructors"></a>
59125929
##### <code>avoidExampleOnConstructors</code>
59135930
59145931
Set to `true` to avoid the need for an example on a constructor (whether
59155932
indicated as such by a jsdoc tag or by being within an ES6 `class`).
59165933
Defaults to `false`.
59175934
5918-
<a name="eslint-plugin-jsdoc-rules-require-example-options-12-contexts-1"></a>
5935+
<a name="eslint-plugin-jsdoc-rules-require-example-options-13-contexts-1"></a>
59195936
##### <code>contexts</code>
59205937
59215938
Set this to an array of strings representing the AST context
@@ -6093,7 +6110,7 @@ function quux () {
60936110
60946111
Requires a hyphen before the `@param` description.
60956112
6096-
<a name="eslint-plugin-jsdoc-rules-require-hyphen-before-param-description-options-13"></a>
6113+
<a name="eslint-plugin-jsdoc-rules-require-hyphen-before-param-description-options-14"></a>
60976114
#### Options
60986115
60996116
This rule takes one optional string argument. If it is `"always"` then a problem is raised when there is no hyphen before the description. If it is `"never"` then a problem is raised when there is a hyphen before the description. The default value is `"always"`.
@@ -6199,7 +6216,7 @@ function quux () {
61996216
Checks for presence of jsdoc comments, on class declarations as well as
62006217
functions.
62016218
6202-
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-14"></a>
6219+
<a name="eslint-plugin-jsdoc-rules-require-jsdoc-options-15"></a>
62036220
#### Options
62046221
62056222
Accepts one optional options object with the following optional keys.
@@ -7387,7 +7404,7 @@ function quux (foo) {
73877404
73887405
Requires that all function parameters are documented.
73897406
7390-
<a name="eslint-plugin-jsdoc-rules-require-param-options-15"></a>
7407+
<a name="eslint-plugin-jsdoc-rules-require-param-options-16"></a>
73917408
#### Options
73927409
73937410
An options object accepts one optional property:
@@ -8487,7 +8504,7 @@ Requires returns are documented.
84878504
84888505
Will also report if multiple `@returns` tags are present.
84898506
8490-
<a name="eslint-plugin-jsdoc-rules-require-returns-options-16"></a>
8507+
<a name="eslint-plugin-jsdoc-rules-require-returns-options-17"></a>
84918508
#### Options
84928509
84938510
- `exemptedBy` - Array of tags (e.g., `['type']`) whose presence on the document
@@ -8952,7 +8969,7 @@ Also impacts behaviors on namepath (or event)-defining and pointing tags:
89528969
allow `#`, `.`, or `~` at the end (which is not allowed at the end of
89538970
normal paths).
89548971
8955-
<a name="eslint-plugin-jsdoc-rules-valid-types-options-17"></a>
8972+
<a name="eslint-plugin-jsdoc-rules-valid-types-options-18"></a>
89568973
#### Options
89578974
89588975
- `allowEmptyNamepaths` (default: true) - Set to `false` to disallow

src/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import matchDescription from './rules/matchDescription';
1414
import newlineAfterDescription from './rules/newlineAfterDescription';
1515
import noTypes from './rules/noTypes';
1616
import noUndefinedTypes from './rules/noUndefinedTypes';
17-
import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence';
17+
import requireAsteriskPrefix from './rules/requireAsteriskPrefix';
1818
import requireDescription from './rules/requireDescription';
19+
import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence';
1920
import requireExample from './rules/requireExample';
2021
import requireHyphenBeforeParamDescription from './rules/requireHyphenBeforeParamDescription';
21-
import requireParamName from './rules/requireParamName';
2222
import requireParam from './rules/requireParam';
2323
import requireParamDescription from './rules/requireParamDescription';
24+
import requireParamName from './rules/requireParamName';
2425
import requireParamType from './rules/requireParamType';
2526
import requireReturns from './rules/requireReturns';
2627
import requireReturnsCheck from './rules/requireReturnsCheck';
@@ -49,6 +50,7 @@ export default {
4950
'jsdoc/newline-after-description': 'warn',
5051
'jsdoc/no-types': 'off',
5152
'jsdoc/no-undefined-types': 'warn',
53+
'jsdoc/require-asterisk-prefix': 'off',
5254
'jsdoc/require-description': 'off',
5355
'jsdoc/require-description-complete-sentence': 'off',
5456
'jsdoc/require-example': 'off',
@@ -82,6 +84,7 @@ export default {
8284
'newline-after-description': newlineAfterDescription,
8385
'no-types': noTypes,
8486
'no-undefined-types': noUndefinedTypes,
87+
'require-asterisk-prefix': requireAsteriskPrefix,
8588
'require-description': requireDescription,
8689
'require-description-complete-sentence': requireDescriptionCompleteSentence,
8790
'require-example': requireExample,

src/rules/requireAsteriskPrefix.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import iterateJsdoc from '../iterateJsdoc';
2+
3+
const prefixMatch = /^(\s+)(?:\*( ?))?/u;
4+
const validPrefix = /^\s+\*(?:\/?$| )/u;
5+
6+
export default iterateJsdoc(({
7+
sourceCode,
8+
jsdocNode,
9+
report,
10+
}) => {
11+
const fix = (fixer) => {
12+
const replacement = sourceCode.getText(jsdocNode).split('\n')
13+
.map((line, index) => {
14+
return index && !validPrefix.test(line) ? line.replace(prefixMatch, (_, $1, $2) => {
15+
return `${$1}*${$2 || ' '}`;
16+
}) : line;
17+
})
18+
.join('\n');
19+
20+
return fixer.replaceText(jsdocNode, replacement);
21+
};
22+
23+
sourceCode.getText(jsdocNode).split('\n').some((line, index) => {
24+
const lineNum = parseInt(index, 10);
25+
if (lineNum && !validPrefix.test(line)) {
26+
report('Expected JSDoc block to have the prefix.', fix, {
27+
line: lineNum,
28+
});
29+
30+
return true;
31+
}
32+
33+
return false;
34+
});
35+
}, {
36+
iterateAllJsdocs: true,
37+
meta: {
38+
fixable: 'code',
39+
type: 'layout',
40+
},
41+
});
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
export default {
2+
invalid: [
3+
{
4+
code: `
5+
6+
/**
7+
@param {Number} foo
8+
*/
9+
function quux (foo) {
10+
// with spaces
11+
}
12+
`,
13+
errors: [
14+
{
15+
line: 4,
16+
message: 'Expected JSDoc block to have the prefix.',
17+
},
18+
],
19+
output: `
20+
21+
/**
22+
* @param {Number} foo
23+
*/
24+
function quux (foo) {
25+
// with spaces
26+
}
27+
`,
28+
},
29+
{
30+
code: `
31+
/**
32+
@param {Number} foo
33+
*/function quux (foo) {
34+
// with spaces
35+
}
36+
`,
37+
errors: [
38+
{
39+
line: 3,
40+
message: 'Expected JSDoc block to have the prefix.',
41+
},
42+
],
43+
output: `
44+
/**
45+
* @param {Number} foo
46+
*/function quux (foo) {
47+
// with spaces
48+
}
49+
`,
50+
},
51+
],
52+
valid: [
53+
{
54+
code: `
55+
/**
56+
* Desc
57+
*
58+
* @param {Number} foo
59+
* This is more comment.
60+
*/
61+
function quux (foo) {
62+
63+
}
64+
`,
65+
},
66+
{
67+
code: `
68+
/**
69+
* Desc
70+
*
71+
* @param {{
72+
* foo: Bar,
73+
* bar: Baz
74+
* }} foo
75+
*
76+
*/
77+
function quux (foo) {
78+
79+
}
80+
`,
81+
},
82+
{
83+
code: `
84+
/* <- JSDoc must start with 2 stars.
85+
So this is unchecked.
86+
*/
87+
function quux (foo) {}
88+
`,
89+
},
90+
],
91+
};

test/rules/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const ruleTester = new RuleTester();
2323
'newline-after-description',
2424
'no-types',
2525
'no-undefined-types',
26+
'require-asterisk-prefix',
2627
'require-description',
2728
'require-description-complete-sentence',
2829
'require-example',

0 commit comments

Comments
 (0)