eslint-plugin-jsdoc 59.1.0 → 60.1.0

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/dist/rules.d.ts CHANGED
@@ -2370,6 +2370,26 @@ export interface Rules {
2370
2370
  }
2371
2371
  ];
2372
2372
 
2373
+ /** Requires tags be present, optionally for specific contexts */
2374
+ "jsdoc/require-tags":
2375
+ | []
2376
+ | [
2377
+ {
2378
+ /**
2379
+ * May be an array of either strings or objects with
2380
+ * a string `tag` property and `context` string property.
2381
+ */
2382
+ tags?: (
2383
+ | string
2384
+ | {
2385
+ context?: string;
2386
+ tag?: string;
2387
+ [k: string]: unknown;
2388
+ }
2389
+ )[];
2390
+ }
2391
+ ];
2392
+
2373
2393
  /** Requires `@template` tags be present when type parameters are used. */
2374
2394
  "jsdoc/require-template":
2375
2395
  | []
@@ -2580,26 +2600,6 @@ export interface Rules {
2580
2600
  /** Requires a type for `@yields` tags */
2581
2601
  "jsdoc/require-yields-type": [];
2582
2602
 
2583
- /** Requires tags be present, optionally for specific contexts */
2584
- "jsdoc/required-tags":
2585
- | []
2586
- | [
2587
- {
2588
- /**
2589
- * May be an array of either strings or objects with
2590
- * a string `tag` property and `context` string property.
2591
- */
2592
- tags?: (
2593
- | string
2594
- | {
2595
- context?: string;
2596
- tag?: string;
2597
- [k: string]: unknown;
2598
- }
2599
- )[];
2600
- }
2601
- ];
2602
-
2603
2603
  /** Sorts tags by a specified sequence according to tag name, optionally adding line breaks between tag groups. */
2604
2604
  "jsdoc/sort-tags":
2605
2605
  | []
@@ -2826,7 +2826,7 @@ export interface Rules {
2826
2826
  }
2827
2827
  ];
2828
2828
 
2829
- /** Enforces lines (or no lines) between tags. */
2829
+ /** Enforces lines (or no lines) before, after, or between tags. */
2830
2830
  "jsdoc/tag-lines":
2831
2831
  | []
2832
2832
  | ["always" | "any" | "never"]
@@ -2853,6 +2853,14 @@ export interface Rules {
2853
2853
  * Defaults to `0`.
2854
2854
  */
2855
2855
  endLines?: number | null;
2856
+ /**
2857
+ * If not set to `null`, will enforce a maximum number of lines to the given count anywhere in the block description.
2858
+ *
2859
+ * Note that if non-`null`, `maxBlockLines` must be greater than or equal to `startLines`.
2860
+ *
2861
+ * Defaults to `null`.
2862
+ */
2863
+ maxBlockLines?: number | null;
2856
2864
  /**
2857
2865
  * If not set to `null`, will enforce end lines to the given count before the
2858
2866
  * first tag only, unless there is only whitespace content, in which case,
package/package.json CHANGED
@@ -172,5 +172,5 @@
172
172
  "test-cov": "TIMING=1 c8 --reporter text pnpm run test-no-cov",
173
173
  "test-index": "pnpm run test-no-cov test/rules/index.js"
174
174
  },
175
- "version": "59.1.0"
175
+ "version": "60.1.0"
176
176
  }
package/src/index-cjs.js CHANGED
@@ -40,7 +40,6 @@ import noUndefinedTypes from './rules/noUndefinedTypes.js';
40
40
  import requireAsteriskPrefix from './rules/requireAsteriskPrefix.js';
41
41
  import requireDescription from './rules/requireDescription.js';
42
42
  import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence.js';
43
- import requiredTags from './rules/requiredTags.js';
44
43
  import requireExample from './rules/requireExample.js';
45
44
  import requireFileOverview from './rules/requireFileOverview.js';
46
45
  import requireHyphenBeforeParamDescription from './rules/requireHyphenBeforeParamDescription.js';
@@ -57,6 +56,7 @@ import requireReturns from './rules/requireReturns.js';
57
56
  import requireReturnsCheck from './rules/requireReturnsCheck.js';
58
57
  import requireReturnsDescription from './rules/requireReturnsDescription.js';
59
58
  import requireReturnsType from './rules/requireReturnsType.js';
59
+ import requireTags from './rules/requireTags.js';
60
60
  import requireTemplate from './rules/requireTemplate.js';
61
61
  import requireThrows from './rules/requireThrows.js';
62
62
  import requireYields from './rules/requireYields.js';
@@ -179,6 +179,7 @@ index.rules = {
179
179
  'require-returns-check': requireReturnsCheck,
180
180
  'require-returns-description': requireReturnsDescription,
181
181
  'require-returns-type': requireReturnsType,
182
+ 'require-tags': requireTags,
182
183
  'require-template': requireTemplate,
183
184
  'require-throws': requireThrows,
184
185
  'require-throws-description': buildForbidRuleDefinition({
@@ -227,7 +228,6 @@ index.rules = {
227
228
  description: 'Requires a type for `@yields` tags',
228
229
  url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-yields-type.md#repos-sticky-header',
229
230
  }),
230
- 'required-tags': requiredTags,
231
231
  'sort-tags': sortTags,
232
232
  'tag-lines': tagLines,
233
233
  'text-escaping': textEscaping,
@@ -306,6 +306,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
306
306
  'jsdoc/require-returns-check': warnOrError,
307
307
  'jsdoc/require-returns-description': warnOrError,
308
308
  'jsdoc/require-returns-type': warnOrError,
309
+ 'jsdoc/require-tags': 'off',
309
310
  'jsdoc/require-template': 'off',
310
311
  'jsdoc/require-throws': 'off',
311
312
  'jsdoc/require-throws-description': 'off',
@@ -314,7 +315,6 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
314
315
  'jsdoc/require-yields-check': warnOrError,
315
316
  'jsdoc/require-yields-description': 'off',
316
317
  'jsdoc/require-yields-type': warnOrError,
317
- 'jsdoc/required-tags': 'off',
318
318
  'jsdoc/sort-tags': 'off',
319
319
  'jsdoc/tag-lines': warnOrError,
320
320
  'jsdoc/text-escaping': 'off',
package/src/index.js CHANGED
@@ -46,7 +46,6 @@ import noUndefinedTypes from './rules/noUndefinedTypes.js';
46
46
  import requireAsteriskPrefix from './rules/requireAsteriskPrefix.js';
47
47
  import requireDescription from './rules/requireDescription.js';
48
48
  import requireDescriptionCompleteSentence from './rules/requireDescriptionCompleteSentence.js';
49
- import requiredTags from './rules/requiredTags.js';
50
49
  import requireExample from './rules/requireExample.js';
51
50
  import requireFileOverview from './rules/requireFileOverview.js';
52
51
  import requireHyphenBeforeParamDescription from './rules/requireHyphenBeforeParamDescription.js';
@@ -63,6 +62,7 @@ import requireReturns from './rules/requireReturns.js';
63
62
  import requireReturnsCheck from './rules/requireReturnsCheck.js';
64
63
  import requireReturnsDescription from './rules/requireReturnsDescription.js';
65
64
  import requireReturnsType from './rules/requireReturnsType.js';
65
+ import requireTags from './rules/requireTags.js';
66
66
  import requireTemplate from './rules/requireTemplate.js';
67
67
  import requireThrows from './rules/requireThrows.js';
68
68
  import requireYields from './rules/requireYields.js';
@@ -185,6 +185,7 @@ index.rules = {
185
185
  'require-returns-check': requireReturnsCheck,
186
186
  'require-returns-description': requireReturnsDescription,
187
187
  'require-returns-type': requireReturnsType,
188
+ 'require-tags': requireTags,
188
189
  'require-template': requireTemplate,
189
190
  'require-throws': requireThrows,
190
191
  'require-throws-description': buildForbidRuleDefinition({
@@ -233,7 +234,6 @@ index.rules = {
233
234
  description: 'Requires a type for `@yields` tags',
234
235
  url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-yields-type.md#repos-sticky-header',
235
236
  }),
236
- 'required-tags': requiredTags,
237
237
  'sort-tags': sortTags,
238
238
  'tag-lines': tagLines,
239
239
  'text-escaping': textEscaping,
@@ -312,6 +312,7 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
312
312
  'jsdoc/require-returns-check': warnOrError,
313
313
  'jsdoc/require-returns-description': warnOrError,
314
314
  'jsdoc/require-returns-type': warnOrError,
315
+ 'jsdoc/require-tags': 'off',
315
316
  'jsdoc/require-template': 'off',
316
317
  'jsdoc/require-throws': 'off',
317
318
  'jsdoc/require-throws-description': 'off',
@@ -320,7 +321,6 @@ const createRecommendedRuleset = (warnOrError, flatName) => {
320
321
  'jsdoc/require-yields-check': warnOrError,
321
322
  'jsdoc/require-yields-description': 'off',
322
323
  'jsdoc/require-yields-type': warnOrError,
323
- 'jsdoc/required-tags': 'off',
324
324
  'jsdoc/sort-tags': 'off',
325
325
  'jsdoc/tag-lines': warnOrError,
326
326
  'jsdoc/text-escaping': 'off',
@@ -7,7 +7,7 @@ export default buildForbidRuleDefinition({
7
7
  getContexts (context, report) {
8
8
  // Transformed options to this option in `modifyContext`:
9
9
  if (!context.options[0].contexts) {
10
- report('Rule `required-tags` is missing a `tags` option.');
10
+ report('Rule `require-tags` is missing a `tags` option.');
11
11
  return false;
12
12
  }
13
13
 
@@ -81,5 +81,5 @@ a string \`tag\` property and \`context\` string property.`,
81
81
  type: 'object',
82
82
  },
83
83
  ],
84
- url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/required-tags.md#repos-sticky-header',
84
+ url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-tags.md#repos-sticky-header',
85
85
  });
@@ -1,5 +1,66 @@
1
1
  import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
+ /**
4
+ * @param {{
5
+ * maxBlockLines: null|number,
6
+ * startLines: null|number,
7
+ * utils: import('../iterateJsdoc.js').Utils
8
+ * }} cfg
9
+ */
10
+ const checkMaxBlockLines = ({
11
+ maxBlockLines,
12
+ startLines,
13
+ utils,
14
+ }) => {
15
+ if (typeof maxBlockLines !== 'number') {
16
+ return false;
17
+ }
18
+
19
+ if (typeof startLines === 'number' && maxBlockLines < startLines) {
20
+ utils.reportJSDoc(
21
+ 'If set to a number, `maxBlockLines` must be greater than or equal to `startLines`.',
22
+ );
23
+ return true;
24
+ }
25
+
26
+ const {
27
+ description,
28
+ } = utils.getDescription();
29
+ const excessBlockLinesRegex = new RegExp('\n{' + (maxBlockLines + 2) + ',}', 'v');
30
+ const excessBlockLinesMatch = description.match(excessBlockLinesRegex);
31
+ const excessBlockLines = excessBlockLinesMatch?.[0]?.length ?? 0;
32
+ if (excessBlockLinesMatch) {
33
+ const excessIndexLine = description.slice(0, excessBlockLinesMatch.index).match(/\n/gv)?.length ?? 0;
34
+ utils.reportJSDoc(
35
+ `Expected a maximum of ${maxBlockLines} line${maxBlockLines === 1 ? '' : 's'} within block description`,
36
+ {
37
+ line: excessIndexLine,
38
+ },
39
+ () => {
40
+ utils.setBlockDescription((info, seedTokens, descLines) => {
41
+ return [
42
+ ...descLines.slice(0, excessIndexLine),
43
+ ...descLines.slice(excessIndexLine + excessBlockLines - 1 - maxBlockLines),
44
+ ].map((desc) => {
45
+ return {
46
+ number: 0,
47
+ source: '',
48
+ tokens: seedTokens({
49
+ ...info,
50
+ description: desc,
51
+ postDelimiter: desc.trim() ? ' ' : '',
52
+ }),
53
+ };
54
+ });
55
+ });
56
+ },
57
+ );
58
+ return true;
59
+ }
60
+
61
+ return false;
62
+ };
63
+
3
64
  export default iterateJsdoc(({
4
65
  context,
5
66
  jsdoc,
@@ -11,6 +72,7 @@ export default iterateJsdoc(({
11
72
  applyToEndTag = true,
12
73
  count = 1,
13
74
  endLines = 0,
75
+ maxBlockLines = null,
14
76
  startLines = 0,
15
77
  tags = {},
16
78
  } = {},
@@ -218,6 +280,14 @@ export default iterateJsdoc(({
218
280
  return false;
219
281
  });
220
282
 
283
+ if (checkMaxBlockLines({
284
+ maxBlockLines,
285
+ startLines,
286
+ utils,
287
+ })) {
288
+ return;
289
+ }
290
+
221
291
  if (typeof startLines === 'number') {
222
292
  if (!jsdoc.tags.length) {
223
293
  return;
@@ -235,7 +305,7 @@ export default iterateJsdoc(({
235
305
  const trailingDiff = (trailingLines ?? 0) - startLines;
236
306
  if (trailingDiff > 0) {
237
307
  utils.reportJSDoc(
238
- `Expected only ${startLines} line after block description`,
308
+ `Expected only ${startLines} line${startLines === 1 ? '' : 's'} after block description`,
239
309
  {
240
310
  line: lastDescriptionLine - trailingDiff,
241
311
  },
@@ -290,14 +360,14 @@ export default iterateJsdoc(({
290
360
  iterateAllJsdocs: true,
291
361
  meta: {
292
362
  docs: {
293
- description: 'Enforces lines (or no lines) between tags.',
363
+ description: 'Enforces lines (or no lines) before, after, or between tags.',
294
364
  url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md#repos-sticky-header',
295
365
  },
296
366
  fixable: 'code',
297
367
  schema: [
298
368
  {
299
369
  description: `Defaults to "never". "any" is only useful with \`tags\` (allowing non-enforcement of lines except
300
- for particular tags) or with \`startLines\` or \`endLines\`. It is also
370
+ for particular tags) or with \`startLines\`, \`endLines\`, or \`maxBlockLines\`. It is also
301
371
  necessary if using the linebreak-setting options of the \`sort-tags\` rule
302
372
  so that the two rules won't conflict in both attempting to set lines
303
373
  between tags.`,
@@ -335,6 +405,21 @@ Defaults to 1.`,
335
405
  final tag only.
336
406
 
337
407
  Defaults to \`0\`.`,
408
+ },
409
+ maxBlockLines: {
410
+ anyOf: [
411
+ {
412
+ type: 'integer',
413
+ },
414
+ {
415
+ type: 'null',
416
+ },
417
+ ],
418
+ description: `If not set to \`null\`, will enforce a maximum number of lines to the given count anywhere in the block description.
419
+
420
+ Note that if non-\`null\`, \`maxBlockLines\` must be greater than or equal to \`startLines\`.
421
+
422
+ Defaults to \`null\`.`,
338
423
  },
339
424
  startLines: {
340
425
  anyOf: [
package/src/rules.d.ts CHANGED
@@ -2370,6 +2370,26 @@ export interface Rules {
2370
2370
  }
2371
2371
  ];
2372
2372
 
2373
+ /** Requires tags be present, optionally for specific contexts */
2374
+ "jsdoc/require-tags":
2375
+ | []
2376
+ | [
2377
+ {
2378
+ /**
2379
+ * May be an array of either strings or objects with
2380
+ * a string `tag` property and `context` string property.
2381
+ */
2382
+ tags?: (
2383
+ | string
2384
+ | {
2385
+ context?: string;
2386
+ tag?: string;
2387
+ [k: string]: unknown;
2388
+ }
2389
+ )[];
2390
+ }
2391
+ ];
2392
+
2373
2393
  /** Requires `@template` tags be present when type parameters are used. */
2374
2394
  "jsdoc/require-template":
2375
2395
  | []
@@ -2580,26 +2600,6 @@ export interface Rules {
2580
2600
  /** Requires a type for `@yields` tags */
2581
2601
  "jsdoc/require-yields-type": [];
2582
2602
 
2583
- /** Requires tags be present, optionally for specific contexts */
2584
- "jsdoc/required-tags":
2585
- | []
2586
- | [
2587
- {
2588
- /**
2589
- * May be an array of either strings or objects with
2590
- * a string `tag` property and `context` string property.
2591
- */
2592
- tags?: (
2593
- | string
2594
- | {
2595
- context?: string;
2596
- tag?: string;
2597
- [k: string]: unknown;
2598
- }
2599
- )[];
2600
- }
2601
- ];
2602
-
2603
2603
  /** Sorts tags by a specified sequence according to tag name, optionally adding line breaks between tag groups. */
2604
2604
  "jsdoc/sort-tags":
2605
2605
  | []
@@ -2826,7 +2826,7 @@ export interface Rules {
2826
2826
  }
2827
2827
  ];
2828
2828
 
2829
- /** Enforces lines (or no lines) between tags. */
2829
+ /** Enforces lines (or no lines) before, after, or between tags. */
2830
2830
  "jsdoc/tag-lines":
2831
2831
  | []
2832
2832
  | ["always" | "any" | "never"]
@@ -2853,6 +2853,14 @@ export interface Rules {
2853
2853
  * Defaults to `0`.
2854
2854
  */
2855
2855
  endLines?: number | null;
2856
+ /**
2857
+ * If not set to `null`, will enforce a maximum number of lines to the given count anywhere in the block description.
2858
+ *
2859
+ * Note that if non-`null`, `maxBlockLines` must be greater than or equal to `startLines`.
2860
+ *
2861
+ * Defaults to `null`.
2862
+ */
2863
+ maxBlockLines?: number | null;
2856
2864
  /**
2857
2865
  * If not set to `null`, will enforce end lines to the given count before the
2858
2866
  * first tag only, unless there is only whitespace content, in which case,
@@ -1 +0,0 @@
1
- {"version":3,"file":"requiredTags.cjs","names":["_buildForbidRuleDefinition","require","_default","exports","default","buildForbidRuleDefinition","description","getContexts","context","report","options","contexts","modifyContext","tags","cntxts","map","tag","tagName","comment","message","propertyDescriptors","Object","getOwnPropertyDescriptors","create","getPrototypeOf","value","schema","additionalProperties","properties","items","anyOf","type","url","module"],"sources":["../../src/rules/requiredTags.js"],"sourcesContent":["import {\n buildForbidRuleDefinition,\n} from '../buildForbidRuleDefinition.js';\n\nexport default buildForbidRuleDefinition({\n description: 'Requires tags be present, optionally for specific contexts',\n getContexts (context, report) {\n // Transformed options to this option in `modifyContext`:\n if (!context.options[0].contexts) {\n report('Rule `required-tags` is missing a `tags` option.');\n return false;\n }\n\n const {\n contexts,\n } = context.options[0];\n\n return contexts;\n },\n modifyContext (context) {\n const tags = /** @type {(string|{tag: string, context: string})[]} */ (\n context.options?.[0]?.tags\n );\n\n const cntxts = tags?.map((tag) => {\n const tagName = typeof tag === 'string' ? tag : tag.tag;\n return {\n comment: `JsdocBlock:not(*:has(JsdocTag[tag=${\n tagName\n }]))`,\n context: typeof tag === 'string' ? 'any' : tag.context,\n message: `Missing required tag \"${tagName}\"`,\n };\n });\n\n // Reproduce context object with our own `contexts`\n const propertyDescriptors = Object.getOwnPropertyDescriptors(context);\n return Object.create(\n Object.getPrototypeOf(context),\n {\n ...propertyDescriptors,\n options: {\n ...propertyDescriptors.options,\n value: [\n {\n contexts: cntxts,\n },\n ],\n },\n },\n );\n },\n schema: [\n {\n additionalProperties: false,\n properties: {\n tags: {\n description: `May be an array of either strings or objects with\na string \\`tag\\` property and \\`context\\` string property.`,\n items: {\n anyOf: [\n {\n type: 'string',\n },\n {\n properties: {\n context: {\n type: 'string',\n },\n tag: {\n type: 'string',\n },\n },\n type: 'object',\n },\n ],\n },\n type: 'array',\n },\n },\n type: 'object',\n },\n ],\n url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/required-tags.md#repos-sticky-header',\n});\n"],"mappings":";;;;;;AAAA,IAAAA,0BAAA,GAAAC,OAAA;AAEyC,IAAAC,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAE1B,IAAAC,oDAAyB,EAAC;EACvCC,WAAW,EAAE,4DAA4D;EACzEC,WAAWA,CAAEC,OAAO,EAAEC,MAAM,EAAE;IAC5B;IACA,IAAI,CAACD,OAAO,CAACE,OAAO,CAAC,CAAC,CAAC,CAACC,QAAQ,EAAE;MAChCF,MAAM,CAAC,kDAAkD,CAAC;MAC1D,OAAO,KAAK;IACd;IAEA,MAAM;MACJE;IACF,CAAC,GAAGH,OAAO,CAACE,OAAO,CAAC,CAAC,CAAC;IAEtB,OAAOC,QAAQ;EACjB,CAAC;EACDC,aAAaA,CAAEJ,OAAO,EAAE;IACtB,MAAMK,IAAI,GAAG;IACXL,OAAO,CAACE,OAAO,GAAG,CAAC,CAAC,EAAEG,IACvB;IAED,MAAMC,MAAM,GAAGD,IAAI,EAAEE,GAAG,CAAEC,GAAG,IAAK;MAChC,MAAMC,OAAO,GAAG,OAAOD,GAAG,KAAK,QAAQ,GAAGA,GAAG,GAAGA,GAAG,CAACA,GAAG;MACvD,OAAO;QACLE,OAAO,EAAE,qCACPD,OAAO,KACJ;QACLT,OAAO,EAAE,OAAOQ,GAAG,KAAK,QAAQ,GAAG,KAAK,GAAGA,GAAG,CAACR,OAAO;QACtDW,OAAO,EAAE,yBAAyBF,OAAO;MAC3C,CAAC;IACH,CAAC,CAAC;;IAEF;IACA,MAAMG,mBAAmB,GAAGC,MAAM,CAACC,yBAAyB,CAACd,OAAO,CAAC;IACrE,OAAOa,MAAM,CAACE,MAAM,CAClBF,MAAM,CAACG,cAAc,CAAChB,OAAO,CAAC,EAC9B;MACE,GAAGY,mBAAmB;MACtBV,OAAO,EAAE;QACP,GAAGU,mBAAmB,CAACV,OAAO;QAC9Be,KAAK,EAAE,CACL;UACEd,QAAQ,EAAEG;QACZ,CAAC;MAEL;IACF,CACF,CAAC;EACH,CAAC;EACDY,MAAM,EAAE,CACN;IACEC,oBAAoB,EAAE,KAAK;IAC3BC,UAAU,EAAE;MACVf,IAAI,EAAE;QACJP,WAAW,EAAE;AACvB,2DAA2D;QACjDuB,KAAK,EAAE;UACLC,KAAK,EAAE,CACL;YACEC,IAAI,EAAE;UACR,CAAC,EACD;YACEH,UAAU,EAAE;cACVpB,OAAO,EAAE;gBACPuB,IAAI,EAAE;cACR,CAAC;cACDf,GAAG,EAAE;gBACHe,IAAI,EAAE;cACR;YACF,CAAC;YACDA,IAAI,EAAE;UACR,CAAC;QAEL,CAAC;QACDA,IAAI,EAAE;MACR;IACF,CAAC;IACDA,IAAI,EAAE;EACR,CAAC,CACF;EACDC,GAAG,EAAE;AACP,CAAC,CAAC;AAAAC,MAAA,CAAA9B,OAAA,GAAAA,OAAA,CAAAC,OAAA","ignoreList":[]}