@depup/eslint-plugin-jsdoc 65.0.1-depup.0 → 65.1.0-depup.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/README.md CHANGED
@@ -13,8 +13,8 @@ npm install @depup/eslint-plugin-jsdoc
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [eslint-plugin-jsdoc](https://www.npmjs.com/package/eslint-plugin-jsdoc) @ 65.0.1 |
17
- | Processed | 2026-09-30 |
16
+ | Original | [eslint-plugin-jsdoc](https://www.npmjs.com/package/eslint-plugin-jsdoc) @ 65.1.0 |
17
+ | Processed | 2026-10-04 |
18
18
  | Smoke test | passed |
19
19
  | Deps updated | 1 |
20
20
 
package/changes.json CHANGED
@@ -5,6 +5,6 @@
5
5
  "to": "^8.71.0"
6
6
  }
7
7
  },
8
- "timestamp": "2026-09-30T16:12:26.038Z",
8
+ "timestamp": "2026-10-04T01:27:27.502Z",
9
9
  "totalUpdated": 1
10
10
  }
package/dist/rules.d.ts CHANGED
@@ -266,7 +266,19 @@ export interface Rules {
266
266
  ];
267
267
 
268
268
  /** Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode). */
269
- "jsdoc/check-syntax": [];
269
+ "jsdoc/check-syntax":
270
+ | []
271
+ | [
272
+ {
273
+ /**
274
+ * Whether to enable the fixer to replace the Closure Compiler style `{type=}`
275
+ * with `{type} [name]` on `@param` and `@property` tags, and with
276
+ * `{type|undefined}` on other tags.
277
+ * Defaults to `false`.
278
+ */
279
+ enableFixer?: boolean;
280
+ }
281
+ ];
270
282
 
271
283
  /** Reports invalid block tag names. */
272
284
  "jsdoc/check-tag-names":
@@ -3301,7 +3313,7 @@ export interface Rules {
3301
3313
  */
3302
3314
  stringQuotes?: "double" | "single";
3303
3315
  /**
3304
- * If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing puncutation is only added when the type is multiline
3316
+ * If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing punctuation is only added when the type is multiline
3305
3317
  */
3306
3318
  trailingPunctuationMultilineOnly?: boolean;
3307
3319
  /**
package/package.json CHANGED
@@ -168,7 +168,7 @@
168
168
  "test-cov": "TIMING=1 c8 --reporter text pnpm run test-no-cov",
169
169
  "test-index": "pnpm run test-no-cov test/rules/index.js"
170
170
  },
171
- "version": "65.0.1-depup.0",
171
+ "version": "65.1.0-depup.0",
172
172
  "depup": {
173
173
  "changes": {
174
174
  "@typescript-eslint/utils": {
@@ -178,8 +178,8 @@
178
178
  },
179
179
  "depsUpdated": 1,
180
180
  "originalPackage": "eslint-plugin-jsdoc",
181
- "originalVersion": "65.0.1",
182
- "processedAt": "2026-09-30T16:12:44.702Z",
181
+ "originalVersion": "65.1.0",
182
+ "processedAt": "2026-10-04T01:27:44.935Z",
183
183
  "smokeTest": "passed"
184
184
  }
185
185
  }
@@ -25,16 +25,6 @@ const maskCodeBlocks = (str) => {
25
25
  });
26
26
  };
27
27
 
28
- /**
29
- * @param {string[]} lines
30
- * @param {number} lineIndex
31
- * @returns {number}
32
- */
33
- const getLineNumber = (lines, lineIndex) => {
34
- const precedingText = lines.slice(0, lineIndex).join('\n');
35
- return precedingText.split('\n').length;
36
- };
37
-
38
28
  export default iterateJsdoc(({
39
29
  context,
40
30
  jsdocNode,
@@ -75,7 +65,7 @@ export default iterateJsdoc(({
75
65
  // Check for no space between the asterisk prefix and content
76
66
  if (!allowNoSpaceAfterAsterisk && /^(?:\/?\**|[\t ]*)\*[^\s*\/]/v.test(line)) {
77
67
  report('There must be a space after the asterisk.', null, {
78
- line: getLineNumber(lines, lineIndex),
68
+ line: lineIndex,
79
69
  });
80
70
  return;
81
71
  }
@@ -91,7 +81,7 @@ export default iterateJsdoc(({
91
81
  // If this is a tag line with indentation, always report
92
82
  if (/^@\w+/v.test(afterIndent)) {
93
83
  report('There must be no indentation.', null, {
94
- line: getLineNumber(lines, lineIndex),
84
+ line: lineIndex,
95
85
  });
96
86
  return;
97
87
  }
@@ -99,7 +89,7 @@ export default iterateJsdoc(({
99
89
  // If we haven't seen any content yet (main description first line) and there's content, report
100
90
  if (!hasSeenContent && afterIndent.trim().length > 0) {
101
91
  report('There must be no indentation.', null, {
102
- line: getLineNumber(lines, lineIndex),
92
+ line: lineIndex,
103
93
  });
104
94
  return;
105
95
  }
@@ -112,7 +102,7 @@ export default iterateJsdoc(({
112
102
  } else if (indentAmount < currentSectionIndent) {
113
103
  // Indentation is less than the established level (inconsistent)
114
104
  report('There must be no indentation.', null, {
115
- line: getLineNumber(lines, lineIndex),
105
+ line: lineIndex,
116
106
  });
117
107
  return;
118
108
  }
@@ -128,8 +118,8 @@ export default iterateJsdoc(({
128
118
  hasSeenContent = true;
129
119
  }
130
120
 
131
- // Reset section indent when we encounter a tag
132
- if (/@\w+/v.test(line)) {
121
+ // Reset section indent when we encounter a block tag
122
+ if (/^(?:\/?\**|[\t ]*)\*[ \t]*@\w+/v.test(line)) {
133
123
  currentSectionIndent = null;
134
124
  }
135
125
  }
@@ -1,20 +1,116 @@
1
1
  import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
+ // Closure's `{type=} name` is written `{type} [name]` in JSDoc/TypeScript
4
+ const namedTags = new Set([
5
+ 'arg', 'argument', 'param', 'prop', 'property',
6
+ ]);
7
+
8
+ // Types that do not need parentheses before `|undefined`
9
+ const simpleType = /^[\w$.]+$/v;
10
+
11
+ /**
12
+ * Builds the fix for a tag with a Closure style optional type (`{type=}`), if
13
+ * there is one.
14
+ *
15
+ * Named tags (`@param {type=} name`) become `{type} [name]`; for other tags
16
+ * (or a missing or defaulted name), the type is joined with `undefined`.
17
+ * @param {import('comment-parser').Spec} tag
18
+ * @returns {() => void}
19
+ */
20
+ const getFix = (tag) => {
21
+ const {
22
+ source,
23
+ } = tag;
24
+
25
+ // For a type over several lines, the end of the type is on the line that has the name
26
+ const lastTypeLine = /** @type {import('comment-parser').Line} */ (source.findLast(({
27
+ tokens,
28
+ }) => {
29
+ return tokens.type.endsWith('=}');
30
+ }));
31
+
32
+ const firstTypeLine = /** @type {import('comment-parser').Line} */ (source.find(({
33
+ tokens,
34
+ }) => {
35
+ return tokens.type;
36
+ }));
37
+
38
+ const nameTokens = source.find(({
39
+ tokens,
40
+ }) => {
41
+ return tokens.name;
42
+ })?.tokens;
43
+
44
+ // A name with a default (`[foo=bar]`) is already bracketed; a bare `foo=bar` is not a valid name
45
+ if (namedTags.has(tag.tag) && nameTokens && (!nameTokens.name.includes('=') || nameTokens.name.startsWith('['))) {
46
+ return () => {
47
+ lastTypeLine.tokens.type = `${lastTypeLine.tokens.type.slice(0, -2)}}`;
48
+ if (!nameTokens.name.startsWith('[')) {
49
+ nameTokens.name = `[${nameTokens.name}]`;
50
+ }
51
+
52
+ tag.optional = true;
53
+ };
54
+ }
55
+
56
+ const isSingleLine = firstTypeLine === lastTypeLine;
57
+ const inner = lastTypeLine.tokens.type.slice(isSingleLine ? 1 : 0, -2);
58
+ if (isSingleLine && simpleType.test(inner)) {
59
+ return () => {
60
+ lastTypeLine.tokens.type = `{${inner}|undefined}`;
61
+ };
62
+ }
63
+
64
+ return () => {
65
+ firstTypeLine.tokens.type = `{(${firstTypeLine.tokens.type.slice(1)}`;
66
+ lastTypeLine.tokens.type = `${lastTypeLine.tokens.type.slice(0, -2)})|undefined}`;
67
+ };
68
+ };
69
+
3
70
  export default iterateJsdoc(({
71
+ context,
4
72
  jsdoc,
5
73
  report,
6
74
  settings,
75
+ utils,
7
76
  }) => {
77
+ const {
78
+ enableFixer = false,
79
+ } = context.options[0] || {};
80
+
8
81
  const {
9
82
  mode,
10
83
  } = settings;
11
84
 
12
85
  // Don't check for "permissive" and "closure"
13
86
  if (mode === 'jsdoc' || mode === 'typescript') {
87
+ /** @type {import('comment-parser').Spec|undefined} */
88
+ let firstTag;
89
+ /** @type {(() => void)[]} */
90
+ const fixes = [];
91
+
14
92
  for (const tag of jsdoc.tags) {
15
- if (tag.type.slice(-1) === '=') {
16
- report('Syntax should not be Google Closure Compiler style.', null, tag);
17
- break;
93
+ if (tag.type.slice(-1) !== '=') {
94
+ continue;
95
+ }
96
+
97
+ firstTag ??= tag;
98
+
99
+ if (enableFixer) {
100
+ fixes.push(getFix(tag));
101
+ }
102
+ }
103
+
104
+ if (firstTag) {
105
+ const message = 'Syntax should not be Google Closure Compiler style.';
106
+ if (fixes.length) {
107
+ utils.reportJSDoc(message, firstTag, () => {
108
+ for (const fix of fixes) {
109
+ fix();
110
+ }
111
+ });
112
+ } else {
113
+ report(message, null, firstTag);
18
114
  }
19
115
  }
20
116
  }
@@ -25,6 +121,22 @@ export default iterateJsdoc(({
25
121
  description: 'Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode).',
26
122
  url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-syntax.md#repos-sticky-header',
27
123
  },
124
+ fixable: 'code',
125
+ schema: [
126
+ {
127
+ additionalProperties: false,
128
+ properties: {
129
+ enableFixer: {
130
+ description: `Whether to enable the fixer to replace the Closure Compiler style \`{type=}\`
131
+ with \`{type} [name]\` on \`@param\` and \`@property\` tags, and with
132
+ \`{type|undefined}\` on other tags.
133
+ Defaults to \`false\`.`,
134
+ type: 'boolean',
135
+ },
136
+ },
137
+ type: 'object',
138
+ },
139
+ ],
28
140
  type: 'suggestion',
29
141
  },
30
142
  });
@@ -668,7 +668,7 @@ or \`double\`. Defaults to 'double'.`,
668
668
  type: 'string',
669
669
  },
670
670
  trailingPunctuationMultilineOnly: {
671
- description: 'If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing puncutation is only added when the type is multiline',
671
+ description: 'If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing punctuation is only added when the type is multiline',
672
672
  type: 'boolean',
673
673
  },
674
674
  typeBracketSpacing: {
package/src/rules.d.ts CHANGED
@@ -266,7 +266,19 @@ export interface Rules {
266
266
  ];
267
267
 
268
268
  /** Reports against syntax not valid for the mode (e.g., Google Closure Compiler in non-Closure mode). */
269
- "jsdoc/check-syntax": [];
269
+ "jsdoc/check-syntax":
270
+ | []
271
+ | [
272
+ {
273
+ /**
274
+ * Whether to enable the fixer to replace the Closure Compiler style `{type=}`
275
+ * with `{type} [name]` on `@param` and `@property` tags, and with
276
+ * `{type|undefined}` on other tags.
277
+ * Defaults to `false`.
278
+ */
279
+ enableFixer?: boolean;
280
+ }
281
+ ];
270
282
 
271
283
  /** Reports invalid block tag names. */
272
284
  "jsdoc/check-tag-names":
@@ -3301,7 +3313,7 @@ export interface Rules {
3301
3313
  */
3302
3314
  stringQuotes?: "double" | "single";
3303
3315
  /**
3304
- * If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing puncutation is only added when the type is multiline
3316
+ * If `objectFieldSeparatorTrailingPunctuation` is set, this will determine whether the trailing punctuation is only added when the type is multiline
3305
3317
  */
3306
3318
  trailingPunctuationMultilineOnly?: boolean;
3307
3319
  /**