Skip to content

Commit f0515be

Browse files
committed
feat(check-tag-names): add inlineTags option with default inline tag checking
1 parent 8bbec0a commit f0515be

File tree

7 files changed

+150
-19
lines changed

7 files changed

+150
-19
lines changed

.README/rules/check-tag-names.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ tag to `false`:
192192
}
193193
```
194194

195+
Also checks for unknown inline tags, with the following being permitted by default
196+
(see the `inlineTags` option):
197+
198+
```
199+
link
200+
linkcode
201+
linkplain
202+
tutorial
203+
```
204+
195205
## Fixer
196206

197207
Auto-removes types that are redundant with the [`typed` option](#typed).
@@ -207,7 +217,7 @@ Auto-removes types that are redundant with the [`typed` option](#typed).
207217
|Context|everywhere|
208218
|Tags|N/A|
209219
|Recommended|true|
210-
|Options|`definedTags`, `enableFixer`, `jsxTags`, `typed`|
220+
|Options|`definedTags`, `enableFixer`, `inlineTags`, `jsxTags`, `typed`|
211221
|Settings|`tagNamePreference`, `mode`|
212222

213223
## Failing examples

docs/rules/check-tag-names.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* [Options](#user-content-check-tag-names-options)
77
* [`definedTags`](#user-content-check-tag-names-options-definedtags)
88
* [`enableFixer`](#user-content-check-tag-names-options-enablefixer)
9+
* [`inlineTags`](#user-content-check-tag-names-options-inlinetags)
910
* [`jsxTags`](#user-content-check-tag-names-options-jsxtags)
1011
* [`typed`](#user-content-check-tag-names-options-typed)
1112
* [Context and settings](#user-content-check-tag-names-context-and-settings)
@@ -203,6 +204,16 @@ tag to `false`:
203204
}
204205
```
205206

207+
Also checks for unknown inline tags, with the following being permitted by default
208+
(see the `inlineTags` option):
209+
210+
```
211+
link
212+
linkcode
213+
linkplain
214+
tutorial
215+
```
216+
206217
<a name="user-content-check-tag-names-fixer"></a>
207218
<a name="check-tag-names-fixer"></a>
208219
## Fixer
@@ -232,6 +243,13 @@ The format is as follows:
232243
### <code>enableFixer</code>
233244

234245
Set to `false` to disable auto-removal of types that are redundant with the [`typed` option](#user-content-typed).
246+
<a name="user-content-check-tag-names-options-inlinetags"></a>
247+
<a name="check-tag-names-options-inlinetags"></a>
248+
### <code>inlineTags</code>
249+
250+
List of tags to allow inline.
251+
252+
Defaults to array of `'link', 'linkcode', 'linkplain', 'tutorial'`
235253
<a name="user-content-check-tag-names-options-jsxtags"></a>
236254
<a name="check-tag-names-options-jsxtags"></a>
237255
### <code>jsxTags</code>
@@ -313,7 +331,7 @@ this
313331
|Context|everywhere|
314332
|Tags|N/A|
315333
|Recommended|true|
316-
|Options|`definedTags`, `enableFixer`, `jsxTags`, `typed`|
334+
|Options|`definedTags`, `enableFixer`, `inlineTags`, `jsxTags`, `typed`|
317335
|Settings|`tagNamePreference`, `mode`|
318336

319337
<a name="user-content-check-tag-names-failing-examples"></a>
@@ -765,6 +783,13 @@ function quux () {
765783
}
766784
// Settings: {"jsdoc":{"tagNamePreference":{"todo":{"message":"Please don't use todo"}}}}
767785
// Message: Please don't use todo
786+
787+
/**
788+
* An {@inline sth} tag in the description and {@another} with a {@link}.
789+
* @param {SomeType} name And an {@inlineTag} inside a tag description.
790+
* @param {AnotherType} anotherName And yet {@another}
791+
*/
792+
// Message: Invalid JSDoc inline tag name "inline"
768793
````
769794

770795

@@ -1121,5 +1146,12 @@ interface WebTwain {
11211146
* A comment related to the module
11221147
*/
11231148
// "jsdoc/check-tag-names": ["error"|"warn", {"typed":true}]
1149+
1150+
/**
1151+
* An {@inline sth} tag in the description and {@another} with a {@link}.
1152+
* @param {SomeType} name And an {@inlineTag} inside a tag description.
1153+
* @param {AnotherType} anotherName And yet {@another}
1154+
*/
1155+
// "jsdoc/check-tag-names": ["error"|"warn", {"inlineTags":["inline","another","inlineTag","link"]}]
11241156
````
11251157

src/iterateJsdoc.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,14 @@ import esquery from 'esquery';
436436
* import('@es-joy/jsdoccomment').JsdocInlineTagNoType)[]}
437437
*/
438438

439+
/**
440+
* @callback getInlineTags
441+
* @returns {(import('comment-parser').Spec|
442+
* import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
443+
* line?: number | undefined; column?: number | undefined;
444+
* })[]}
445+
*/
446+
439447
/**
440448
* @callback GetTagsByType
441449
* @param {import('comment-parser').Spec[]} tags
@@ -533,6 +541,7 @@ import esquery from 'esquery';
533541
* getPresentTags: GetPresentTags,
534542
* filterTags: FilterTags,
535543
* filterAllTags: FilterAllTags,
544+
* getInlineTags: getInlineTags,
536545
* getTagsByType: GetTagsByType,
537546
* hasOptionTag: HasOptionTag,
538547
* getClassNode: GetClassNode,
@@ -1641,6 +1650,10 @@ const getUtils = (
16411650
});
16421651
};
16431652

1653+
utils.getInlineTags = () => {
1654+
return jsdocUtils.getInlineTags(jsdoc);
1655+
};
1656+
16441657
/** @type {GetTagsByType} */
16451658
utils.getTagsByType = (tags) => {
16461659
return jsdocUtils.getTagsByType(context, mode, tags);

src/jsdocUtils.js

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -836,14 +836,15 @@ const forEachPreferredTag = (
836836
};
837837

838838
/**
839-
* Get all tags, inline tags and inline tags in tags
839+
* Get all inline tags and inline tags in tags
840840
* @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
841841
* @returns {(import('comment-parser').Spec|
842-
* import('@es-joy/jsdoccomment').JsdocInlineTagNoType)[]}
842+
* import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
843+
* line?: number | undefined; column?: number | undefined;
844+
* })[]}
843845
*/
844-
const getAllTags = (jsdoc) => {
846+
const getInlineTags = (jsdoc) => {
845847
return [
846-
...jsdoc.tags,
847848
...jsdoc.inlineTags.map((inlineTag) => {
848849
// Tags don't have source or line numbers, so add before returning
849850
let line = -1;
@@ -863,18 +864,6 @@ const getAllTags = (jsdoc) => {
863864
return inlineTag;
864865
}),
865866
...jsdoc.tags.flatMap((tag) => {
866-
let tagBegins = -1;
867-
for (const {
868-
tokens: {
869-
tag: tg,
870-
},
871-
} of jsdoc.source) {
872-
tagBegins++;
873-
if (tg) {
874-
break;
875-
}
876-
}
877-
878867
for (const inlineTag of tag.inlineTags) {
879868
/** @type {import('./iterateJsdoc.js').Integer} */
880869
let line = 0;
@@ -890,7 +879,7 @@ const getAllTags = (jsdoc) => {
890879
}
891880
}
892881

893-
inlineTag.line = tagBegins + line - 1;
882+
inlineTag.line = line;
894883
}
895884

896885
return (
@@ -906,6 +895,21 @@ const getAllTags = (jsdoc) => {
906895
];
907896
};
908897

898+
/**
899+
* Get all tags, inline tags and inline tags in tags
900+
* @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
901+
* @returns {(import('comment-parser').Spec|
902+
* import('@es-joy/jsdoccomment').JsdocInlineTagNoType & {
903+
* line?: number | undefined; column?: number | undefined;
904+
* })[]}
905+
*/
906+
const getAllTags = (jsdoc) => {
907+
return [
908+
...jsdoc.tags,
909+
...getInlineTags(jsdoc),
910+
];
911+
};
912+
909913
/**
910914
* @param {import('./iterateJsdoc.js').JsdocBlockWithInline} jsdoc
911915
* @param {string[]} targetTagNames
@@ -1853,6 +1857,7 @@ export {
18531857
getContextObject,
18541858
getFunctionParameterNames,
18551859
getIndent,
1860+
getInlineTags,
18561861
getJsdocTagsDeep,
18571862
getPreferredTagName,
18581863
getPreferredTagNameSimple,

src/rules.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ export interface Rules {
261261
* Set to `false` to disable auto-removal of types that are redundant with the [`typed` option](#typed).
262262
*/
263263
enableFixer?: boolean;
264+
/**
265+
* List of tags to allow inline.
266+
*
267+
* Defaults to array of `'link', 'linkcode', 'linkplain', 'tutorial'`
268+
*/
269+
inlineTags?: string[];
264270
/**
265271
* If this is set to `true`, all of the following tags used to control JSX output are allowed:
266272
*

src/rules/checkTagNames.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,15 @@ export default iterateJsdoc(({
7575
* @type {{
7676
* definedTags: string[],
7777
* enableFixer: boolean,
78+
* inlineTags: string[],
7879
* jsxTags: boolean,
7980
* typed: boolean
8081
}} */ {
8182
definedTags = [],
8283
enableFixer = true,
84+
inlineTags = [
85+
'link', 'linkcode', 'linkplain', 'tutorial',
86+
],
8387
jsxTags,
8488
typed,
8589
} = context.options[0] || {};
@@ -278,6 +282,12 @@ export default iterateJsdoc(({
278282
report(`Invalid JSDoc tag name "${tagName}".`, null, jsdocTag);
279283
}
280284
}
285+
286+
for (const inlineTag of utils.getInlineTags()) {
287+
if (!inlineTags.includes(inlineTag.tag)) {
288+
report(`Invalid JSDoc inline tag name "${inlineTag.tag}"`, null, inlineTag);
289+
}
290+
}
281291
}, {
282292
iterateAllJsdocs: true,
283293
meta: {
@@ -308,6 +318,15 @@ The format is as follows:
308318
description: 'Set to `false` to disable auto-removal of types that are redundant with the [`typed` option](#typed).',
309319
type: 'boolean',
310320
},
321+
inlineTags: {
322+
description: `List of tags to allow inline.
323+
324+
Defaults to array of \`'link', 'linkcode', 'linkplain', 'tutorial'\``,
325+
items: {
326+
type: 'string',
327+
},
328+
type: 'array',
329+
},
311330
jsxTags: {
312331
description: `If this is set to \`true\`, all of the following tags used to control JSX output are allowed:
313332

test/rules/assertions/checkTagNames.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,33 @@ export default /** @type {import('../index.js').TestCases} */ ({
10291029
},
10301030
},
10311031
},
1032+
{
1033+
code: `
1034+
/**
1035+
* An {@inline sth} tag in the description and {@another} with a {@link}.
1036+
* @param {SomeType} name And an {@inlineTag} inside a tag description.
1037+
* @param {AnotherType} anotherName And yet {@another}
1038+
*/
1039+
`,
1040+
errors: [
1041+
{
1042+
line: 3,
1043+
message: 'Invalid JSDoc inline tag name "inline"',
1044+
},
1045+
{
1046+
line: 3,
1047+
message: 'Invalid JSDoc inline tag name "another"',
1048+
},
1049+
{
1050+
line: 4,
1051+
message: 'Invalid JSDoc inline tag name "inlineTag"',
1052+
},
1053+
{
1054+
line: 5,
1055+
message: 'Invalid JSDoc inline tag name "another"',
1056+
},
1057+
],
1058+
},
10321059
],
10331060
valid: [
10341061
{
@@ -1453,5 +1480,24 @@ export default /** @type {import('../index.js').TestCases} */ ({
14531480
},
14541481
],
14551482
},
1483+
{
1484+
code: `
1485+
/**
1486+
* An {@inline sth} tag in the description and {@another} with a {@link}.
1487+
* @param {SomeType} name And an {@inlineTag} inside a tag description.
1488+
* @param {AnotherType} anotherName And yet {@another}
1489+
*/
1490+
`,
1491+
options: [
1492+
{
1493+
inlineTags: [
1494+
'inline',
1495+
'another',
1496+
'inlineTag',
1497+
'link',
1498+
],
1499+
},
1500+
],
1501+
},
14561502
],
14571503
});

0 commit comments

Comments
 (0)