eslint-plugin-jsdoc 53.0.1 → 54.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) 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 +410 -2
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.ts +17 -2
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/iterateJsdoc.cjs +2007 -1539
  22. package/dist/iterateJsdoc.cjs.map +1 -1
  23. package/dist/iterateJsdoc.d.ts +350 -359
  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 +391 -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 +559 -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 +41 -57
  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 +2542 -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 +545 -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 +744 -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 -2
  231. package/dist/index.js +0 -3
  232. package/dist/iterateJsdoc.d.cts +0 -472
  233. package/dist/iterateJsdoc.d.cts.map +0 -1
  234. package/dist/iterateJsdoc.js +0 -1628
  235. package/dist/iterateJsdoc.js.map +0 -1
  236. package/dist/jsdocUtils.js +0 -1123
  237. package/dist/jsdocUtils.js.map +0 -1
  238. package/dist/plugin.cjs +0 -427
  239. package/dist/plugin.cjs.map +0 -1
  240. package/dist/plugin.js +0 -427
  241. package/dist/plugin.js.map +0 -1
  242. package/dist/rules/checkAccess.js +0 -33
  243. package/dist/rules/checkAccess.js.map +0 -1
  244. package/dist/rules/checkAlignment.js +0 -47
  245. package/dist/rules/checkAlignment.js.map +0 -1
  246. package/dist/rules/checkExamples.js +0 -348
  247. package/dist/rules/checkExamples.js.map +0 -1
  248. package/dist/rules/checkIndentation.js +0 -59
  249. package/dist/rules/checkIndentation.js.map +0 -1
  250. package/dist/rules/checkLineAlignment.js +0 -229
  251. package/dist/rules/checkLineAlignment.js.map +0 -1
  252. package/dist/rules/checkParamNames.js +0 -237
  253. package/dist/rules/checkParamNames.js.map +0 -1
  254. package/dist/rules/checkPropertyNames.js +0 -88
  255. package/dist/rules/checkPropertyNames.js.map +0 -1
  256. package/dist/rules/checkSyntax.js +0 -25
  257. package/dist/rules/checkSyntax.js.map +0 -1
  258. package/dist/rules/checkTagNames.js +0 -191
  259. package/dist/rules/checkTagNames.js.map +0 -1
  260. package/dist/rules/checkTemplateNames.js +0 -124
  261. package/dist/rules/checkTemplateNames.js.map +0 -1
  262. package/dist/rules/checkTypes.js +0 -299
  263. package/dist/rules/checkTypes.js.map +0 -1
  264. package/dist/rules/checkValues.js +0 -103
  265. package/dist/rules/checkValues.js.map +0 -1
  266. package/dist/rules/convertToJsdocComments.js +0 -231
  267. package/dist/rules/convertToJsdocComments.js.map +0 -1
  268. package/dist/rules/emptyTags.js +0 -67
  269. package/dist/rules/emptyTags.js.map +0 -1
  270. package/dist/rules/implementsOnClasses.js +0 -40
  271. package/dist/rules/implementsOnClasses.js.map +0 -1
  272. package/dist/rules/importsAsDependencies.js +0 -68
  273. package/dist/rules/importsAsDependencies.js.map +0 -1
  274. package/dist/rules/informativeDocs.js +0 -110
  275. package/dist/rules/informativeDocs.js.map +0 -1
  276. package/dist/rules/linesBeforeBlock.js +0 -75
  277. package/dist/rules/linesBeforeBlock.js.map +0 -1
  278. package/dist/rules/matchDescription.js +0 -167
  279. package/dist/rules/matchDescription.js.map +0 -1
  280. package/dist/rules/matchName.js +0 -77
  281. package/dist/rules/matchName.js.map +0 -1
  282. package/dist/rules/multilineBlocks.js +0 -245
  283. package/dist/rules/multilineBlocks.js.map +0 -1
  284. package/dist/rules/noBadBlocks.js +0 -68
  285. package/dist/rules/noBadBlocks.js.map +0 -1
  286. package/dist/rules/noBlankBlockDescriptions.js +0 -41
  287. package/dist/rules/noBlankBlockDescriptions.js.map +0 -1
  288. package/dist/rules/noBlankBlocks.js +0 -30
  289. package/dist/rules/noBlankBlocks.js.map +0 -1
  290. package/dist/rules/noDefaults.js +0 -56
  291. package/dist/rules/noDefaults.js.map +0 -1
  292. package/dist/rules/noMissingSyntax.js +0 -126
  293. package/dist/rules/noMissingSyntax.js.map +0 -1
  294. package/dist/rules/noMultiAsterisks.js +0 -58
  295. package/dist/rules/noMultiAsterisks.js.map +0 -1
  296. package/dist/rules/noRestrictedSyntax.js +0 -49
  297. package/dist/rules/noRestrictedSyntax.js.map +0 -1
  298. package/dist/rules/noTypes.js +0 -65
  299. package/dist/rules/noTypes.js.map +0 -1
  300. package/dist/rules/noUndefinedTypes.js +0 -303
  301. package/dist/rules/noUndefinedTypes.js.map +0 -1
  302. package/dist/rules/requireAsteriskPrefix.js +0 -112
  303. package/dist/rules/requireAsteriskPrefix.js.map +0 -1
  304. package/dist/rules/requireDescription.js +0 -95
  305. package/dist/rules/requireDescription.js.map +0 -1
  306. package/dist/rules/requireDescriptionCompleteSentence.js +0 -220
  307. package/dist/rules/requireDescriptionCompleteSentence.js.map +0 -1
  308. package/dist/rules/requireExample.js +0 -77
  309. package/dist/rules/requireExample.js.map +0 -1
  310. package/dist/rules/requireFileOverview.js +0 -81
  311. package/dist/rules/requireFileOverview.js.map +0 -1
  312. package/dist/rules/requireHyphenBeforeParamDescription.js +0 -89
  313. package/dist/rules/requireHyphenBeforeParamDescription.js.map +0 -1
  314. package/dist/rules/requireJsdoc.js +0 -404
  315. package/dist/rules/requireJsdoc.js.map +0 -1
  316. package/dist/rules/requireParam.js +0 -344
  317. package/dist/rules/requireParam.js.map +0 -1
  318. package/dist/rules/requireParamDescription.js +0 -59
  319. package/dist/rules/requireParamDescription.js.map +0 -1
  320. package/dist/rules/requireParamName.js +0 -36
  321. package/dist/rules/requireParamName.js.map +0 -1
  322. package/dist/rules/requireParamType.js +0 -59
  323. package/dist/rules/requireParamType.js.map +0 -1
  324. package/dist/rules/requireProperty.js +0 -35
  325. package/dist/rules/requireProperty.js.map +0 -1
  326. package/dist/rules/requirePropertyDescription.js +0 -21
  327. package/dist/rules/requirePropertyDescription.js.map +0 -1
  328. package/dist/rules/requirePropertyName.js +0 -21
  329. package/dist/rules/requirePropertyName.js.map +0 -1
  330. package/dist/rules/requirePropertyType.js +0 -21
  331. package/dist/rules/requirePropertyType.js.map +0 -1
  332. package/dist/rules/requireReturns.js +0 -131
  333. package/dist/rules/requireReturns.js.map +0 -1
  334. package/dist/rules/requireReturnsCheck.js +0 -66
  335. package/dist/rules/requireReturnsCheck.js.map +0 -1
  336. package/dist/rules/requireReturnsDescription.js +0 -43
  337. package/dist/rules/requireReturnsDescription.js.map +0 -1
  338. package/dist/rules/requireReturnsType.js +0 -36
  339. package/dist/rules/requireReturnsType.js.map +0 -1
  340. package/dist/rules/requireTemplate.js +0 -122
  341. package/dist/rules/requireTemplate.js.map +0 -1
  342. package/dist/rules/requireThrows.js +0 -67
  343. package/dist/rules/requireThrows.js.map +0 -1
  344. package/dist/rules/requireYields.js +0 -115
  345. package/dist/rules/requireYields.js.map +0 -1
  346. package/dist/rules/requireYieldsCheck.js +0 -105
  347. package/dist/rules/requireYieldsCheck.js.map +0 -1
  348. package/dist/rules/sortTags.js +0 -262
  349. package/dist/rules/sortTags.js.map +0 -1
  350. package/dist/rules/tagLines.js +0 -183
  351. package/dist/rules/tagLines.js.map +0 -1
  352. package/dist/rules/textEscaping.js +0 -102
  353. package/dist/rules/textEscaping.js.map +0 -1
  354. package/dist/rules/validTypes.js +0 -259
  355. package/dist/rules/validTypes.js.map +0 -1
  356. package/dist/tagNames.js +0 -144
  357. package/dist/tagNames.js.map +0 -1
  358. package/dist/utils/hasReturnValue.js +0 -265
  359. 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
+ };