eslint-plugin-jsdoc 52.0.3 → 52.0.4

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 (357) hide show
  1. package/dist/WarnSettings.cjs +35 -18
  2. package/dist/WarnSettings.cjs.map +1 -1
  3. package/dist/alignTransform.cjs +305 -224
  4. package/dist/alignTransform.cjs.map +1 -1
  5. package/dist/defaultTagOrder.cjs +43 -132
  6. package/dist/defaultTagOrder.cjs.map +1 -1
  7. package/dist/exportParser.cjs +696 -478
  8. package/dist/exportParser.cjs.map +1 -1
  9. package/dist/generateRule.cjs +242 -0
  10. package/dist/generateRule.cjs.map +1 -0
  11. package/dist/getDefaultTagStructureForMode.cjs +288 -184
  12. package/dist/getDefaultTagStructureForMode.cjs.map +1 -1
  13. package/dist/getJsdocProcessorPlugin.cjs +550 -364
  14. package/dist/getJsdocProcessorPlugin.cjs.map +1 -1
  15. package/dist/getJsdocProcessorPlugin.d.ts +65 -68
  16. package/dist/getJsdocProcessorPlugin.d.ts.map +1 -1
  17. package/dist/index.cjs +383 -398
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.ts +6 -11
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/iterateJsdoc.cjs +1988 -1528
  22. package/dist/iterateJsdoc.cjs.map +1 -1
  23. package/dist/iterateJsdoc.d.ts +349 -358
  24. package/dist/iterateJsdoc.d.ts.map +1 -1
  25. package/dist/jsdocUtils.cjs +1376 -1009
  26. package/dist/jsdocUtils.cjs.map +1 -1
  27. package/dist/rules/checkAccess.cjs +36 -29
  28. package/dist/rules/checkAccess.cjs.map +1 -1
  29. package/dist/rules/checkAlignment.cjs +54 -41
  30. package/dist/rules/checkAlignment.cjs.map +1 -1
  31. package/dist/rules/checkExamples.cjs +484 -327
  32. package/dist/rules/checkExamples.cjs.map +1 -1
  33. package/dist/rules/checkIndentation.cjs +65 -50
  34. package/dist/rules/checkIndentation.cjs.map +1 -1
  35. package/dist/rules/checkLineAlignment.cjs +311 -220
  36. package/dist/rules/checkLineAlignment.cjs.map +1 -1
  37. package/dist/rules/checkParamNames.cjs +335 -227
  38. package/dist/rules/checkParamNames.cjs.map +1 -1
  39. package/dist/rules/checkPropertyNames.cjs +106 -78
  40. package/dist/rules/checkPropertyNames.cjs.map +1 -1
  41. package/dist/rules/checkSyntax.cjs +34 -21
  42. package/dist/rules/checkSyntax.cjs.map +1 -1
  43. package/dist/rules/checkTagNames.cjs +210 -188
  44. package/dist/rules/checkTagNames.cjs.map +1 -1
  45. package/dist/rules/checkTemplateNames.cjs +178 -121
  46. package/dist/rules/checkTemplateNames.cjs.map +1 -1
  47. package/dist/rules/checkTypes.cjs +385 -291
  48. package/dist/rules/checkTypes.cjs.map +1 -1
  49. package/dist/rules/checkValues.cjs +146 -100
  50. package/dist/rules/checkValues.cjs.map +1 -1
  51. package/dist/rules/convertToJsdocComments.cjs +306 -228
  52. package/dist/rules/convertToJsdocComments.cjs.map +1 -1
  53. package/dist/rules/emptyTags.cjs +72 -62
  54. package/dist/rules/emptyTags.cjs.map +1 -1
  55. package/dist/rules/implementsOnClasses.cjs +56 -36
  56. package/dist/rules/implementsOnClasses.cjs.map +1 -1
  57. package/dist/rules/importsAsDependencies.cjs +99 -62
  58. package/dist/rules/importsAsDependencies.cjs.map +1 -1
  59. package/dist/rules/informativeDocs.cjs +142 -105
  60. package/dist/rules/informativeDocs.cjs.map +1 -1
  61. package/dist/rules/linesBeforeBlock.cjs +105 -70
  62. package/dist/rules/linesBeforeBlock.cjs.map +1 -1
  63. package/dist/rules/matchDescription.cjs +222 -160
  64. package/dist/rules/matchDescription.cjs.map +1 -1
  65. package/dist/rules/matchName.cjs +128 -73
  66. package/dist/rules/matchName.cjs.map +1 -1
  67. package/dist/rules/multilineBlocks.cjs +352 -235
  68. package/dist/rules/multilineBlocks.cjs.map +1 -1
  69. package/dist/rules/noBadBlocks.cjs +86 -63
  70. package/dist/rules/noBadBlocks.cjs.map +1 -1
  71. package/dist/rules/noBlankBlockDescriptions.cjs +57 -35
  72. package/dist/rules/noBlankBlockDescriptions.cjs.map +1 -1
  73. package/dist/rules/noBlankBlocks.cjs +48 -26
  74. package/dist/rules/noBlankBlocks.cjs.map +1 -1
  75. package/dist/rules/noDefaults.cjs +79 -52
  76. package/dist/rules/noDefaults.cjs.map +1 -1
  77. package/dist/rules/noMissingSyntax.cjs +165 -115
  78. package/dist/rules/noMissingSyntax.cjs.map +1 -1
  79. package/dist/rules/noMultiAsterisks.cjs +89 -48
  80. package/dist/rules/noMultiAsterisks.cjs.map +1 -1
  81. package/dist/rules/noRestrictedSyntax.cjs +79 -45
  82. package/dist/rules/noRestrictedSyntax.cjs.map +1 -1
  83. package/dist/rules/noTypes.cjs +80 -59
  84. package/dist/rules/noTypes.cjs.map +1 -1
  85. package/dist/rules/noUndefinedTypes.cjs +388 -297
  86. package/dist/rules/noUndefinedTypes.cjs.map +1 -1
  87. package/dist/rules/requireAsteriskPrefix.cjs +159 -108
  88. package/dist/rules/requireAsteriskPrefix.cjs.map +1 -1
  89. package/dist/rules/requireDescription.cjs +129 -89
  90. package/dist/rules/requireDescription.cjs.map +1 -1
  91. package/dist/rules/requireDescriptionCompleteSentence.cjs +262 -201
  92. package/dist/rules/requireDescriptionCompleteSentence.cjs.map +1 -1
  93. package/dist/rules/requireExample.cjs +104 -73
  94. package/dist/rules/requireExample.cjs.map +1 -1
  95. package/dist/rules/requireFileOverview.cjs +129 -75
  96. package/dist/rules/requireFileOverview.cjs.map +1 -1
  97. package/dist/rules/requireHyphenBeforeParamDescription.cjs +133 -85
  98. package/dist/rules/requireHyphenBeforeParamDescription.cjs.map +1 -1
  99. package/dist/rules/requireJsdoc.cjs +557 -384
  100. package/dist/rules/requireJsdoc.cjs.map +1 -1
  101. package/dist/rules/requireParam.cjs +526 -336
  102. package/dist/rules/requireParam.cjs.map +1 -1
  103. package/dist/rules/requireParamDescription.cjs +80 -55
  104. package/dist/rules/requireParamDescription.cjs.map +1 -1
  105. package/dist/rules/requireParamName.cjs +50 -32
  106. package/dist/rules/requireParamName.cjs.map +1 -1
  107. package/dist/rules/requireParamType.cjs +80 -55
  108. package/dist/rules/requireParamType.cjs.map +1 -1
  109. package/dist/rules/requireProperty.cjs +42 -31
  110. package/dist/rules/requireProperty.cjs.map +1 -1
  111. package/dist/rules/requirePropertyDescription.cjs +25 -17
  112. package/dist/rules/requirePropertyDescription.cjs.map +1 -1
  113. package/dist/rules/requirePropertyName.cjs +25 -17
  114. package/dist/rules/requirePropertyName.cjs.map +1 -1
  115. package/dist/rules/requirePropertyType.cjs +25 -17
  116. package/dist/rules/requirePropertyType.cjs.map +1 -1
  117. package/dist/rules/requireReturns.cjs +203 -125
  118. package/dist/rules/requireReturns.cjs.map +1 -1
  119. package/dist/rules/requireReturnsCheck.cjs +103 -60
  120. package/dist/rules/requireReturnsCheck.cjs.map +1 -1
  121. package/dist/rules/requireReturnsDescription.cjs +54 -39
  122. package/dist/rules/requireReturnsDescription.cjs.map +1 -1
  123. package/dist/rules/requireReturnsType.cjs +50 -32
  124. package/dist/rules/requireReturnsType.cjs.map +1 -1
  125. package/dist/rules/requireTemplate.cjs +178 -119
  126. package/dist/rules/requireTemplate.cjs.map +1 -1
  127. package/dist/rules/requireThrows.cjs +95 -61
  128. package/dist/rules/requireThrows.cjs.map +1 -1
  129. package/dist/rules/requireYields.cjs +166 -106
  130. package/dist/rules/requireYields.cjs.map +1 -1
  131. package/dist/rules/requireYieldsCheck.cjs +152 -96
  132. package/dist/rules/requireYieldsCheck.cjs.map +1 -1
  133. package/dist/rules/sortTags.cjs +444 -258
  134. package/dist/rules/sortTags.cjs.map +1 -1
  135. package/dist/rules/tagLines.cjs +266 -179
  136. package/dist/rules/tagLines.cjs.map +1 -1
  137. package/dist/rules/textEscaping.cjs +127 -92
  138. package/dist/rules/textEscaping.cjs.map +1 -1
  139. package/dist/rules/validTypes.cjs +265 -252
  140. package/dist/rules/validTypes.cjs.map +1 -1
  141. package/dist/tagNames.cjs +170 -134
  142. package/dist/tagNames.cjs.map +1 -1
  143. package/dist/utils/hasReturnValue.cjs +474 -246
  144. package/dist/utils/hasReturnValue.cjs.map +1 -1
  145. package/package.json +24 -40
  146. package/src/WarnSettings.js +34 -0
  147. package/src/alignTransform.js +358 -0
  148. package/src/defaultTagOrder.js +169 -0
  149. package/src/exportParser.js +978 -0
  150. package/src/getDefaultTagStructureForMode.js +969 -0
  151. package/src/getJsdocProcessorPlugin.js +672 -0
  152. package/src/index.js +530 -0
  153. package/src/iterateJsdoc.js +2518 -0
  154. package/src/jsdocUtils.js +1896 -0
  155. package/src/rules/checkAccess.js +45 -0
  156. package/src/rules/checkAlignment.js +63 -0
  157. package/src/rules/checkExamples.js +589 -0
  158. package/src/rules/checkIndentation.js +75 -0
  159. package/src/rules/checkLineAlignment.js +372 -0
  160. package/src/rules/checkParamNames.js +474 -0
  161. package/src/rules/checkPropertyNames.js +152 -0
  162. package/src/rules/checkSyntax.js +30 -0
  163. package/src/rules/checkTagNames.js +314 -0
  164. package/src/rules/checkTemplateNames.js +204 -0
  165. package/src/rules/checkTypes.js +535 -0
  166. package/src/rules/checkValues.js +248 -0
  167. package/src/rules/convertToJsdocComments.js +398 -0
  168. package/src/rules/emptyTags.js +98 -0
  169. package/src/rules/implementsOnClasses.js +64 -0
  170. package/src/rules/importsAsDependencies.js +133 -0
  171. package/src/rules/informativeDocs.js +189 -0
  172. package/src/rules/linesBeforeBlock.js +134 -0
  173. package/src/rules/matchDescription.js +286 -0
  174. package/src/rules/matchName.js +151 -0
  175. package/src/rules/multilineBlocks.js +493 -0
  176. package/src/rules/noBadBlocks.js +119 -0
  177. package/src/rules/noBlankBlockDescriptions.js +69 -0
  178. package/src/rules/noBlankBlocks.js +53 -0
  179. package/src/rules/noDefaults.js +85 -0
  180. package/src/rules/noMissingSyntax.js +195 -0
  181. package/src/rules/noMultiAsterisks.js +134 -0
  182. package/src/rules/noRestrictedSyntax.js +91 -0
  183. package/src/rules/noTypes.js +93 -0
  184. package/src/rules/noUndefinedTypes.js +543 -0
  185. package/src/rules/requireAsteriskPrefix.js +190 -0
  186. package/src/rules/requireDescription.js +161 -0
  187. package/src/rules/requireDescriptionCompleteSentence.js +335 -0
  188. package/src/rules/requireExample.js +118 -0
  189. package/src/rules/requireFileOverview.js +154 -0
  190. package/src/rules/requireHyphenBeforeParamDescription.js +176 -0
  191. package/src/rules/requireJsdoc.js +743 -0
  192. package/src/rules/requireParam.js +602 -0
  193. package/src/rules/requireParamDescription.js +89 -0
  194. package/src/rules/requireParamName.js +55 -0
  195. package/src/rules/requireParamType.js +89 -0
  196. package/src/rules/requireProperty.js +48 -0
  197. package/src/rules/requirePropertyDescription.js +25 -0
  198. package/src/rules/requirePropertyName.js +25 -0
  199. package/src/rules/requirePropertyType.js +25 -0
  200. package/src/rules/requireReturns.js +238 -0
  201. package/src/rules/requireReturnsCheck.js +145 -0
  202. package/src/rules/requireReturnsDescription.js +59 -0
  203. package/src/rules/requireReturnsType.js +51 -0
  204. package/src/rules/requireTemplate.js +201 -0
  205. package/src/rules/requireThrows.js +111 -0
  206. package/src/rules/requireYields.js +216 -0
  207. package/src/rules/requireYieldsCheck.js +208 -0
  208. package/src/rules/sortTags.js +558 -0
  209. package/src/rules/tagLines.js +359 -0
  210. package/src/rules/textEscaping.js +154 -0
  211. package/src/rules/validTypes.js +401 -0
  212. package/src/tagNames.js +238 -0
  213. package/src/utils/hasReturnValue.js +572 -0
  214. package/dist/WarnSettings.js +0 -20
  215. package/dist/WarnSettings.js.map +0 -1
  216. package/dist/_virtual/rolldown_runtime.cjs +0 -32
  217. package/dist/_virtual/rolldown_runtime.js +0 -11
  218. package/dist/alignTransform.js +0 -241
  219. package/dist/alignTransform.js.map +0 -1
  220. package/dist/defaultTagOrder.js +0 -134
  221. package/dist/defaultTagOrder.js.map +0 -1
  222. package/dist/exportParser.js +0 -518
  223. package/dist/exportParser.js.map +0 -1
  224. package/dist/getDefaultTagStructureForMode.js +0 -188
  225. package/dist/getDefaultTagStructureForMode.js.map +0 -1
  226. package/dist/getJsdocProcessorPlugin.d.cts +0 -70
  227. package/dist/getJsdocProcessorPlugin.d.cts.map +0 -1
  228. package/dist/getJsdocProcessorPlugin.js +0 -383
  229. package/dist/getJsdocProcessorPlugin.js.map +0 -1
  230. package/dist/index.d.cts +0 -22
  231. package/dist/index.d.cts.map +0 -1
  232. package/dist/index.js +0 -425
  233. package/dist/index.js.map +0 -1
  234. package/dist/iterateJsdoc.d.cts +0 -471
  235. package/dist/iterateJsdoc.d.cts.map +0 -1
  236. package/dist/iterateJsdoc.js +0 -1617
  237. package/dist/iterateJsdoc.js.map +0 -1
  238. package/dist/jsdocUtils.js +0 -1123
  239. package/dist/jsdocUtils.js.map +0 -1
  240. package/dist/rules/checkAccess.js +0 -33
  241. package/dist/rules/checkAccess.js.map +0 -1
  242. package/dist/rules/checkAlignment.js +0 -47
  243. package/dist/rules/checkAlignment.js.map +0 -1
  244. package/dist/rules/checkExamples.js +0 -348
  245. package/dist/rules/checkExamples.js.map +0 -1
  246. package/dist/rules/checkIndentation.js +0 -59
  247. package/dist/rules/checkIndentation.js.map +0 -1
  248. package/dist/rules/checkLineAlignment.js +0 -229
  249. package/dist/rules/checkLineAlignment.js.map +0 -1
  250. package/dist/rules/checkParamNames.js +0 -237
  251. package/dist/rules/checkParamNames.js.map +0 -1
  252. package/dist/rules/checkPropertyNames.js +0 -88
  253. package/dist/rules/checkPropertyNames.js.map +0 -1
  254. package/dist/rules/checkSyntax.js +0 -25
  255. package/dist/rules/checkSyntax.js.map +0 -1
  256. package/dist/rules/checkTagNames.js +0 -191
  257. package/dist/rules/checkTagNames.js.map +0 -1
  258. package/dist/rules/checkTemplateNames.js +0 -124
  259. package/dist/rules/checkTemplateNames.js.map +0 -1
  260. package/dist/rules/checkTypes.js +0 -299
  261. package/dist/rules/checkTypes.js.map +0 -1
  262. package/dist/rules/checkValues.js +0 -103
  263. package/dist/rules/checkValues.js.map +0 -1
  264. package/dist/rules/convertToJsdocComments.js +0 -231
  265. package/dist/rules/convertToJsdocComments.js.map +0 -1
  266. package/dist/rules/emptyTags.js +0 -67
  267. package/dist/rules/emptyTags.js.map +0 -1
  268. package/dist/rules/implementsOnClasses.js +0 -40
  269. package/dist/rules/implementsOnClasses.js.map +0 -1
  270. package/dist/rules/importsAsDependencies.js +0 -68
  271. package/dist/rules/importsAsDependencies.js.map +0 -1
  272. package/dist/rules/informativeDocs.js +0 -110
  273. package/dist/rules/informativeDocs.js.map +0 -1
  274. package/dist/rules/linesBeforeBlock.js +0 -75
  275. package/dist/rules/linesBeforeBlock.js.map +0 -1
  276. package/dist/rules/matchDescription.js +0 -167
  277. package/dist/rules/matchDescription.js.map +0 -1
  278. package/dist/rules/matchName.js +0 -77
  279. package/dist/rules/matchName.js.map +0 -1
  280. package/dist/rules/multilineBlocks.js +0 -245
  281. package/dist/rules/multilineBlocks.js.map +0 -1
  282. package/dist/rules/noBadBlocks.js +0 -68
  283. package/dist/rules/noBadBlocks.js.map +0 -1
  284. package/dist/rules/noBlankBlockDescriptions.js +0 -41
  285. package/dist/rules/noBlankBlockDescriptions.js.map +0 -1
  286. package/dist/rules/noBlankBlocks.js +0 -30
  287. package/dist/rules/noBlankBlocks.js.map +0 -1
  288. package/dist/rules/noDefaults.js +0 -56
  289. package/dist/rules/noDefaults.js.map +0 -1
  290. package/dist/rules/noMissingSyntax.js +0 -126
  291. package/dist/rules/noMissingSyntax.js.map +0 -1
  292. package/dist/rules/noMultiAsterisks.js +0 -58
  293. package/dist/rules/noMultiAsterisks.js.map +0 -1
  294. package/dist/rules/noRestrictedSyntax.js +0 -49
  295. package/dist/rules/noRestrictedSyntax.js.map +0 -1
  296. package/dist/rules/noTypes.js +0 -65
  297. package/dist/rules/noTypes.js.map +0 -1
  298. package/dist/rules/noUndefinedTypes.js +0 -303
  299. package/dist/rules/noUndefinedTypes.js.map +0 -1
  300. package/dist/rules/requireAsteriskPrefix.js +0 -112
  301. package/dist/rules/requireAsteriskPrefix.js.map +0 -1
  302. package/dist/rules/requireDescription.js +0 -95
  303. package/dist/rules/requireDescription.js.map +0 -1
  304. package/dist/rules/requireDescriptionCompleteSentence.js +0 -220
  305. package/dist/rules/requireDescriptionCompleteSentence.js.map +0 -1
  306. package/dist/rules/requireExample.js +0 -77
  307. package/dist/rules/requireExample.js.map +0 -1
  308. package/dist/rules/requireFileOverview.js +0 -81
  309. package/dist/rules/requireFileOverview.js.map +0 -1
  310. package/dist/rules/requireHyphenBeforeParamDescription.js +0 -89
  311. package/dist/rules/requireHyphenBeforeParamDescription.js.map +0 -1
  312. package/dist/rules/requireJsdoc.js +0 -404
  313. package/dist/rules/requireJsdoc.js.map +0 -1
  314. package/dist/rules/requireParam.js +0 -344
  315. package/dist/rules/requireParam.js.map +0 -1
  316. package/dist/rules/requireParamDescription.js +0 -59
  317. package/dist/rules/requireParamDescription.js.map +0 -1
  318. package/dist/rules/requireParamName.js +0 -36
  319. package/dist/rules/requireParamName.js.map +0 -1
  320. package/dist/rules/requireParamType.js +0 -59
  321. package/dist/rules/requireParamType.js.map +0 -1
  322. package/dist/rules/requireProperty.js +0 -35
  323. package/dist/rules/requireProperty.js.map +0 -1
  324. package/dist/rules/requirePropertyDescription.js +0 -21
  325. package/dist/rules/requirePropertyDescription.js.map +0 -1
  326. package/dist/rules/requirePropertyName.js +0 -21
  327. package/dist/rules/requirePropertyName.js.map +0 -1
  328. package/dist/rules/requirePropertyType.js +0 -21
  329. package/dist/rules/requirePropertyType.js.map +0 -1
  330. package/dist/rules/requireReturns.js +0 -131
  331. package/dist/rules/requireReturns.js.map +0 -1
  332. package/dist/rules/requireReturnsCheck.js +0 -66
  333. package/dist/rules/requireReturnsCheck.js.map +0 -1
  334. package/dist/rules/requireReturnsDescription.js +0 -43
  335. package/dist/rules/requireReturnsDescription.js.map +0 -1
  336. package/dist/rules/requireReturnsType.js +0 -36
  337. package/dist/rules/requireReturnsType.js.map +0 -1
  338. package/dist/rules/requireTemplate.js +0 -122
  339. package/dist/rules/requireTemplate.js.map +0 -1
  340. package/dist/rules/requireThrows.js +0 -67
  341. package/dist/rules/requireThrows.js.map +0 -1
  342. package/dist/rules/requireYields.js +0 -115
  343. package/dist/rules/requireYields.js.map +0 -1
  344. package/dist/rules/requireYieldsCheck.js +0 -105
  345. package/dist/rules/requireYieldsCheck.js.map +0 -1
  346. package/dist/rules/sortTags.js +0 -262
  347. package/dist/rules/sortTags.js.map +0 -1
  348. package/dist/rules/tagLines.js +0 -183
  349. package/dist/rules/tagLines.js.map +0 -1
  350. package/dist/rules/textEscaping.js +0 -102
  351. package/dist/rules/textEscaping.js.map +0 -1
  352. package/dist/rules/validTypes.js +0 -259
  353. package/dist/rules/validTypes.js.map +0 -1
  354. package/dist/tagNames.js +0 -144
  355. package/dist/tagNames.js.map +0 -1
  356. package/dist/utils/hasReturnValue.js +0 -265
  357. package/dist/utils/hasReturnValue.js.map +0 -1
@@ -0,0 +1,672 @@
1
+ import {
2
+ forEachPreferredTag,
3
+ getPreferredTagName,
4
+ getRegexFromString,
5
+ getTagDescription,
6
+ hasTag,
7
+ } from './jsdocUtils.js';
8
+ import {
9
+ parseComment,
10
+ } from '@es-joy/jsdoccomment';
11
+ import * as espree from 'espree';
12
+ import {
13
+ readFileSync,
14
+ } from 'node:fs';
15
+ import {
16
+ join,
17
+ } from 'node:path';
18
+
19
+ /**
20
+ * @import {
21
+ * Integer,
22
+ * JsdocBlockWithInline,
23
+ * } from './iterateJsdoc.js';
24
+ * @import {
25
+ * ESLint,
26
+ * Linter,
27
+ * } from 'eslint';
28
+ */
29
+
30
+ const {
31
+ version,
32
+ } = JSON.parse(
33
+ // @ts-expect-error `Buffer` is ok for `JSON.parse`
34
+ readFileSync(join(import.meta.dirname, '../package.json')),
35
+ );
36
+
37
+ // const zeroBasedLineIndexAdjust = -1;
38
+ const likelyNestedJSDocIndentSpace = 1;
39
+ const preTagSpaceLength = 1;
40
+
41
+ // If a space is present, we should ignore it
42
+ const firstLinePrefixLength = preTagSpaceLength;
43
+
44
+ const hasCaptionRegex = /^\s*<caption>([\s\S]*?)<\/caption>/v;
45
+
46
+ /**
47
+ * @param {string} str
48
+ * @returns {string}
49
+ */
50
+ const escapeStringRegexp = (str) => {
51
+ return str.replaceAll(/[.*+?^$\{\}\(\)\|\[\]\\]/gv, '\\$&');
52
+ };
53
+
54
+ /**
55
+ * @param {string} str
56
+ * @param {string} ch
57
+ * @returns {Integer}
58
+ */
59
+ const countChars = (str, ch) => {
60
+ return (str.match(new RegExp(escapeStringRegexp(ch), 'gv')) || []).length;
61
+ };
62
+
63
+ /**
64
+ * @param {string} text
65
+ * @returns {[
66
+ * Integer,
67
+ * Integer
68
+ * ]}
69
+ */
70
+ const getLinesCols = (text) => {
71
+ const matchLines = countChars(text, '\n');
72
+
73
+ const colDelta = matchLines ?
74
+ text.slice(text.lastIndexOf('\n') + 1).length :
75
+ text.length;
76
+
77
+ return [
78
+ matchLines, colDelta,
79
+ ];
80
+ };
81
+
82
+ /**
83
+ * @typedef {number} Integer
84
+ */
85
+
86
+ /**
87
+ * @typedef {object} JsdocProcessorOptions
88
+ * @property {boolean} [captionRequired] Require captions for example tags
89
+ * @property {Integer} [paddedIndent] See docs
90
+ * @property {boolean} [checkDefaults] See docs
91
+ * @property {boolean} [checkParams] See docs
92
+ * @property {boolean} [checkExamples] See docs
93
+ * @property {boolean} [checkProperties] See docs
94
+ * @property {string} [matchingFileName] See docs
95
+ * @property {string} [matchingFileNameDefaults] See docs
96
+ * @property {string} [matchingFileNameParams] See docs
97
+ * @property {string} [matchingFileNameProperties] See docs
98
+ * @property {string|RegExp} [exampleCodeRegex] See docs
99
+ * @property {string|RegExp} [rejectExampleCodeRegex] See docs
100
+ * @property {string[]} [allowedLanguagesToProcess] See docs
101
+ * @property {"script"|"module"} [sourceType] See docs
102
+ * @property {import('eslint').Linter.ESTreeParser|import('eslint').Linter.NonESTreeParser} [parser] See docs
103
+ */
104
+
105
+ /**
106
+ * We use a function for the ability of the user to pass in a config, but
107
+ * without requiring all users of the plugin to do so.
108
+ * @param {JsdocProcessorOptions} [options]
109
+ * @returns {ESLint.Plugin}
110
+ */
111
+ export const getJsdocProcessorPlugin = (options = {}) => {
112
+ const {
113
+ allowedLanguagesToProcess = [
114
+ 'js', 'ts', 'javascript', 'typescript',
115
+ ],
116
+ captionRequired = false,
117
+ checkDefaults = false,
118
+ checkExamples = true,
119
+ checkParams = false,
120
+ checkProperties = false,
121
+ exampleCodeRegex = null,
122
+ matchingFileName = null,
123
+ matchingFileNameDefaults = null,
124
+ matchingFileNameParams = null,
125
+ matchingFileNameProperties = null,
126
+ paddedIndent = 0,
127
+ parser = undefined,
128
+ rejectExampleCodeRegex = null,
129
+ sourceType = 'module',
130
+ } = options;
131
+
132
+ /** @type {RegExp} */
133
+ let exampleCodeRegExp;
134
+ /** @type {RegExp} */
135
+ let rejectExampleCodeRegExp;
136
+
137
+ if (exampleCodeRegex) {
138
+ exampleCodeRegExp = typeof exampleCodeRegex === 'string' ?
139
+ getRegexFromString(exampleCodeRegex) :
140
+ exampleCodeRegex;
141
+ }
142
+
143
+ if (rejectExampleCodeRegex) {
144
+ rejectExampleCodeRegExp = typeof rejectExampleCodeRegex === 'string' ?
145
+ getRegexFromString(rejectExampleCodeRegex) :
146
+ rejectExampleCodeRegex;
147
+ }
148
+
149
+ /**
150
+ * @type {{
151
+ * targetTagName: string,
152
+ * ext: string,
153
+ * codeStartLine: number,
154
+ * codeStartCol: number,
155
+ * nonJSPrefacingCols: number,
156
+ * commentLineCols: [number, number]
157
+ * }[]}
158
+ */
159
+ const otherInfo = [];
160
+
161
+ /** @type {import('eslint').Linter.LintMessage[]} */
162
+ let extraMessages = [];
163
+
164
+ /**
165
+ * @param {JsdocBlockWithInline} jsdoc
166
+ * @param {string} jsFileName
167
+ * @param {[number, number]} commentLineCols
168
+ */
169
+ const getTextsAndFileNames = (jsdoc, jsFileName, commentLineCols) => {
170
+ /**
171
+ * @type {{
172
+ * text: string,
173
+ * filename: string|null|undefined
174
+ * }[]}
175
+ */
176
+ const textsAndFileNames = [];
177
+
178
+ /**
179
+ * @param {{
180
+ * filename: string|null,
181
+ * defaultFileName: string|undefined,
182
+ * source: string,
183
+ * targetTagName: string,
184
+ * rules?: import('eslint').Linter.RulesRecord|undefined,
185
+ * lines?: Integer,
186
+ * cols?: Integer,
187
+ * skipInit?: boolean,
188
+ * ext: string,
189
+ * sources?: {
190
+ * nonJSPrefacingCols: Integer,
191
+ * nonJSPrefacingLines: Integer,
192
+ * string: string,
193
+ * }[],
194
+ * tag?: import('comment-parser').Spec & {
195
+ * line?: Integer,
196
+ * }|{
197
+ * line: Integer,
198
+ * }
199
+ * }} cfg
200
+ */
201
+ const checkSource = ({
202
+ cols = 0,
203
+ defaultFileName,
204
+ ext,
205
+ filename,
206
+ lines = 0,
207
+ skipInit,
208
+ source,
209
+ sources = [],
210
+ tag = {
211
+ line: 0,
212
+ },
213
+ targetTagName,
214
+ }) => {
215
+ if (!skipInit) {
216
+ sources.push({
217
+ nonJSPrefacingCols: cols,
218
+ nonJSPrefacingLines: lines,
219
+ string: source,
220
+ });
221
+ }
222
+
223
+ /**
224
+ * @param {{
225
+ * nonJSPrefacingCols: Integer,
226
+ * nonJSPrefacingLines: Integer,
227
+ * string: string
228
+ * }} cfg
229
+ */
230
+ const addSourceInfo = function ({
231
+ nonJSPrefacingCols,
232
+ nonJSPrefacingLines,
233
+ string,
234
+ }) {
235
+ const src = paddedIndent ?
236
+ string.replaceAll(new RegExp(`(^|\n) {${paddedIndent}}(?!$)`, 'gv'), '\n') :
237
+ string;
238
+
239
+ // Programmatic ESLint API: https://eslint.org/docs/developer-guide/nodejs-api
240
+ const file = filename || defaultFileName;
241
+
242
+ if (!('line' in tag)) {
243
+ tag.line = tag.source[0].number;
244
+ }
245
+
246
+ // NOTE: `tag.line` can be 0 if of form `/** @tag ... */`
247
+ const codeStartLine = /**
248
+ * @type {import('comment-parser').Spec & {
249
+ * line: Integer,
250
+ * }}
251
+ */ (tag).line + nonJSPrefacingLines;
252
+ const codeStartCol = likelyNestedJSDocIndentSpace;
253
+
254
+ textsAndFileNames.push({
255
+ filename: file,
256
+ text: src,
257
+ });
258
+ otherInfo.push({
259
+ codeStartCol,
260
+ codeStartLine,
261
+ commentLineCols,
262
+ ext,
263
+ nonJSPrefacingCols,
264
+ targetTagName,
265
+ });
266
+ };
267
+
268
+ for (const targetSource of sources) {
269
+ addSourceInfo(targetSource);
270
+ }
271
+ };
272
+
273
+ /**
274
+ *
275
+ * @param {string|null} filename
276
+ * @param {string} [ext] Since `eslint-plugin-markdown` v2, and
277
+ * ESLint 7, this is the default which other JS-fenced rules will used.
278
+ * Formerly "md" was the default.
279
+ * @returns {{
280
+ * defaultFileName: string|undefined,
281
+ * filename: string|null,
282
+ * ext: string
283
+ * }}
284
+ */
285
+ const getFilenameInfo = (filename, ext = 'md/*.js') => {
286
+ let defaultFileName;
287
+ if (!filename) {
288
+ if (typeof jsFileName === 'string' && jsFileName.includes('.')) {
289
+ defaultFileName = jsFileName.replace(/\.[^.]*$/v, `.${ext}`);
290
+ } else {
291
+ defaultFileName = `dummy.${ext}`;
292
+ }
293
+ }
294
+
295
+ return {
296
+ defaultFileName,
297
+ ext,
298
+ filename,
299
+ };
300
+ };
301
+
302
+ if (checkDefaults) {
303
+ const filenameInfo = getFilenameInfo(matchingFileNameDefaults, 'jsdoc-defaults');
304
+ forEachPreferredTag(jsdoc, 'default', (tag, targetTagName) => {
305
+ if (!tag.description.trim()) {
306
+ return;
307
+ }
308
+
309
+ checkSource({
310
+ source: `(${getTagDescription(tag)})`,
311
+ targetTagName,
312
+ ...filenameInfo,
313
+ });
314
+ });
315
+ }
316
+
317
+ if (checkParams) {
318
+ const filenameInfo = getFilenameInfo(matchingFileNameParams, 'jsdoc-params');
319
+ forEachPreferredTag(jsdoc, 'param', (tag, targetTagName) => {
320
+ if (!tag.default || !tag.default.trim()) {
321
+ return;
322
+ }
323
+
324
+ checkSource({
325
+ source: `(${tag.default})`,
326
+ targetTagName,
327
+ ...filenameInfo,
328
+ });
329
+ });
330
+ }
331
+
332
+ if (checkProperties) {
333
+ const filenameInfo = getFilenameInfo(matchingFileNameProperties, 'jsdoc-properties');
334
+ forEachPreferredTag(jsdoc, 'property', (tag, targetTagName) => {
335
+ if (!tag.default || !tag.default.trim()) {
336
+ return;
337
+ }
338
+
339
+ checkSource({
340
+ source: `(${tag.default})`,
341
+ targetTagName,
342
+ ...filenameInfo,
343
+ });
344
+ });
345
+ }
346
+
347
+ if (!checkExamples) {
348
+ return textsAndFileNames;
349
+ }
350
+
351
+ const tagName = /** @type {string} */ (getPreferredTagName(jsdoc, {
352
+ tagName: 'example',
353
+ }));
354
+ if (!hasTag(jsdoc, tagName)) {
355
+ return textsAndFileNames;
356
+ }
357
+
358
+ const matchingFilenameInfo = getFilenameInfo(matchingFileName);
359
+
360
+ forEachPreferredTag(jsdoc, 'example', (tag, targetTagName) => {
361
+ let source = /** @type {string} */ (getTagDescription(tag));
362
+ const match = source.match(hasCaptionRegex);
363
+
364
+ if (captionRequired && (!match || !match[1].trim())) {
365
+ extraMessages.push({
366
+ column: commentLineCols[1] + 1,
367
+ line: 1 + commentLineCols[0] + (tag.line ?? tag.source[0].number),
368
+ message: `@${targetTagName} error - Caption is expected for examples.`,
369
+ ruleId: 'jsdoc/example-missing-caption',
370
+ severity: 2,
371
+ });
372
+ return;
373
+ }
374
+
375
+ source = source.replace(hasCaptionRegex, '');
376
+ const [
377
+ lines,
378
+ cols,
379
+ ] = match ? getLinesCols(match[0]) : [
380
+ 0, 0,
381
+ ];
382
+
383
+ if (exampleCodeRegex && !exampleCodeRegExp.test(source) ||
384
+ rejectExampleCodeRegex && rejectExampleCodeRegExp.test(source)
385
+ ) {
386
+ return;
387
+ }
388
+
389
+ // If `allowedLanguagesToProcess` is falsy, all languages should be processed.
390
+ if (allowedLanguagesToProcess) {
391
+ const matches = (/^\s*```(?<language>\S+)([\s\S]*)```\s*$/v).exec(source);
392
+ if (matches?.groups && !allowedLanguagesToProcess.includes(
393
+ matches.groups.language.toLowerCase(),
394
+ )) {
395
+ return;
396
+ }
397
+ }
398
+
399
+ const sources = [];
400
+ let skipInit = false;
401
+ if (exampleCodeRegex) {
402
+ let nonJSPrefacingCols = 0;
403
+ let nonJSPrefacingLines = 0;
404
+
405
+ let startingIndex = 0;
406
+ let lastStringCount = 0;
407
+
408
+ let exampleCode;
409
+ exampleCodeRegExp.lastIndex = 0;
410
+ while ((exampleCode = exampleCodeRegExp.exec(source)) !== null) {
411
+ const {
412
+ '0': n0,
413
+ '1': n1,
414
+ index,
415
+ } = exampleCode;
416
+
417
+ // Count anything preceding user regex match (can affect line numbering)
418
+ const preMatch = source.slice(startingIndex, index);
419
+
420
+ const [
421
+ preMatchLines,
422
+ colDelta,
423
+ ] = getLinesCols(preMatch);
424
+
425
+ let nonJSPreface;
426
+ let nonJSPrefaceLineCount;
427
+ if (n1) {
428
+ const idx = n0.indexOf(n1);
429
+ nonJSPreface = n0.slice(0, idx);
430
+ nonJSPrefaceLineCount = countChars(nonJSPreface, '\n');
431
+ } else {
432
+ nonJSPreface = '';
433
+ nonJSPrefaceLineCount = 0;
434
+ }
435
+
436
+ nonJSPrefacingLines += lastStringCount + preMatchLines + nonJSPrefaceLineCount;
437
+
438
+ // Ignore `preMatch` delta if newlines here
439
+ if (nonJSPrefaceLineCount) {
440
+ const charsInLastLine = nonJSPreface.slice(nonJSPreface.lastIndexOf('\n') + 1).length;
441
+
442
+ nonJSPrefacingCols += charsInLastLine;
443
+ } else {
444
+ nonJSPrefacingCols += colDelta + nonJSPreface.length;
445
+ }
446
+
447
+ const string = n1 || n0;
448
+ sources.push({
449
+ nonJSPrefacingCols,
450
+ nonJSPrefacingLines,
451
+ string,
452
+ });
453
+ startingIndex = exampleCodeRegExp.lastIndex;
454
+ lastStringCount = countChars(string, '\n');
455
+ if (!exampleCodeRegExp.global) {
456
+ break;
457
+ }
458
+ }
459
+
460
+ skipInit = true;
461
+ }
462
+
463
+ checkSource({
464
+ cols,
465
+ lines,
466
+ skipInit,
467
+ source,
468
+ sources,
469
+ tag,
470
+ targetTagName,
471
+ ...matchingFilenameInfo,
472
+ });
473
+ });
474
+
475
+ return textsAndFileNames;
476
+ };
477
+
478
+ // See https://eslint.org/docs/latest/extend/plugins#processors-in-plugins
479
+ // See https://eslint.org/docs/latest/extend/custom-processors
480
+ // From https://github.com/eslint/eslint/issues/14745#issuecomment-869457265
481
+ /*
482
+ {
483
+ "files": ["*.js", "*.ts"],
484
+ "processor": "jsdoc/example" // a pretended value here
485
+ },
486
+ {
487
+ "files": [
488
+ "*.js/*_jsdoc-example.js",
489
+ "*.ts/*_jsdoc-example.js",
490
+ "*.js/*_jsdoc-example.ts"
491
+ ],
492
+ "rules": {
493
+ // specific rules for examples in jsdoc only here
494
+ // And other rules for `.js` and `.ts` will also be enabled for them
495
+ }
496
+ }
497
+ */
498
+ return {
499
+ meta: {
500
+ name: 'eslint-plugin-jsdoc/processor',
501
+ version,
502
+ },
503
+ processors: {
504
+ examples: {
505
+ meta: {
506
+ name: 'eslint-plugin-jsdoc/preprocessor',
507
+ version,
508
+ },
509
+ /**
510
+ * @param {import('eslint').Linter.LintMessage[][]} messages
511
+ * @param {string} filename
512
+ */
513
+ postprocess ([
514
+ jsMessages,
515
+ ...messages
516
+ // eslint-disable-next-line no-unused-vars -- Placeholder
517
+ ], filename) {
518
+ for (const [
519
+ idx,
520
+ message,
521
+ ] of messages.entries()) {
522
+ const {
523
+ codeStartCol,
524
+ codeStartLine,
525
+ commentLineCols,
526
+ nonJSPrefacingCols,
527
+ targetTagName,
528
+ } = otherInfo[idx];
529
+
530
+ for (const msg of message) {
531
+ const {
532
+ column,
533
+ endColumn,
534
+ endLine,
535
+ fatal,
536
+ line,
537
+ message: messageText,
538
+ ruleId,
539
+ severity,
540
+
541
+ // Todo: Make fixable
542
+ // fix
543
+ // fix: {range: [number, number], text: string}
544
+ // suggestions: {desc: , messageId:, fix: }[],
545
+ } = msg;
546
+
547
+ const [
548
+ codeCtxLine,
549
+ codeCtxColumn,
550
+ ] = commentLineCols;
551
+ const startLine = codeCtxLine + codeStartLine + line;
552
+
553
+ // Seems to need one more now
554
+ const startCol = 1 +
555
+ codeCtxColumn + codeStartCol + (
556
+ // This might not work for line 0, but line 0 is unlikely for examples
557
+ line <= 1 ? nonJSPrefacingCols + firstLinePrefixLength : preTagSpaceLength
558
+ ) + column;
559
+
560
+ msg.message = '@' + targetTagName + ' ' + (severity === 2 ? 'error' : 'warning') +
561
+ (ruleId ? ' (' + ruleId + ')' : '') + ': ' +
562
+ (fatal ? 'Fatal: ' : '') +
563
+ messageText;
564
+ msg.line = startLine;
565
+ msg.column = startCol;
566
+ msg.endLine = endLine ? startLine + endLine : startLine;
567
+ // added `- column` to offset what `endColumn` already seemed to include
568
+ msg.endColumn = endColumn ? startCol - column + endColumn : startCol;
569
+ }
570
+ }
571
+
572
+ const ret = [
573
+ ...jsMessages,
574
+ ].concat(...messages, ...extraMessages);
575
+ extraMessages = [];
576
+ return ret;
577
+ },
578
+
579
+ /**
580
+ * @param {string} text
581
+ * @param {string} filename
582
+ * @returns {(string | Linter.ProcessorFile)[]}
583
+ */
584
+ preprocess (text, filename) {
585
+ try {
586
+ let ast;
587
+
588
+ // May be running a second time so catch and ignore
589
+ try {
590
+ ast = parser ?
591
+ // @ts-expect-error Should be present
592
+ parser.parseForESLint(text, {
593
+ comment: true,
594
+ ecmaVersion: 'latest',
595
+ sourceType,
596
+ }).ast :
597
+ espree.parse(text, {
598
+ comment: true,
599
+ ecmaVersion: 'latest',
600
+ sourceType,
601
+ });
602
+ } catch {
603
+ return [
604
+ text,
605
+ ];
606
+ }
607
+
608
+ /** @type {[number, number][]} */
609
+ const commentLineCols = [];
610
+ const jsdocComments = /** @type {import('estree').Comment[]} */ (
611
+ /**
612
+ * @type {import('estree').Program & {
613
+ * comments?: import('estree').Comment[]
614
+ * }}
615
+ */
616
+ (ast).comments
617
+ ).filter((comment) => {
618
+ return (/^\*\s/v).test(comment.value);
619
+ }).map((comment) => {
620
+ const [
621
+ start,
622
+ /* c8 ignore next -- Unsupporting processors only? */
623
+ ] = comment.range ?? [];
624
+ const textToStart = text.slice(0, start);
625
+
626
+ const [
627
+ lines,
628
+ cols,
629
+ ] = getLinesCols(textToStart);
630
+
631
+ // const lines = [...textToStart.matchAll(/\n/gv)].length
632
+ // const lastLinePos = textToStart.lastIndexOf('\n');
633
+ // const cols = lastLinePos === -1
634
+ // ? 0
635
+ // : textToStart.slice(lastLinePos).length;
636
+ commentLineCols.push([
637
+ lines, cols,
638
+ ]);
639
+ return parseComment(comment);
640
+ });
641
+
642
+ return [
643
+ text,
644
+ ...jsdocComments.flatMap((jsdoc, idx) => {
645
+ return getTextsAndFileNames(
646
+ jsdoc,
647
+ filename,
648
+ commentLineCols[idx],
649
+ );
650
+ }).filter(
651
+ /**
652
+ * @returns {file is Linter.ProcessorFile}
653
+ */
654
+ (file) => {
655
+ return file !== null && file !== undefined;
656
+ },
657
+ ),
658
+ ];
659
+ /* c8 ignore next 6 */
660
+ } catch (error) {
661
+ // eslint-disable-next-line no-console -- Debugging
662
+ console.log('err', filename, error);
663
+ }
664
+
665
+ return [];
666
+ },
667
+ // Todo: Reenable
668
+ supportsAutofix: false,
669
+ },
670
+ },
671
+ };
672
+ };