eslint-plugin-jsdoc 51.4.0 → 52.0.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.
Files changed (100) hide show
  1. package/dist/alignTransform.cjs +1 -1
  2. package/dist/alignTransform.cjs.map +1 -1
  3. package/dist/generateRule.cjs +5 -5
  4. package/dist/generateRule.cjs.map +1 -1
  5. package/dist/getJsdocProcessorPlugin.cjs +8 -8
  6. package/dist/getJsdocProcessorPlugin.cjs.map +1 -1
  7. package/dist/iterateJsdoc.cjs +3 -3
  8. package/dist/iterateJsdoc.cjs.map +1 -1
  9. package/dist/jsdocUtils.cjs +9 -9
  10. package/dist/jsdocUtils.cjs.map +1 -1
  11. package/dist/rules/checkAlignment.cjs +1 -1
  12. package/dist/rules/checkAlignment.cjs.map +1 -1
  13. package/dist/rules/checkExamples.cjs +5 -5
  14. package/dist/rules/checkExamples.cjs.map +1 -1
  15. package/dist/rules/checkIndentation.cjs +6 -6
  16. package/dist/rules/checkIndentation.cjs.map +1 -1
  17. package/dist/rules/checkLineAlignment.cjs +3 -3
  18. package/dist/rules/checkLineAlignment.cjs.map +1 -1
  19. package/dist/rules/checkTagNames.cjs +1 -1
  20. package/dist/rules/checkTagNames.cjs.map +1 -1
  21. package/dist/rules/checkTemplateNames.cjs +1 -1
  22. package/dist/rules/checkTemplateNames.cjs.map +1 -1
  23. package/dist/rules/checkTypes.cjs +2 -2
  24. package/dist/rules/checkTypes.cjs.map +1 -1
  25. package/dist/rules/checkValues.cjs +1 -1
  26. package/dist/rules/checkValues.cjs.map +1 -1
  27. package/dist/rules/emptyTags.cjs +1 -1
  28. package/dist/rules/emptyTags.cjs.map +1 -1
  29. package/dist/rules/importsAsDependencies.cjs +2 -2
  30. package/dist/rules/importsAsDependencies.cjs.map +1 -1
  31. package/dist/rules/linesBeforeBlock.cjs +1 -1
  32. package/dist/rules/linesBeforeBlock.cjs.map +1 -1
  33. package/dist/rules/matchDescription.cjs +4 -4
  34. package/dist/rules/matchDescription.cjs.map +1 -1
  35. package/dist/rules/matchName.cjs +5 -2
  36. package/dist/rules/matchName.cjs.map +1 -1
  37. package/dist/rules/noBadBlocks.cjs +2 -2
  38. package/dist/rules/noBadBlocks.cjs.map +1 -1
  39. package/dist/rules/noBlankBlockDescriptions.cjs +2 -2
  40. package/dist/rules/noBlankBlockDescriptions.cjs.map +1 -1
  41. package/dist/rules/noDefaults.cjs +2 -2
  42. package/dist/rules/noDefaults.cjs.map +1 -1
  43. package/dist/rules/noMultiAsterisks.cjs +6 -6
  44. package/dist/rules/noMultiAsterisks.cjs.map +1 -1
  45. package/dist/rules/noUndefinedTypes.cjs +4 -4
  46. package/dist/rules/noUndefinedTypes.cjs.map +1 -1
  47. package/dist/rules/requireAsteriskPrefix.cjs +1 -0
  48. package/dist/rules/requireAsteriskPrefix.cjs.map +1 -1
  49. package/dist/rules/requireDescriptionCompleteSentence.cjs +21 -21
  50. package/dist/rules/requireDescriptionCompleteSentence.cjs.map +1 -1
  51. package/dist/rules/requireHyphenBeforeParamDescription.cjs +3 -3
  52. package/dist/rules/requireHyphenBeforeParamDescription.cjs.map +1 -1
  53. package/dist/rules/requireJsdoc.cjs +1 -1
  54. package/dist/rules/requireJsdoc.cjs.map +1 -1
  55. package/dist/rules/requireReturnsCheck.cjs +1 -1
  56. package/dist/rules/requireReturnsCheck.cjs.map +1 -1
  57. package/dist/rules/requireTemplate.cjs +2 -2
  58. package/dist/rules/requireTemplate.cjs.map +1 -1
  59. package/dist/rules/sortTags.cjs +1 -0
  60. package/dist/rules/sortTags.cjs.map +1 -1
  61. package/dist/rules/tagLines.cjs +2 -2
  62. package/dist/rules/tagLines.cjs.map +1 -1
  63. package/dist/rules/textEscaping.cjs +4 -4
  64. package/dist/rules/textEscaping.cjs.map +1 -1
  65. package/dist/rules/validTypes.cjs +1 -1
  66. package/dist/rules/validTypes.cjs.map +1 -1
  67. package/eslint.config.js +6 -0
  68. package/package.json +1 -1
  69. package/src/alignTransform.js +1 -1
  70. package/src/getJsdocProcessorPlugin.js +8 -8
  71. package/src/iterateJsdoc.js +3 -3
  72. package/src/jsdocUtils.js +9 -9
  73. package/src/rules/checkAlignment.js +1 -1
  74. package/src/rules/checkExamples.js +5 -5
  75. package/src/rules/checkIndentation.js +6 -6
  76. package/src/rules/checkLineAlignment.js +3 -3
  77. package/src/rules/checkTagNames.js +1 -1
  78. package/src/rules/checkTemplateNames.js +1 -1
  79. package/src/rules/checkTypes.js +2 -2
  80. package/src/rules/checkValues.js +1 -1
  81. package/src/rules/emptyTags.js +1 -1
  82. package/src/rules/importsAsDependencies.js +2 -2
  83. package/src/rules/linesBeforeBlock.js +1 -1
  84. package/src/rules/matchDescription.js +4 -4
  85. package/src/rules/matchName.js +5 -2
  86. package/src/rules/noBadBlocks.js +2 -2
  87. package/src/rules/noBlankBlockDescriptions.js +2 -2
  88. package/src/rules/noDefaults.js +2 -2
  89. package/src/rules/noMultiAsterisks.js +6 -6
  90. package/src/rules/noUndefinedTypes.js +4 -4
  91. package/src/rules/requireAsteriskPrefix.js +1 -0
  92. package/src/rules/requireDescriptionCompleteSentence.js +21 -21
  93. package/src/rules/requireHyphenBeforeParamDescription.js +3 -3
  94. package/src/rules/requireJsdoc.js +1 -1
  95. package/src/rules/requireReturnsCheck.js +1 -1
  96. package/src/rules/requireTemplate.js +2 -2
  97. package/src/rules/sortTags.js +1 -0
  98. package/src/rules/tagLines.js +2 -2
  99. package/src/rules/textEscaping.js +4 -4
  100. package/src/rules/validTypes.js +1 -1
package/src/jsdocUtils.js CHANGED
@@ -647,12 +647,12 @@ const getPreferredTagNameSimple = (
647
647
  value,
648
648
  ]) => {
649
649
  return [
650
- key.replace(/^tag /u, ''), value,
650
+ key.replace(/^tag /v, ''), value,
651
651
  ];
652
652
  }),
653
653
  );
654
654
 
655
- if (Object.prototype.hasOwnProperty.call(tagPreferenceFixed, name)) {
655
+ if (Object.hasOwn(tagPreferenceFixed, name)) {
656
656
  return tagPreferenceFixed[name];
657
657
  }
658
658
 
@@ -1480,7 +1480,7 @@ const hasThrowValue = (node, innerFunction) => {
1480
1480
  */
1481
1481
  /*
1482
1482
  const isInlineTag = (tag) => {
1483
- return /^(@link|@linkcode|@linkplain|@tutorial) /u.test(tag);
1483
+ return /^(@link|@linkcode|@linkplain|@tutorial) /v.test(tag);
1484
1484
  };
1485
1485
  */
1486
1486
 
@@ -1495,7 +1495,7 @@ const parseClosureTemplateTag = (tag) => {
1495
1495
  return tag.name
1496
1496
  .split(',')
1497
1497
  .map((type) => {
1498
- return type.trim().replace(/^\[?(?<name>.*?)=.*$/u, '$<name>');
1498
+ return type.trim().replace(/^\[?(?<name>.*?)=.*$/v, '$<name>');
1499
1499
  });
1500
1500
  };
1501
1501
 
@@ -1649,7 +1649,7 @@ const getTagsByType = (context, mode, tags) => {
1649
1649
  * @returns {string}
1650
1650
  */
1651
1651
  const getIndent = (sourceCode) => {
1652
- return (sourceCode.text.match(/^\n*([ \t]+)/u)?.[1] ?? '') + ' ';
1652
+ return (sourceCode.text.match(/^\n*([ \t]+)/v)?.[1] ?? '') + ' ';
1653
1653
  };
1654
1654
 
1655
1655
  /**
@@ -1789,7 +1789,7 @@ const exemptSpeciaMethods = (jsdoc, node, context, schema) => {
1789
1789
  * @returns {string}
1790
1790
  */
1791
1791
  const dropPathSegmentQuotes = (str) => {
1792
- return str.replaceAll(/\.(['"])(.*)\1/gu, '.$2');
1792
+ return str.replaceAll(/\.(['"])(.*)\1/gv, '.$2');
1793
1793
  };
1794
1794
 
1795
1795
  /**
@@ -1822,8 +1822,8 @@ const pathDoesNotBeginWith = (name, otherPathName) => {
1822
1822
  * @returns {RegExp}
1823
1823
  */
1824
1824
  const getRegexFromString = (regexString, requiredFlags) => {
1825
- const match = regexString.match(/^\/(.*)\/([gimyus]*)$/us);
1826
- let flags = 'u';
1825
+ const match = regexString.match(/^\/(.*)\/([gimyvus]*)$/vs);
1826
+ let flags = 'v';
1827
1827
  let regex = regexString;
1828
1828
  if (match) {
1829
1829
  [
@@ -1831,7 +1831,7 @@ const getRegexFromString = (regexString, requiredFlags) => {
1831
1831
  flags,
1832
1832
  ] = match;
1833
1833
  if (!flags) {
1834
- flags = 'u';
1834
+ flags = 'v';
1835
1835
  }
1836
1836
  }
1837
1837
 
@@ -5,7 +5,7 @@ import iterateJsdoc from '../iterateJsdoc.js';
5
5
  * @returns {string}
6
6
  */
7
7
  const trimStart = (string) => {
8
- return string.replace(/^\s+/u, '');
8
+ return string.replace(/^\s+/v, '');
9
9
  };
10
10
 
11
11
  export default iterateJsdoc(({
@@ -16,14 +16,14 @@ const preTagSpaceLength = 1;
16
16
  // If a space is present, we should ignore it
17
17
  const firstLinePrefixLength = preTagSpaceLength;
18
18
 
19
- const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/u;
19
+ const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/v;
20
20
 
21
21
  /**
22
22
  * @param {string} str
23
23
  * @returns {string}
24
24
  */
25
25
  const escapeStringRegexp = (str) => {
26
- return str.replaceAll(/[.*+?^${}()|[\]\\]/gu, '\\$&');
26
+ return str.replaceAll(/[.*+?^$\{\}\(\)\|\[\]\\]/gv, '\\$&');
27
27
  };
28
28
 
29
29
  /**
@@ -32,7 +32,7 @@ const escapeStringRegexp = (str) => {
32
32
  * @returns {import('../iterateJsdoc.js').Integer}
33
33
  */
34
34
  const countChars = (str, ch) => {
35
- return (str.match(new RegExp(escapeStringRegexp(ch), 'gu')) || []).length;
35
+ return (str.match(new RegExp(escapeStringRegexp(ch), 'gv')) || []).length;
36
36
  };
37
37
 
38
38
  /** @type {import('eslint').Linter.RulesRecord} */
@@ -244,7 +244,7 @@ export default iterateJsdoc(({
244
244
  const cliConfigStr = JSON.stringify(cliConfig);
245
245
 
246
246
  const src = paddedIndent ?
247
- string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gu'), '\n') :
247
+ string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gv'), '\n') :
248
248
  string;
249
249
 
250
250
  // Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api
@@ -345,7 +345,7 @@ export default iterateJsdoc(({
345
345
  if (!filename) {
346
346
  const jsFileName = context.getFilename();
347
347
  if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
348
- defaultFileName = jsFileName.replace(/\.[^.]*$/u, `.${ext}`);
348
+ defaultFileName = jsFileName.replace(/\.[^.]*$/v, `.${ext}`);
349
349
  } else {
350
350
  defaultFileName = `dummy.${ext}`;
351
351
  }
@@ -6,10 +6,10 @@ import iterateJsdoc from '../iterateJsdoc.js';
6
6
  * @returns {string}
7
7
  */
8
8
  const maskExcludedContent = (str, excludeTags) => {
9
- const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@\\w+\\s|\\/))`, 'gu');
9
+ const regContent = new RegExp(`([ \\t]+\\*)[ \\t]@(?:${excludeTags.join('|')})(?=[ \\n])([\\w\\|\\W]*?\\n)(?=[ \\t]*\\*(?:[ \\t]*@\\w+\\s|\\/))`, 'gv');
10
10
 
11
11
  return str.replace(regContent, (_match, margin, code) => {
12
- return (margin + '\n').repeat(code.match(/\n/gu).length);
12
+ return (margin + '\n').repeat(code.match(/\n/gv).length);
13
13
  });
14
14
  };
15
15
 
@@ -18,10 +18,10 @@ const maskExcludedContent = (str, excludeTags) => {
18
18
  * @returns {string}
19
19
  */
20
20
  const maskCodeBlocks = (str) => {
21
- const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@\w+\s)|\/))/gu;
21
+ const regContent = /([ \t]+\*)[ \t]```[^\n]*?([\w\|\W]*?\n)(?=[ \t]*\*(?:[ \t]*(?:```|@\w+\s)|\/))/gv;
22
22
 
23
23
  return str.replaceAll(regContent, (_match, margin, code) => {
24
- return (margin + '\n').repeat(code.match(/\n/gu).length);
24
+ return (margin + '\n').repeat(code.match(/\n/gv).length);
25
25
  });
26
26
  };
27
27
 
@@ -38,12 +38,12 @@ export default iterateJsdoc(({
38
38
  ],
39
39
  } = options;
40
40
 
41
- const reg = /^(?:\/?\**|[ \t]*)\*[ \t]{2}/gmu;
41
+ const reg = /^(?:\/?\**|[ \t]*)\*[ \t]{2}/gmv;
42
42
  const textWithoutCodeBlocks = maskCodeBlocks(sourceCode.getText(jsdocNode));
43
43
  const text = excludeTags.length ? maskExcludedContent(textWithoutCodeBlocks, excludeTags) : textWithoutCodeBlocks;
44
44
 
45
45
  if (reg.test(text)) {
46
- const lineBreaks = text.slice(0, reg.lastIndex).match(/\n/gu) || [];
46
+ const lineBreaks = text.slice(0, reg.lastIndex).match(/\n/gv) || [];
47
47
  report('There must be no indentation.', null, {
48
48
  line: lineBreaks.length,
49
49
  });
@@ -93,8 +93,8 @@ const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
93
93
  };
94
94
 
95
95
  const postHyphenSpacing = customSpacings?.postHyphen ?? 1;
96
- const exactHyphenSpacing = new RegExp(`^\\s*-\\s{${postHyphenSpacing},${postHyphenSpacing}}(?!\\s)`, 'u');
97
- const hasNoHyphen = !(/^\s*-(?!$)(?=\s)/u).test(tokens.description);
96
+ const exactHyphenSpacing = new RegExp(`^\\s*-\\s{${postHyphenSpacing},${postHyphenSpacing}}(?!\\s)`, 'v');
97
+ const hasNoHyphen = !(/^\s*-(?!$)(?=\s)/v).test(tokens.description);
98
98
  const hasExactHyphenSpacing = exactHyphenSpacing.test(
99
99
  tokens.description,
100
100
  );
@@ -144,7 +144,7 @@ const checkNotAlignedPerTag = (utils, tag, customSpacings) => {
144
144
  }
145
145
 
146
146
  if (!hasExactHyphenSpacing) {
147
- const hyphenSpacing = /^\s*-\s+/u;
147
+ const hyphenSpacing = /^\s*-\s+/v;
148
148
  tokens.description = tokens.description.replace(
149
149
  hyphenSpacing, '-' + ''.padStart(postHyphenSpacing, ' '),
150
150
  );
@@ -267,7 +267,7 @@ export default iterateJsdoc(({
267
267
  if (preferredTagName !== tagName) {
268
268
  report(message, (fixer) => {
269
269
  const replacement = sourceCode.getText(jsdocNode).replace(
270
- new RegExp(`@${escapeStringRegexp(tagName)}\\b`, 'u'),
270
+ new RegExp(`@${escapeStringRegexp(tagName)}\\b`, 'v'),
271
271
  `@${preferredTagName}`,
272
272
  );
273
273
 
@@ -73,7 +73,7 @@ export default iterateJsdoc(({
73
73
  const {
74
74
  name,
75
75
  } = tag;
76
- const names = name.split(/,\s*/u);
76
+ const names = name.split(/,\s*/v);
77
77
  for (const nme of names) {
78
78
  if (!usedNames.has(nme)) {
79
79
  report(`@template ${nme} not in use`, null, tag);
@@ -43,7 +43,7 @@ const adjustNames = (type, preferred, isGenericMatch, typeNodeName, node, parent
43
43
  parentMeta.dot = false;
44
44
  ret = 'Array';
45
45
  } else {
46
- const dotBracketEnd = preferred.match(/\.(?:<>)?$/u);
46
+ const dotBracketEnd = preferred.match(/\.(?:<>)?$/v);
47
47
  if (dotBracketEnd) {
48
48
  parentMeta.brackets = 'angle';
49
49
  parentMeta.dot = true;
@@ -69,7 +69,7 @@ const adjustNames = (type, preferred, isGenericMatch, typeNodeName, node, parent
69
69
 
70
70
  /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (
71
71
  node
72
- ).value = ret.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
72
+ ).value = ret.replace(/(?:\.|<>|\.<>|\[\])$/v, '');
73
73
 
74
74
  // For bare pseudo-types like `<>`
75
75
  if (!ret) {
@@ -29,7 +29,7 @@ export default iterateJsdoc(({
29
29
  const {
30
30
  allowedAuthors = null,
31
31
  allowedLicenses = null,
32
- licensePattern = '/([^\n\r]*)/gu',
32
+ licensePattern = '/([^\n\r]*)/gv',
33
33
  numericOnlyVariation = false,
34
34
  } = options;
35
35
 
@@ -53,7 +53,7 @@ export default iterateJsdoc(({
53
53
  const content = tag.name || tag.description || tag.type;
54
54
  if (content.trim() && (
55
55
  // Allow for JSDoc-block final asterisks
56
- key !== emptyTags.length - 1 || !(/^\s*\*+$/u).test(content)
56
+ key !== emptyTags.length - 1 || !(/^\s*\*+$/v).test(content)
57
57
  )) {
58
58
  const fix = () => {
59
59
  // By time of call in fixer, `tag` will have `line` added
@@ -83,10 +83,10 @@ export default iterateJsdoc(({
83
83
 
84
84
  if (nde.type === 'JsdocTypeImport') {
85
85
  let mod = nde.element.value.replace(
86
- /^(@[^/]+\/[^/]+|[^/]+).*$/u, '$1',
86
+ /^(@[^\/]+\/[^\/]+|[^\/]+).*$/v, '$1',
87
87
  );
88
88
 
89
- if ((/^[./]/u).test(mod)) {
89
+ if ((/^[.\/]/v).test(mod)) {
90
90
  return;
91
91
  }
92
92
 
@@ -68,7 +68,7 @@ export default iterateJsdoc(({
68
68
  // @ts-expect-error Should be a comment
69
69
  indent = /** @type {import('estree').Comment} */ (
70
70
  jsdocNode
71
- ).value.match(/^\*\n([\t ]*) \*/u)?.[1]?.slice(spaceDiff);
71
+ ).value.match(/^\*\n([\t ]*) \*/v)?.[1]?.slice(spaceDiff);
72
72
  if (!indent) {
73
73
  /** @type {import('eslint').AST.Token|import('estree').Comment|undefined} */
74
74
  let tokenPrior = tokenBefore;
@@ -2,7 +2,7 @@ import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
3
  // If supporting Node >= 10, we could loosen the default to this for the
4
4
  // initial letter: \\p{Upper}
5
- const matchDescriptionDefault = '^\n?([A-Z`\\d_][\\s\\S]*[.?!`]\\s*)?$';
5
+ const matchDescriptionDefault = '^\n?([A-Z`\\d_][\\s\\S]*[.?!`\\p{RGI_Emoji}]\\s*)?$';
6
6
 
7
7
  /**
8
8
  * @param {string} value
@@ -43,7 +43,7 @@ export default iterateJsdoc(({
43
43
  }
44
44
 
45
45
  if (mainDescriptionMatch === false && (
46
- !tag || !Object.prototype.hasOwnProperty.call(tags, tag.tag))
46
+ !tag || !Object.hasOwn(tags, tag.tag))
47
47
  ) {
48
48
  return;
49
49
  }
@@ -114,7 +114,7 @@ export default iterateJsdoc(({
114
114
  utils.forEachPreferredTag(tag, (matchingJsdocTag, targetTagName) => {
115
115
  const desc = (matchingJsdocTag.name + ' ' + utils.getTagDescription(matchingJsdocTag)).trim();
116
116
 
117
- if (hasNoTag(targetTagName) && !(/.+/u).test(desc)) {
117
+ if (hasNoTag(targetTagName) && !(/.+/v).test(desc)) {
118
118
  report(
119
119
  'JSDoc description must not be empty.',
120
120
  null,
@@ -150,7 +150,7 @@ export default iterateJsdoc(({
150
150
  tagsWithNames.some((tag) => {
151
151
  const desc = /** @type {string} */ (
152
152
  utils.getTagDescription(tag)
153
- ).replace(/^[- ]*/u, '')
153
+ ).replace(/^[\- ]*/v, '')
154
154
  .trim();
155
155
 
156
156
  return validateDescription(desc, tag);
@@ -38,7 +38,7 @@ export default iterateJsdoc(({
38
38
 
39
39
  let reported = false;
40
40
  for (const tag of applicableTags) {
41
- const tagName = tag.name.replace(/^\[/u, '').replace(/(=.*)?\]$/u, '');
41
+ const tagName = tag.name.replace(/^\[/v, '').replace(/(=.*)?\]$/v, '');
42
42
  const allowed = !allowNameRegex || allowNameRegex.test(tagName);
43
43
  const disallowed = disallowNameRegex && disallowNameRegex.test(tagName);
44
44
  const hasRegex = allowNameRegex || disallowNameRegex;
@@ -107,8 +107,8 @@ export default iterateJsdoc(({
107
107
  additionalProperties: false,
108
108
  properties: {
109
109
  match: {
110
- additionalProperties: false,
111
110
  items: {
111
+ additionalProperties: false,
112
112
  properties: {
113
113
  allowName: {
114
114
  type: 'string',
@@ -125,6 +125,9 @@ export default iterateJsdoc(({
125
125
  message: {
126
126
  type: 'string',
127
127
  },
128
+ replacement: {
129
+ type: 'string',
130
+ },
128
131
  tags: {
129
132
  items: {
130
133
  type: 'string',
@@ -5,8 +5,8 @@ import {
5
5
 
6
6
  // Neither a single nor 3+ asterisks are valid jsdoc per
7
7
  // https://jsdoc.app/about-getting-started.html#adding-documentation-comments-to-your-code
8
- const commentRegexp = /^\/\*(?!\*)/u;
9
- const extraAsteriskCommentRegexp = /^\/\*{3,}/u;
8
+ const commentRegexp = /^\/\*(?!\*)/v;
9
+ const extraAsteriskCommentRegexp = /^\/\*{3,}/v;
10
10
 
11
11
  export default iterateJsdoc(({
12
12
  allComments,
@@ -1,7 +1,7 @@
1
1
  import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
- const anyWhitespaceLines = /^\s*$/u;
4
- const atLeastTwoLinesWhitespace = /^[ \t]*\n[ \t]*\n\s*$/u;
3
+ const anyWhitespaceLines = /^\s*$/v;
4
+ const atLeastTwoLinesWhitespace = /^[ \t]*\n[ \t]*\n\s*$/v;
5
5
 
6
6
  export default iterateJsdoc(({
7
7
  jsdoc,
@@ -14,13 +14,13 @@ export default iterateJsdoc(({
14
14
  if (noOptionalParamNames && tag.optional) {
15
15
  utils.reportJSDoc(`Optional param names are not permitted on @${tag.tag}.`, tag, () => {
16
16
  utils.changeTag(tag, {
17
- name: tag.name.replace(/([^=]*)(=.+)?/u, '$1'),
17
+ name: tag.name.replace(/([^=]*)(=.+)?/v, '$1'),
18
18
  });
19
19
  });
20
20
  } else if (tag.default) {
21
21
  utils.reportJSDoc(`Defaults are not permitted on @${tag.tag}.`, tag, () => {
22
22
  utils.changeTag(tag, {
23
- name: tag.name.replace(/([^=]*)(=.+)?/u, '[$1]'),
23
+ name: tag.name.replace(/([^=]*)(=.+)?/v, '[$1]'),
24
24
  });
25
25
  });
26
26
  }
@@ -1,13 +1,13 @@
1
1
  import iterateJsdoc from '../iterateJsdoc.js';
2
2
 
3
- const middleAsterisksBlockWS = /^([\t ]|\*(?!\*))+/u;
4
- const middleAsterisksNoBlockWS = /^\*+/u;
3
+ const middleAsterisksBlockWS = /^([\t ]|\*(?!\*))+/v;
4
+ const middleAsterisksNoBlockWS = /^\*+/v;
5
5
 
6
- const endAsterisksSingleLineBlockWS = /\*((?:\*|(?: |\t))*)\*$/u;
7
- const endAsterisksMultipleLineBlockWS = /((?:\*|(?: |\t))*)\*$/u;
6
+ const endAsterisksSingleLineBlockWS = /\*((?:\*|(?: |\t))*)\*$/v;
7
+ const endAsterisksMultipleLineBlockWS = /((?:\*|(?: |\t))*)\*$/v;
8
8
 
9
- const endAsterisksSingleLineNoBlockWS = /\*(\**)\*$/u;
10
- const endAsterisksMultipleLineNoBlockWS = /(\**)\*$/u;
9
+ const endAsterisksSingleLineNoBlockWS = /\*(\**)\*$/v;
10
+ const endAsterisksMultipleLineNoBlockWS = /(\**)\*$/v;
11
11
 
12
12
  export default iterateJsdoc(({
13
13
  context,
@@ -50,7 +50,7 @@ const typescriptGlobals = [
50
50
  * @returns {undefined|string|false}
51
51
  */
52
52
  const stripPseudoTypes = (str) => {
53
- return str && str.replace(/(?:\.|<>|\.<>|\[\])$/u, '');
53
+ return str && str.replace(/(?:\.|<>|\.<>|\[\])$/v, '');
54
54
  };
55
55
 
56
56
  export default iterateJsdoc(({
@@ -115,7 +115,7 @@ export default iterateJsdoc(({
115
115
  const allComments = sourceCode.getAllComments();
116
116
  const comments = allComments
117
117
  .filter((comment) => {
118
- return (/^\*\s/u).test(comment.value);
118
+ return (/^\*\s/v).test(comment.value);
119
119
  })
120
120
  .map((commentNode) => {
121
121
  return parseComment(commentNode, '');
@@ -123,9 +123,9 @@ export default iterateJsdoc(({
123
123
 
124
124
  const globals = allComments
125
125
  .filter((comment) => {
126
- return (/^\s*globals/u).test(comment.value);
126
+ return (/^\s*globals/v).test(comment.value);
127
127
  }).flatMap((commentNode) => {
128
- return commentNode.value.replace(/^\s*globals/u, '').trim().split(/,\s*/u);
128
+ return commentNode.value.replace(/^\s*globals/v, '').trim().split(/,\s*/v);
129
129
  }).concat(Object.keys(context.languageOptions.globals ?? []));
130
130
 
131
131
  const typedefDeclarations = comments
@@ -158,6 +158,7 @@ export default iterateJsdoc(({
158
158
  additionalProperties: false,
159
159
  properties: {
160
160
  tags: {
161
+ additionalProperties: false,
161
162
  properties: {
162
163
  always: {
163
164
  items: {
@@ -14,7 +14,7 @@ const otherDescriptiveTags = new Set([
14
14
  * @returns {string[]}
15
15
  */
16
16
  const extractParagraphs = (text) => {
17
- return text.split(/(?<![;:])\n\n+/u);
17
+ return text.split(/(?<![;:])\n\n+/v);
18
18
  };
19
19
 
20
20
  /**
@@ -25,12 +25,12 @@ const extractParagraphs = (text) => {
25
25
  const extractSentences = (text, abbreviationsRegex) => {
26
26
  const txt = text
27
27
  // Remove all {} tags.
28
- .replaceAll(/(?<!^)\{[\s\S]*?\}\s*/gu, '')
28
+ .replaceAll(/(?<!^)\{[\s\S]*?\}\s*/gv, '')
29
29
 
30
30
  // Remove custom abbreviations
31
31
  .replace(abbreviationsRegex, '');
32
32
 
33
- const sentenceEndGrouping = /([.?!])(?:\s+|$)/ug;
33
+ const sentenceEndGrouping = /([.?!])(?:\s+|$)/gv;
34
34
 
35
35
  const puncts = [
36
36
  ...txt.matchAll(sentenceEndGrouping),
@@ -39,11 +39,11 @@ const extractSentences = (text, abbreviationsRegex) => {
39
39
  });
40
40
 
41
41
  return txt
42
- .split(/[.?!](?:\s+|$)/u)
42
+ .split(/[.?!](?:\s+|$)/v)
43
43
 
44
44
  // Re-add the dot.
45
45
  .map((sentence, idx) => {
46
- return !puncts[idx] && /^\s*$/u.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
46
+ return !puncts[idx] && /^\s*$/v.test(sentence) ? sentence : `${sentence}${puncts[idx] || ''}`;
47
47
  });
48
48
  };
49
49
 
@@ -58,11 +58,11 @@ const isNewLinePrecededByAPeriod = (text) => {
58
58
  const lines = text.split('\n');
59
59
 
60
60
  return !lines.some((line) => {
61
- if (lastLineEndsSentence === false && /^[A-Z][a-z]/u.test(line)) {
61
+ if (lastLineEndsSentence === false && /^[A-Z][a-z]/v.test(line)) {
62
62
  return true;
63
63
  }
64
64
 
65
- lastLineEndsSentence = /[.:?!|]$/u.test(line);
65
+ lastLineEndsSentence = /[.:?!\|]$/v.test(line);
66
66
 
67
67
  return false;
68
68
  });
@@ -108,11 +108,11 @@ const validateDescription = (
108
108
  description, reportOrig, jsdocNode, abbreviationsRegex,
109
109
  sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd,
110
110
  ) => {
111
- if (!description || (/^\n+$/u).test(description)) {
111
+ if (!description || (/^\n+$/v).test(description)) {
112
112
  return false;
113
113
  }
114
114
 
115
- const descriptionNoHeadings = description.replaceAll(/^\s*#[^\n]*(\n|$)/gmu, '');
115
+ const descriptionNoHeadings = description.replaceAll(/^\s*#[^\n]*(\n|$)/gmv, '');
116
116
 
117
117
  const paragraphs = extractParagraphs(descriptionNoHeadings).filter(Boolean);
118
118
 
@@ -122,28 +122,28 @@ const validateDescription = (
122
122
  const fix = /** @type {import('eslint').Rule.ReportFixer} */ (fixer) => {
123
123
  let text = sourceCode.getText(jsdocNode);
124
124
 
125
- if (!/[.:?!]$/u.test(paragraph)) {
125
+ if (!/[.:?!]$/v.test(paragraph)) {
126
126
  const line = paragraph.split('\n').findLast(Boolean);
127
127
  text = text.replace(new RegExp(`${escapeStringRegexp(
128
128
  /** @type {string} */
129
129
  (line),
130
- )}$`, 'mu'), `${line}.`);
130
+ )}$`, 'mv'), `${line}.`);
131
131
  }
132
132
 
133
133
  for (const sentence of sentences.filter((sentence_) => {
134
- return !(/^\s*$/u).test(sentence_) && !isCapitalized(sentence_) &&
134
+ return !(/^\s*$/v).test(sentence_) && !isCapitalized(sentence_) &&
135
135
  !isTable(sentence_);
136
136
  })) {
137
137
  const beginning = sentence.split('\n')[0];
138
138
 
139
139
  if ('tag' in tag && tag.tag) {
140
- const reg = new RegExp(`(@${escapeStringRegexp(tag.tag)}.*)${escapeStringRegexp(beginning)}`, 'u');
140
+ const reg = new RegExp(`(@${escapeStringRegexp(tag.tag)}.*)${escapeStringRegexp(beginning)}`, 'v');
141
141
 
142
142
  text = text.replace(reg, (_$0, $1) => {
143
143
  return $1 + capitalize(beginning);
144
144
  });
145
145
  } else {
146
- text = text.replace(new RegExp('((?:[.?!]|\\*|\\})\\s*)' + escapeStringRegexp(beginning), 'u'), '$1' + capitalize(beginning));
146
+ text = text.replace(new RegExp('((?:[.?!]|\\*|\\})\\s*)' + escapeStringRegexp(beginning), 'v'), '$1' + capitalize(beginning));
147
147
  }
148
148
  }
149
149
 
@@ -181,20 +181,20 @@ const validateDescription = (
181
181
  };
182
182
 
183
183
  if (sentences.some((sentence) => {
184
- return (/^[.?!]$/u).test(sentence);
184
+ return (/^[.?!]$/v).test(sentence);
185
185
  })) {
186
186
  report('Sentences must be more than punctuation.', null, tag);
187
187
  }
188
188
 
189
189
  if (sentences.some((sentence) => {
190
- return !(/^\s*$/u).test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
190
+ return !(/^\s*$/v).test(sentence) && !isCapitalized(sentence) && !isTable(sentence);
191
191
  })) {
192
192
  report('Sentences should start with an uppercase character.', fix, tag);
193
193
  }
194
194
 
195
195
  const paragraphNoAbbreviations = paragraph.replace(abbreviationsRegex, '');
196
196
 
197
- if (!/(?:[.?!|]|```)\s*$/u.test(paragraphNoAbbreviations)) {
197
+ if (!/(?:[.?!\|]|```)\s*$/v.test(paragraphNoAbbreviations)) {
198
198
  report('Sentences must end with a period.', fix, tag);
199
199
  return true;
200
200
  }
@@ -224,8 +224,8 @@ export default iterateJsdoc(({
224
224
 
225
225
  const abbreviationsRegex = abbreviations.length ?
226
226
  new RegExp('\\b' + abbreviations.map((abbreviation) => {
227
- return escapeStringRegexp(abbreviation.replaceAll(/\.$/ug, '') + '.');
228
- }).join('|') + '(?:$|\\s)', 'gu') :
227
+ return escapeStringRegexp(abbreviation.replaceAll(/\.$/gv, '') + '.');
228
+ }).join('|') + '(?:$|\\s)', 'gv') :
229
229
  '';
230
230
 
231
231
  let {
@@ -233,7 +233,7 @@ export default iterateJsdoc(({
233
233
  } = utils.getDescription();
234
234
 
235
235
  const indices = [
236
- ...description.matchAll(/```[\s\S]*```/gu),
236
+ ...description.matchAll(/```[\s\S]*```/gv),
237
237
  ].map((match) => {
238
238
  const {
239
239
  index,
@@ -289,7 +289,7 @@ export default iterateJsdoc(({
289
289
  tagsWithNames.some((tag) => {
290
290
  const desc = /** @type {string} */ (
291
291
  utils.getTagDescription(tag)
292
- ).replace(/^- /u, '').trimEnd();
292
+ ).replace(/^- /v, '').trimEnd();
293
293
 
294
294
  return validateDescription(desc, report, jsdocNode, abbreviationsRegex, sourceCode, tag, newlineBeforeCapsAssumesBadSentenceEnd);
295
295
  });
@@ -29,7 +29,7 @@ export default iterateJsdoc(({
29
29
  return;
30
30
  }
31
31
 
32
- const startsWithHyphen = (/^\s*-/u).test(desc);
32
+ const startsWithHyphen = (/^\s*-/v).test(desc);
33
33
  let lines = 0;
34
34
  for (const {
35
35
  tokens,
@@ -54,7 +54,7 @@ export default iterateJsdoc(({
54
54
  } of jsdocTag.source) {
55
55
  if (tokens.description) {
56
56
  tokens.description = tokens.description.replace(
57
- /^(\s*)/u, '$1- ',
57
+ /^(\s*)/v, '$1- ',
58
58
  );
59
59
  break;
60
60
  }
@@ -74,7 +74,7 @@ export default iterateJsdoc(({
74
74
  } of jsdocTag.source) {
75
75
  if (tokens.description) {
76
76
  tokens.description = tokens.description.replace(
77
- /^\s*-\s*/u, '',
77
+ /^\s*-\s*/v, '',
78
78
  );
79
79
  break;
80
80
  }
@@ -444,7 +444,7 @@ export default {
444
444
  */
445
445
  const underMinLine = (count) => {
446
446
  return count !== undefined && count >
447
- (sourceCode.getText(node).match(/\n/gu)?.length ?? 0) + 1;
447
+ (sourceCode.getText(node).match(/\n/gv)?.length ?? 0) + 1;
448
448
  };
449
449
 
450
450
  if (underMinLine(minLineCount)) {
@@ -81,7 +81,7 @@ export default iterateJsdoc(({
81
81
  const type = tag.type.trim();
82
82
 
83
83
  // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions
84
- if (/asserts\s/u.test(type)) {
84
+ if (/asserts\s/v.test(type)) {
85
85
  return;
86
86
  }
87
87
 
@@ -31,7 +31,7 @@ export default iterateJsdoc(({
31
31
  const {
32
32
  name,
33
33
  } = tag;
34
- const names = name.split(/,\s*/u);
34
+ const names = name.split(/,\s*/v);
35
35
  if (names.length > 1) {
36
36
  report(`Missing separate @template for ${names[1]}`, null, tag);
37
37
  }
@@ -126,7 +126,7 @@ export default iterateJsdoc(({
126
126
  type,
127
127
  value,
128
128
  } = /** @type {import('jsdoc-type-pratt-parser').NameResult} */ (nde);
129
- if (type === 'JsdocTypeName' && (/^[A-Z]$/u).test(value)) {
129
+ if (type === 'JsdocTypeName' && (/^[A-Z]$/v).test(value)) {
130
130
  usedNames.add(value);
131
131
  if (!usedNameToTag.has(value)) {
132
132
  usedNameToTag.set(value, potentialTag);