eslint-plugin-jsdoc 62.6.1 → 62.7.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.
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "html-entities": "^2.6.0",
17
17
  "object-deep-merge": "^2.0.0",
18
18
  "parse-imports-exports": "^0.2.4",
19
- "semver": "^7.7.3",
19
+ "semver": "^7.7.4",
20
20
  "spdx-expression-parse": "^4.0.0",
21
21
  "to-valid-identifier": "^1.0.0"
22
22
  },
@@ -24,19 +24,18 @@
24
24
  "devDependencies": {
25
25
  "@arethetypeswrong/cli": "^0.18.2",
26
26
  "@babel/cli": "^7.28.6",
27
- "@babel/core": "^7.29.0",
28
- "@babel/eslint-parser": "^7.28.6",
29
- "@babel/plugin-syntax-class-properties": "^7.12.13",
30
- "@babel/plugin-transform-flow-strip-types": "^7.27.1",
31
- "@babel/preset-env": "^7.29.0",
27
+ "@babel/core": "8.0.0-rc.1",
28
+ "@babel/eslint-parser": "8.0.0-rc.1",
29
+ "@babel/plugin-transform-flow-strip-types": "8.0.0-rc.1",
30
+ "@babel/preset-env": "8.0.0-rc.1",
32
31
  "@es-joy/escodegen": "^4.2.0",
33
32
  "@es-joy/jsdoc-eslint-parser": "^0.27.0",
34
33
  "@eslint/core": "^1.1.0",
35
34
  "@hkdobrev/run-if-changed": "^0.6.3",
36
35
  "@rollup/plugin-node-resolve": "^16.0.3",
37
36
  "@semantic-release/commit-analyzer": "^13.0.1",
38
- "@semantic-release/github": "^12.0.3",
39
- "@semantic-release/npm": "^13.1.3",
37
+ "@semantic-release/github": "^12.0.6",
38
+ "@semantic-release/npm": "^13.1.4",
40
39
  "@types/chai": "^5.2.3",
41
40
  "@types/debug": "^4.1.12",
42
41
  "@types/espree": "^10.1.0",
@@ -44,10 +43,10 @@
44
43
  "@types/estree": "^1.0.8",
45
44
  "@types/json-schema": "^7.0.15",
46
45
  "@types/mocha": "^10.0.10",
47
- "@types/node": "^25.2.0",
46
+ "@types/node": "^25.3.0",
48
47
  "@types/semver": "^7.7.1",
49
48
  "@types/spdx-expression-parse": "^3.0.5",
50
- "@typescript-eslint/types": "^8.54.0",
49
+ "@typescript-eslint/types": "8.56.0",
51
50
  "babel-plugin-add-module-exports": "^1.0.4",
52
51
  "babel-plugin-istanbul": "^7.0.1",
53
52
  "babel-plugin-transform-import-meta": "^2.3.3",
@@ -55,10 +54,10 @@
55
54
  "camelcase": "^9.0.0",
56
55
  "chai": "^6.2.2",
57
56
  "decamelize": "^6.0.1",
58
- "eslint": "9.39.2",
57
+ "eslint": "10.0.0",
59
58
  "eslint-config-canonical": "^47.4.2",
60
59
  "gitdown": "^4.1.1",
61
- "glob": "^13.0.1",
60
+ "glob": "^13.0.5",
62
61
  "globals": "^17.3.0",
63
62
  "husky": "^9.1.7",
64
63
  "jsdoc-type-pratt-parser": "^7.1.1",
@@ -67,15 +66,15 @@
67
66
  "lint-staged": "^16.2.7",
68
67
  "mocha": "^11.7.5",
69
68
  "open-editor": "^6.0.0",
70
- "playwright": "^1.58.1",
69
+ "playwright": "^1.58.2",
71
70
  "replace": "^1.2.2",
72
- "rimraf": "^6.1.2",
71
+ "rimraf": "^6.1.3",
73
72
  "rollup": "^4.57.1",
74
73
  "semantic-release": "^25.0.3",
75
74
  "sinon": "^21.0.1",
76
75
  "ts-api-utils": "^2.4.0",
77
76
  "typescript": "5.9.3",
78
- "typescript-eslint": "^8.54.0"
77
+ "typescript-eslint": "8.56.0"
79
78
  },
80
79
  "engines": {
81
80
  "node": "^20.19.0 || ^22.13.0 || >=24"
@@ -147,7 +146,7 @@
147
146
  "statements": 100
148
147
  },
149
148
  "peerDependencies": {
150
- "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
149
+ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
151
150
  },
152
151
  "repository": {
153
152
  "type": "git",
@@ -162,7 +161,8 @@
162
161
  },
163
162
  "pnpm": {
164
163
  "overrides": {
165
- "@types/eslint": "0.0.0-interferes-with-eslint-now"
164
+ "@types/eslint": "0.0.0-interferes-with-eslint-now",
165
+ "eslint-scope": "9.1.0"
166
166
  },
167
167
  "ignoredBuiltDependencies": [
168
168
  "core-js",
@@ -177,7 +177,7 @@
177
177
  "tsc-build": "tsc -p tsconfig-prod.json",
178
178
  "tsc-cjs": "tsc -p tsconfig-cjs.json",
179
179
  "rollup": "rollup -c",
180
- "build": "node ./src/bin/buildEntryFileForTS.js && rimraf ./dist && pnpm rollup && NODE_ENV=production babel ./src --out-file-extension .cjs --out-dir ./dist --copy-files --source-maps --ignore ./src/bin/*.js --no-copy-ignored && replace 'to-valid-identifier' '../to-valid-identifier.cjs' 'dist' -r --include=\"*.cjs\" && replace 'require\\(\"\\.(.*?)\\.[^.]*?\"\\)' 'require(\".$1.cjs\")' 'dist' -r --include=\"*.cjs\" && pnpm tsc-build && pnpm tsc-cjs",
180
+ "build": "node ./src/bin/buildEntryFileForTS.js && rimraf ./dist && mkdir dist && pnpm rollup && NODE_ENV=production babel ./src --out-file-extension .cjs --out-dir ./dist --copy-files --source-maps --ignore ./src/bin/*.js --no-copy-ignored && replace 'to-valid-identifier' '../to-valid-identifier.cjs' 'dist' -r --include=\"*.cjs\" && replace 'require\\(\"\\.(.*?)\\.[^.]*?\"\\)' 'require(\".$1.cjs\")' 'dist' -r --include=\"*.cjs\" && pnpm tsc-build && pnpm tsc-cjs",
181
181
  "attw": "attw --pack .",
182
182
  "check-docs": "node ./src/bin/generateDocs.js --check",
183
183
  "create-docs": "pnpm run create-options && node ./src/bin/generateDocs.js && pnpm ruleTypes",
@@ -192,5 +192,5 @@
192
192
  "test-cov": "TIMING=1 c8 --reporter text pnpm run test-no-cov",
193
193
  "test-index": "pnpm run test-no-cov test/rules/index.js"
194
194
  },
195
- "version": "62.6.1"
195
+ "version": "62.7.1"
196
196
  }
@@ -739,6 +739,7 @@ const getUtils = (
739
739
 
740
740
  /* c8 ignore next -- Fallback to deprecated method */
741
741
  const {
742
+ // @ts-expect-error ESLint < 10
742
743
  sourceCode = context.getSourceCode(),
743
744
  } = context;
744
745
 
@@ -2188,6 +2189,7 @@ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveCommentContext
2188
2189
  const callIterator = (context, node, jsdocNodes, state, lastCall) => {
2189
2190
  /* c8 ignore next -- Fallback to deprecated method */
2190
2191
  const {
2192
+ // @ts-expect-error ESLint < 10
2191
2193
  sourceCode = context.getSourceCode(),
2192
2194
  } = context;
2193
2195
  const {
@@ -2301,6 +2303,7 @@ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveCommentContext
2301
2303
  create (context) {
2302
2304
  /* c8 ignore next -- Fallback to deprecated method */
2303
2305
  const {
2306
+ // @ts-expect-error ESLint < 10
2304
2307
  sourceCode = context.getSourceCode(),
2305
2308
  } = context;
2306
2309
  settings = getSettings(context);
@@ -2349,7 +2352,9 @@ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveCommentContext
2349
2352
  ], /** @type {StateObject} */ (state));
2350
2353
  },
2351
2354
  'Program:exit' () {
2352
- const allComments = sourceCode.getAllComments();
2355
+ const allComments = /** @type {import('estree').Comment[]} */ (
2356
+ sourceCode.getAllComments()
2357
+ );
2353
2358
  const untrackedJSdoc = allComments.filter((node) => {
2354
2359
  return !trackedJsdocs.has(node);
2355
2360
  });
@@ -2381,6 +2386,7 @@ const checkFile = (iterator, ruleConfig) => {
2381
2386
  create (context) {
2382
2387
  /* c8 ignore next -- Fallback to deprecated method */
2383
2388
  const {
2389
+ // @ts-expect-error ESLint < 10
2384
2390
  sourceCode = context.getSourceCode(),
2385
2391
  } = context;
2386
2392
  const settings = getSettings(context);
@@ -2504,6 +2510,7 @@ export default function iterateJsdoc (iterator, ruleConfig) {
2504
2510
 
2505
2511
  /* c8 ignore next -- Fallback to deprecated method */
2506
2512
  const {
2513
+ // @ts-expect-error ESLint < 10
2507
2514
  sourceCode = context.getSourceCode(),
2508
2515
  } = context;
2509
2516
  const {
@@ -366,6 +366,7 @@ export default iterateJsdoc(({
366
366
  const getFilenameInfo = (filename, ext = 'md/*.js') => {
367
367
  let defaultFileName;
368
368
  if (!filename) {
369
+ // @ts-expect-error ESLint < 10
369
370
  const jsFileName = context.getFilename();
370
371
  if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
371
372
  defaultFileName = jsFileName.replace(/\.[^.]*$/v, `.${ext}`);
@@ -130,7 +130,8 @@ export default iterateJsdoc(({
130
130
  */
131
131
  const isInAmbientContext = (subNode) => {
132
132
  return subNode.type === 'Program' ?
133
- /* c8 ignore next -- Support old ESLint */
133
+ /* c8 ignore next 2 -- Support old ESLint */
134
+ // @ts-expect-error ESLint < 10
134
135
  (context.filename ?? context.getFilename()).endsWith('.d.ts') :
135
136
  Boolean(
136
137
  /** @type {import('@typescript-eslint/types').TSESTree.VariableDeclaration} */ (
@@ -156,7 +157,8 @@ export default iterateJsdoc(({
156
157
  return false;
157
158
  }
158
159
 
159
- /* c8 ignore next -- Support old ESLint */
160
+ /* c8 ignore next 2 -- Support old ESLint */
161
+ // @ts-expect-error ESLint < 10
160
162
  if ((context.filename ?? context.getFilename()).endsWith('.d.ts') && [
161
163
  null, 'Program', undefined,
162
164
  ].includes(node?.parent?.type)) {
@@ -35,6 +35,7 @@ export default {
35
35
 
36
36
  /* c8 ignore next -- Fallback to deprecated method */
37
37
  const {
38
+ // @ts-expect-error ESLint < 10
38
39
  sourceCode = context.getSourceCode(),
39
40
  } = context;
40
41
  const settings = getSettings(context);
@@ -10,9 +10,13 @@ import {
10
10
  traverse,
11
11
  tryParse as tryParseType,
12
12
  } from '@es-joy/jsdoccomment';
13
+ import {
14
+ Linter,
15
+ } from 'eslint';
13
16
  import {
14
17
  parseImportsExports,
15
18
  } from 'parse-imports-exports';
19
+ import semver from 'semver';
16
20
  import toValidIdentifier from 'to-valid-identifier';
17
21
 
18
22
  export default iterateJsdoc(({
@@ -66,6 +70,60 @@ export default iterateJsdoc(({
66
70
  return tag;
67
71
  });
68
72
 
73
+ /**
74
+ * Helper to insert an import statement at the top of the file.
75
+ * @param {string} importText - The import statement text (without newline)
76
+ * @returns {((fixer: import('eslint').Rule.RuleFixer) => import('eslint').Rule.Fix|void)} - Fixer function for ESLint
77
+ */
78
+ const createImportInserter = (importText) => {
79
+ return (fixer) => {
80
+ const programNode = sourceCode.ast;
81
+ const commentNodes = sourceCode.getCommentsBefore(programNode);
82
+
83
+ /* c8 ignore start -- ESLint < 10 */
84
+ if (commentNodes[0]) {
85
+ return fixer.insertTextBefore(
86
+ // @ts-expect-error - Comment is compatible with Node in practice
87
+ commentNodes[0],
88
+ `${importText}\n${indent}`,
89
+ );
90
+ }
91
+
92
+ // For ESLint < 10, use the simple approach of inserting before programNode
93
+ if (semver.lt(Linter.version, '10.0.0')) {
94
+ return fixer.insertTextBefore(
95
+ programNode,
96
+ importText,
97
+ );
98
+ }
99
+
100
+ // For ESLint 10+, handle the changed Program node range
101
+ const sourceText = sourceCode.getText();
102
+ const hasCode = programNode.body && programNode.body.length > 0;
103
+ const leadingMatch = hasCode ? sourceText.match(/^(\n[ \t]*)/v) : null;
104
+ if (leadingMatch) {
105
+ const leading = leadingMatch[1];
106
+ return fixer.replaceTextRange(
107
+ [
108
+ leading.length, leading.length,
109
+ ],
110
+ `${importText}\n${leading.slice(1)}`,
111
+ );
112
+ }
113
+
114
+ const startsWithNewline = sourceText[0] === '\n';
115
+ return fixer.replaceTextRange(
116
+ startsWithNewline ? [
117
+ 0, 1,
118
+ ] : [
119
+ 0, 0,
120
+ ],
121
+ `${importText}\n`,
122
+ );
123
+ /* c8 ignore end -- ESLint < 10 */
124
+ };
125
+ };
126
+
69
127
  /**
70
128
  * @param {import('@es-joy/jsdoccomment').JsdocTagWithInline} tag
71
129
  */
@@ -365,16 +423,9 @@ export default iterateJsdoc(({
365
423
  tag,
366
424
  enableFixer ? (fixer) => {
367
425
  getFixer(element.value, [])();
368
-
369
- const programNode = sourceCode.ast;
370
- const commentNodes = sourceCode.getCommentsBefore(programNode);
371
- return fixer.insertTextBefore(
372
- // @ts-expect-error Ok
373
- commentNodes[0] ?? programNode,
374
- `/** @import * as ${toValidIdentifier(element.value)} from '${element.value}'; */${
375
- commentNodes[0] ? '\n' + indent : ''
376
- }`,
377
- );
426
+ return createImportInserter(
427
+ `/** @import * as ${toValidIdentifier(element.value)} from '${element.value}'; */`,
428
+ )(fixer);
378
429
  } : null,
379
430
  );
380
431
  return;
@@ -387,17 +438,9 @@ export default iterateJsdoc(({
387
438
  tag,
388
439
  enableFixer ? (fixer) => {
389
440
  getFixer(element.value, [])();
390
-
391
- const programNode = sourceCode.ast;
392
- const commentNodes = sourceCode.getCommentsBefore(programNode);
393
-
394
- return fixer.insertTextBefore(
395
- // @ts-expect-error Ok
396
- commentNodes[0] ?? programNode,
397
- `/** @import ${element.value} from '${element.value}'; */${
398
- commentNodes[0] ? '\n' + indent : ''
399
- }`,
400
- );
441
+ return createImportInserter(
442
+ `/** @import ${element.value} from '${element.value}'; */`,
443
+ )(fixer);
401
444
  } : null,
402
445
  );
403
446
  return;
@@ -418,22 +461,14 @@ export default iterateJsdoc(({
418
461
  )();
419
462
  }
420
463
 
421
- const programNode = sourceCode.ast;
422
- const commentNodes = sourceCode.getCommentsBefore(programNode);
423
- return fixer.insertTextBefore(
424
- // @ts-expect-error Ok
425
- commentNodes[0] ?? programNode,
426
- outputType === 'namespaced-import' ?
427
- `/** @import * as ${toValidIdentifier(element.value)} from '${element.value}'; */${
428
- commentNodes[0] ? '\n' + indent : ''
429
- }` :
430
- `/** @import { ${toValidIdentifier(
431
- /* c8 ignore next -- TS */
432
- pathSegments.at(-1) ?? '',
433
- )} } from '${element.value}'; */${
434
- commentNodes[0] ? '\n' + indent : ''
435
- }`,
436
- );
464
+ const importText = outputType === 'namespaced-import' ?
465
+ `/** @import * as ${toValidIdentifier(element.value)} from '${element.value}'; */` :
466
+ `/** @import { ${toValidIdentifier(
467
+ /* c8 ignore next -- TS */
468
+ pathSegments.at(-1) ?? '',
469
+ )} } from '${element.value}'; */`;
470
+
471
+ return createImportInserter(importText)(fixer);
437
472
  } : null,
438
473
  );
439
474
  });
@@ -536,6 +536,7 @@ export default {
536
536
  create (context) {
537
537
  /* c8 ignore next -- Fallback to deprecated method */
538
538
  const {
539
+ // @ts-expect-error ESLint < 10
539
540
  sourceCode = context.getSourceCode(),
540
541
  } = context;
541
542
  const settings = getSettings(context);
@@ -876,7 +877,6 @@ export default {
876
877
  },
877
878
  meta: {
878
879
  docs: {
879
- category: 'Stylistic Issues',
880
880
  description: 'Checks for presence of JSDoc comments, on functions and potentially other contexts (optionally limited to exports).',
881
881
  recommended: true,
882
882
  url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-jsdoc.md#repos-sticky-header',
@@ -1,6 +1,7 @@
1
1
  import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
3
  export default iterateJsdoc(({
4
+ context,
4
5
  utils,
5
6
  }) => {
6
7
  const propertyAssociatedTags = utils.filterTags(({
@@ -18,6 +19,23 @@ export default iterateJsdoc(({
18
19
  tagName: 'property',
19
20
  }));
20
21
 
22
+ if (!targetTagName) {
23
+ context.report({
24
+ loc: {
25
+ end: {
26
+ column: 1,
27
+ line: 1,
28
+ },
29
+ start: {
30
+ column: 1,
31
+ line: 1,
32
+ },
33
+ },
34
+ message: 'Cannot prohibit `@property` in the `tagNamePreference` setting while using the `require-property` rule.',
35
+ });
36
+ return;
37
+ }
38
+
21
39
  if (utils.hasATag([
22
40
  targetTagName,
23
41
  ])) {
@@ -106,6 +106,7 @@ export default iterateJsdoc(({
106
106
  };
107
107
  /* c8 ignore next -- Fallback to deprecated method */
108
108
  const {
109
+ // @ts-expect-error ESLint < 10
109
110
  sourceCode = context.getSourceCode(),
110
111
  } = context;
111
112
  const exported = exportParser.isUncommentedExport(