@shivaedev/quality 0.3.1 → 0.5.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 (391) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +187 -30
  3. package/biome/declarations.json +17 -0
  4. package/biome/plugins/ambient-runtime.grit +18 -0
  5. package/biome/plugins/effect-fn-spans.grit +7 -0
  6. package/biome/preset.json +602 -0
  7. package/dist/baseline/compare.d.ts +8 -9
  8. package/dist/baseline/compare.d.ts.map +1 -1
  9. package/dist/baseline/compare.js +4 -4
  10. package/dist/baseline/compare.js.map +1 -1
  11. package/dist/baseline/format.d.ts +4 -4
  12. package/dist/baseline/format.d.ts.map +1 -1
  13. package/dist/baseline/format.js +3 -2
  14. package/dist/baseline/format.js.map +1 -1
  15. package/dist/baseline/guard.d.ts +3 -3
  16. package/dist/baseline/guard.d.ts.map +1 -1
  17. package/dist/baseline/guard.js +6 -5
  18. package/dist/baseline/guard.js.map +1 -1
  19. package/dist/baseline/legacy.d.ts +3 -3
  20. package/dist/baseline/legacy.d.ts.map +1 -1
  21. package/dist/baseline/legacy.js.map +1 -1
  22. package/dist/baseline/rewrite.d.ts +1 -1
  23. package/dist/baseline/rewrite.d.ts.map +1 -1
  24. package/dist/baseline/rewrite.js.map +1 -1
  25. package/dist/baseline/update.d.ts +8 -9
  26. package/dist/baseline/update.d.ts.map +1 -1
  27. package/dist/baseline/update.js +10 -9
  28. package/dist/baseline/update.js.map +1 -1
  29. package/dist/biome/report.d.ts +33 -0
  30. package/dist/biome/report.d.ts.map +1 -0
  31. package/dist/biome/report.js +25 -0
  32. package/dist/biome/report.js.map +1 -0
  33. package/dist/biome/run.d.ts +7 -0
  34. package/dist/biome/run.d.ts.map +1 -0
  35. package/dist/biome/run.js +16 -0
  36. package/dist/biome/run.js.map +1 -0
  37. package/dist/cli/args.d.ts +6 -3
  38. package/dist/cli/args.d.ts.map +1 -1
  39. package/dist/cli/args.js +9 -4
  40. package/dist/cli/args.js.map +1 -1
  41. package/dist/cli/baseline.d.ts +1 -1
  42. package/dist/cli/baseline.d.ts.map +1 -1
  43. package/dist/cli/baseline.js +3 -3
  44. package/dist/cli/baseline.js.map +1 -1
  45. package/dist/cli/check.js.map +1 -1
  46. package/dist/cli/fix.d.ts +4 -0
  47. package/dist/cli/fix.d.ts.map +1 -0
  48. package/dist/cli/fix.js +19 -0
  49. package/dist/cli/fix.js.map +1 -0
  50. package/dist/cli/lint.js +1 -1
  51. package/dist/cli/lint.js.map +1 -1
  52. package/dist/cli/run-main.d.ts.map +1 -1
  53. package/dist/cli/run-main.js +7 -3
  54. package/dist/cli/run-main.js.map +1 -1
  55. package/dist/cli.js +3 -0
  56. package/dist/cli.js.map +1 -1
  57. package/dist/config/decode.d.ts +4 -4
  58. package/dist/config/decode.js +12 -12
  59. package/dist/config/decode.js.map +1 -1
  60. package/dist/config/load.d.ts +3 -3
  61. package/dist/config/load.d.ts.map +1 -1
  62. package/dist/config/load.js +1 -1
  63. package/dist/config/load.js.map +1 -1
  64. package/dist/config/resolve.d.ts +3 -5
  65. package/dist/config/resolve.d.ts.map +1 -1
  66. package/dist/config/resolve.js +11 -5
  67. package/dist/config/resolve.js.map +1 -1
  68. package/dist/config.d.ts +9 -9
  69. package/dist/config.d.ts.map +1 -1
  70. package/dist/config.js.map +1 -1
  71. package/dist/decoded.d.ts +1 -1
  72. package/dist/decoded.d.ts.map +1 -1
  73. package/dist/engine/baseline-file.d.ts +1 -1
  74. package/dist/engine/baseline-file.d.ts.map +1 -1
  75. package/dist/engine/evaluate.d.ts +8 -9
  76. package/dist/engine/evaluate.d.ts.map +1 -1
  77. package/dist/engine/evaluate.js +4 -4
  78. package/dist/engine/evaluate.js.map +1 -1
  79. package/dist/engine/run-rules.d.ts +4 -3
  80. package/dist/engine/run-rules.d.ts.map +1 -1
  81. package/dist/engine/run-rules.js +3 -3
  82. package/dist/engine/run-rules.js.map +1 -1
  83. package/dist/engine/session.d.ts +3 -3
  84. package/dist/engine/session.d.ts.map +1 -1
  85. package/dist/engine/violation.d.ts +11 -3
  86. package/dist/engine/violation.d.ts.map +1 -1
  87. package/dist/engine/violation.js +6 -2
  88. package/dist/engine/violation.js.map +1 -1
  89. package/dist/exceptions/registry.d.ts +7 -8
  90. package/dist/exceptions/registry.d.ts.map +1 -1
  91. package/dist/exceptions/registry.js +6 -6
  92. package/dist/exceptions/registry.js.map +1 -1
  93. package/dist/git/base.d.ts +1 -1
  94. package/dist/git/base.d.ts.map +1 -1
  95. package/dist/git/base.js.map +1 -1
  96. package/dist/git/command.d.ts +3 -3
  97. package/dist/git/command.d.ts.map +1 -1
  98. package/dist/git/command.js.map +1 -1
  99. package/dist/git/history.d.ts +1 -1
  100. package/dist/git/history.d.ts.map +1 -1
  101. package/dist/git/history.js +1 -1
  102. package/dist/git/history.js.map +1 -1
  103. package/dist/imports/ambient.d.ts +7 -0
  104. package/dist/imports/ambient.d.ts.map +1 -0
  105. package/dist/imports/ambient.js +44 -0
  106. package/dist/imports/ambient.js.map +1 -0
  107. package/dist/imports/components.d.ts +2 -0
  108. package/dist/imports/components.d.ts.map +1 -0
  109. package/dist/imports/components.js +63 -0
  110. package/dist/imports/components.js.map +1 -0
  111. package/dist/imports/extract.d.ts +10 -0
  112. package/dist/imports/extract.d.ts.map +1 -0
  113. package/dist/imports/extract.js +100 -0
  114. package/dist/imports/extract.js.map +1 -0
  115. package/dist/imports/fences/dsl.d.ts +18 -0
  116. package/dist/imports/fences/dsl.d.ts.map +1 -0
  117. package/dist/imports/fences/dsl.js +14 -0
  118. package/dist/imports/fences/dsl.js.map +1 -0
  119. package/dist/imports/fences/evaluate.d.ts +12 -0
  120. package/dist/imports/fences/evaluate.d.ts.map +1 -0
  121. package/dist/imports/fences/evaluate.js +55 -0
  122. package/dist/imports/fences/evaluate.js.map +1 -0
  123. package/dist/imports/fences/match.d.ts +17 -0
  124. package/dist/imports/fences/match.d.ts.map +1 -0
  125. package/dist/imports/fences/match.js +106 -0
  126. package/dist/imports/fences/match.js.map +1 -0
  127. package/dist/imports/fences/model.d.ts +60 -0
  128. package/dist/imports/fences/model.d.ts.map +1 -0
  129. package/dist/imports/fences/model.js +2 -0
  130. package/dist/imports/fences/model.js.map +1 -0
  131. package/dist/imports/fences/policy.d.ts +5 -0
  132. package/dist/imports/fences/policy.d.ts.map +1 -0
  133. package/dist/imports/fences/policy.js +59 -0
  134. package/dist/imports/fences/policy.js.map +1 -0
  135. package/dist/imports/fences/reach.d.ts +12 -0
  136. package/dist/imports/fences/reach.d.ts.map +1 -0
  137. package/dist/imports/fences/reach.js +39 -0
  138. package/dist/imports/fences/reach.js.map +1 -0
  139. package/dist/imports/fences/selectors.d.ts +11 -0
  140. package/dist/imports/fences/selectors.d.ts.map +1 -0
  141. package/dist/imports/fences/selectors.js +27 -0
  142. package/dist/imports/fences/selectors.js.map +1 -0
  143. package/dist/imports/fences/vocabulary.d.ts +9 -0
  144. package/dist/imports/fences/vocabulary.d.ts.map +1 -0
  145. package/dist/imports/fences/vocabulary.js +40 -0
  146. package/dist/imports/fences/vocabulary.js.map +1 -0
  147. package/dist/imports/generated.d.ts +6 -0
  148. package/dist/imports/generated.d.ts.map +1 -0
  149. package/dist/imports/generated.js +78 -0
  150. package/dist/imports/generated.js.map +1 -0
  151. package/dist/imports/glob.d.ts +2 -0
  152. package/dist/imports/glob.d.ts.map +1 -0
  153. package/dist/imports/glob.js +125 -0
  154. package/dist/imports/glob.js.map +1 -0
  155. package/dist/imports/graph.d.ts +23 -0
  156. package/dist/imports/graph.d.ts.map +1 -0
  157. package/dist/imports/graph.js +56 -0
  158. package/dist/imports/graph.js.map +1 -0
  159. package/dist/imports/paths.d.ts +2 -0
  160. package/dist/imports/paths.d.ts.map +1 -0
  161. package/dist/imports/paths.js +24 -0
  162. package/dist/imports/paths.js.map +1 -0
  163. package/dist/imports/pnpm-workspace.d.ts +2 -0
  164. package/dist/imports/pnpm-workspace.d.ts.map +1 -0
  165. package/dist/imports/pnpm-workspace.js +122 -0
  166. package/dist/imports/pnpm-workspace.js.map +1 -0
  167. package/dist/imports/projects.d.ts +10 -0
  168. package/dist/imports/projects.d.ts.map +1 -0
  169. package/dist/imports/projects.js +83 -0
  170. package/dist/imports/projects.js.map +1 -0
  171. package/dist/imports/resolve.d.ts +16 -0
  172. package/dist/imports/resolve.d.ts.map +1 -0
  173. package/dist/imports/resolve.js +88 -0
  174. package/dist/imports/resolve.js.map +1 -0
  175. package/dist/imports/workspace.d.ts +10 -0
  176. package/dist/imports/workspace.d.ts.map +1 -0
  177. package/dist/imports/workspace.js +55 -0
  178. package/dist/imports/workspace.js.map +1 -0
  179. package/dist/index.d.ts +3 -0
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +2 -0
  182. package/dist/index.js.map +1 -1
  183. package/dist/inventory/collect.d.ts +6 -6
  184. package/dist/inventory/collect.d.ts.map +1 -1
  185. package/dist/inventory/collect.js.map +1 -1
  186. package/dist/manifests/sorted.d.ts +14 -0
  187. package/dist/manifests/sorted.d.ts.map +1 -0
  188. package/dist/manifests/sorted.js +39 -0
  189. package/dist/manifests/sorted.js.map +1 -0
  190. package/dist/report/guard.d.ts +1 -1
  191. package/dist/report/guard.d.ts.map +1 -1
  192. package/dist/report/guard.js +1 -1
  193. package/dist/report/guard.js.map +1 -1
  194. package/dist/report/render.d.ts +2 -2
  195. package/dist/report/render.d.ts.map +1 -1
  196. package/dist/report/render.js.map +1 -1
  197. package/dist/report/stale.d.ts +2 -2
  198. package/dist/report/stale.d.ts.map +1 -1
  199. package/dist/report/stale.js.map +1 -1
  200. package/dist/rule.d.ts +12 -11
  201. package/dist/rule.d.ts.map +1 -1
  202. package/dist/rule.js.map +1 -1
  203. package/dist/rules/biome.d.ts +4 -0
  204. package/dist/rules/biome.d.ts.map +1 -0
  205. package/dist/rules/biome.js +40 -0
  206. package/dist/rules/biome.js.map +1 -0
  207. package/dist/rules/built-in.d.ts +8 -10
  208. package/dist/rules/built-in.d.ts.map +1 -1
  209. package/dist/rules/built-in.js +12 -0
  210. package/dist/rules/built-in.js.map +1 -1
  211. package/dist/rules/comments/kinds.d.ts +1 -2
  212. package/dist/rules/comments/kinds.d.ts.map +1 -1
  213. package/dist/rules/comments/kinds.js +7 -16
  214. package/dist/rules/comments/kinds.js.map +1 -1
  215. package/dist/rules/comments/max-per-file.d.ts +1 -1
  216. package/dist/rules/comments/max-per-file.js +11 -11
  217. package/dist/rules/comments/max-per-file.js.map +1 -1
  218. package/dist/rules/comments/no-banner.js +2 -2
  219. package/dist/rules/comments/no-banner.js.map +1 -1
  220. package/dist/rules/comments/no-environment-pragma.d.ts +2 -0
  221. package/dist/rules/comments/no-environment-pragma.d.ts.map +1 -0
  222. package/dist/rules/comments/no-environment-pragma.js +8 -0
  223. package/dist/rules/comments/no-environment-pragma.js.map +1 -0
  224. package/dist/rules/comments/no-jsdoc.js +3 -3
  225. package/dist/rules/comments/no-jsdoc.js.map +1 -1
  226. package/dist/rules/comments/no-line-reference.js +2 -2
  227. package/dist/rules/comments/no-line-reference.js.map +1 -1
  228. package/dist/rules/comments/no-pr-reference.js +6 -6
  229. package/dist/rules/comments/no-pr-reference.js.map +1 -1
  230. package/dist/rules/comments/no-todo.js +2 -2
  231. package/dist/rules/comments/no-todo.js.map +1 -1
  232. package/dist/rules/comments/pattern-rule.d.ts +2 -2
  233. package/dist/rules/comments/pattern-rule.d.ts.map +1 -1
  234. package/dist/rules/comments/pattern-rule.js +2 -2
  235. package/dist/rules/comments/pattern-rule.js.map +1 -1
  236. package/dist/rules/comments/scan.d.ts +6 -6
  237. package/dist/rules/comments/scan.d.ts.map +1 -1
  238. package/dist/rules/comments/scan.js +2 -2
  239. package/dist/rules/comments/scan.js.map +1 -1
  240. package/dist/rules/imports/cycles.d.ts +2 -0
  241. package/dist/rules/imports/cycles.d.ts.map +1 -0
  242. package/dist/rules/imports/cycles.js +38 -0
  243. package/dist/rules/imports/cycles.js.map +1 -0
  244. package/dist/rules/imports/fences.d.ts +5 -0
  245. package/dist/rules/imports/fences.d.ts.map +1 -0
  246. package/dist/rules/imports/fences.js +24 -0
  247. package/dist/rules/imports/fences.js.map +1 -0
  248. package/dist/rules/imports/resolvable.d.ts +4 -0
  249. package/dist/rules/imports/resolvable.d.ts.map +1 -0
  250. package/dist/rules/imports/resolvable.js +22 -0
  251. package/dist/rules/imports/resolvable.js.map +1 -0
  252. package/dist/rules/manifests-sorted.d.ts +2 -0
  253. package/dist/rules/manifests-sorted.d.ts.map +1 -0
  254. package/dist/rules/manifests-sorted.js +22 -0
  255. package/dist/rules/manifests-sorted.js.map +1 -0
  256. package/dist/rules/max-lines.js +4 -4
  257. package/dist/rules/max-lines.js.map +1 -1
  258. package/dist/rules/suppressions/biome/configs.d.ts +21 -10
  259. package/dist/rules/suppressions/biome/configs.d.ts.map +1 -1
  260. package/dist/rules/suppressions/biome/configs.js +58 -22
  261. package/dist/rules/suppressions/biome/configs.js.map +1 -1
  262. package/dist/rules/suppressions/biome/declarations.d.ts +18 -0
  263. package/dist/rules/suppressions/biome/declarations.d.ts.map +1 -0
  264. package/dist/rules/suppressions/biome/declarations.js +20 -0
  265. package/dist/rules/suppressions/biome/declarations.js.map +1 -0
  266. package/dist/rules/suppressions/biome/json.d.ts +2 -2
  267. package/dist/rules/suppressions/biome/json.d.ts.map +1 -1
  268. package/dist/rules/suppressions/biome/json.js +1 -1
  269. package/dist/rules/suppressions/biome/json.js.map +1 -1
  270. package/dist/rules/suppressions/biome/resolve.d.ts +3 -0
  271. package/dist/rules/suppressions/biome/resolve.d.ts.map +1 -0
  272. package/dist/rules/suppressions/biome/resolve.js +70 -0
  273. package/dist/rules/suppressions/biome/resolve.js.map +1 -0
  274. package/dist/rules/suppressions/biome/weakenings.d.ts +5 -5
  275. package/dist/rules/suppressions/biome/weakenings.d.ts.map +1 -1
  276. package/dist/rules/suppressions/biome/weakenings.js +41 -33
  277. package/dist/rules/suppressions/biome/weakenings.js.map +1 -1
  278. package/dist/rules/suppressions/biome-overrides.d.ts +1 -1
  279. package/dist/rules/suppressions/biome-overrides.d.ts.map +1 -1
  280. package/dist/rules/suppressions/biome-overrides.js +35 -27
  281. package/dist/rules/suppressions/biome-overrides.js.map +1 -1
  282. package/dist/rules/suppressions/directives.d.ts +1 -1
  283. package/dist/rules/suppressions/directives.d.ts.map +1 -1
  284. package/dist/rules/suppressions/directives.js +11 -11
  285. package/dist/rules/suppressions/directives.js.map +1 -1
  286. package/dist/rules/suppressions/no-double-cast.js +2 -2
  287. package/dist/rules/suppressions/no-double-cast.js.map +1 -1
  288. package/dist/rules/suppressions/no-inline.d.ts +1 -7
  289. package/dist/rules/suppressions/no-inline.d.ts.map +1 -1
  290. package/dist/rules/suppressions/no-inline.js +7 -30
  291. package/dist/rules/suppressions/no-inline.js.map +1 -1
  292. package/dist/rules/suppressions/stylesheet-comments.d.ts +1 -1
  293. package/dist/rules/suppressions/stylesheet-comments.d.ts.map +1 -1
  294. package/dist/rules/suppressions/stylesheet-comments.js +3 -3
  295. package/dist/rules/suppressions/stylesheet-comments.js.map +1 -1
  296. package/dist/rules/syntax.js +4 -4
  297. package/dist/rules/syntax.js.map +1 -1
  298. package/dist/standard-schema.d.ts +1 -1
  299. package/dist/standard-schema.d.ts.map +1 -1
  300. package/dist/vitest.d.ts +3 -0
  301. package/dist/vitest.d.ts.map +1 -0
  302. package/dist/vitest.js +20 -0
  303. package/dist/vitest.js.map +1 -0
  304. package/package.json +48 -31
  305. package/src/baseline/compare.ts +10 -15
  306. package/src/baseline/format.ts +8 -6
  307. package/src/baseline/guard.ts +11 -10
  308. package/src/baseline/legacy.ts +3 -3
  309. package/src/baseline/rewrite.ts +1 -1
  310. package/src/baseline/update.ts +21 -21
  311. package/src/biome/report.ts +35 -0
  312. package/src/biome/run.ts +23 -0
  313. package/src/cli/args.ts +14 -8
  314. package/src/cli/baseline.ts +5 -6
  315. package/src/cli/check.ts +1 -1
  316. package/src/cli/fix.ts +19 -0
  317. package/src/cli/lint.ts +1 -1
  318. package/src/cli/run-main.ts +8 -3
  319. package/src/cli.ts +3 -0
  320. package/src/config/decode.ts +12 -12
  321. package/src/config/load.ts +4 -4
  322. package/src/config/resolve.ts +15 -11
  323. package/src/config.ts +9 -9
  324. package/src/decoded.ts +1 -1
  325. package/src/engine/baseline-file.ts +1 -1
  326. package/src/engine/evaluate.ts +14 -16
  327. package/src/engine/run-rules.ts +8 -7
  328. package/src/engine/session.ts +3 -3
  329. package/src/engine/violation.ts +18 -4
  330. package/src/exceptions/registry.ts +10 -16
  331. package/src/git/base.ts +2 -2
  332. package/src/git/command.ts +3 -3
  333. package/src/git/history.ts +2 -2
  334. package/src/imports/ambient.ts +54 -0
  335. package/src/imports/components.ts +80 -0
  336. package/src/imports/extract.ts +129 -0
  337. package/src/imports/fences/dsl.ts +33 -0
  338. package/src/imports/fences/evaluate.ts +75 -0
  339. package/src/imports/fences/match.ts +148 -0
  340. package/src/imports/fences/model.ts +42 -0
  341. package/src/imports/fences/policy.ts +70 -0
  342. package/src/imports/fences/reach.ts +62 -0
  343. package/src/imports/fences/selectors.ts +37 -0
  344. package/src/imports/fences/vocabulary.ts +51 -0
  345. package/src/imports/generated.ts +95 -0
  346. package/src/imports/glob.ts +142 -0
  347. package/src/imports/graph.ts +81 -0
  348. package/src/imports/paths.ts +28 -0
  349. package/src/imports/pnpm-workspace.ts +134 -0
  350. package/src/imports/projects.ts +106 -0
  351. package/src/imports/resolve.ts +115 -0
  352. package/src/imports/workspace.ts +76 -0
  353. package/src/index.ts +3 -0
  354. package/src/inventory/collect.ts +6 -6
  355. package/src/manifests/sorted.ts +46 -0
  356. package/src/report/guard.ts +2 -2
  357. package/src/report/render.ts +9 -9
  358. package/src/report/stale.ts +3 -3
  359. package/src/rule.ts +13 -12
  360. package/src/rules/biome.ts +47 -0
  361. package/src/rules/built-in.ts +12 -0
  362. package/src/rules/comments/kinds.ts +11 -21
  363. package/src/rules/comments/max-per-file.ts +13 -13
  364. package/src/rules/comments/no-banner.ts +2 -2
  365. package/src/rules/comments/no-environment-pragma.ts +9 -0
  366. package/src/rules/comments/no-jsdoc.ts +3 -3
  367. package/src/rules/comments/no-line-reference.ts +2 -2
  368. package/src/rules/comments/no-pr-reference.ts +6 -6
  369. package/src/rules/comments/no-todo.ts +2 -2
  370. package/src/rules/comments/pattern-rule.ts +6 -6
  371. package/src/rules/comments/scan.ts +13 -13
  372. package/src/rules/imports/cycles.ts +44 -0
  373. package/src/rules/imports/fences.ts +27 -0
  374. package/src/rules/imports/resolvable.ts +23 -0
  375. package/src/rules/manifests-sorted.ts +23 -0
  376. package/src/rules/max-lines.ts +6 -6
  377. package/src/rules/suppressions/biome/configs.ts +99 -30
  378. package/src/rules/suppressions/biome/declarations.ts +37 -0
  379. package/src/rules/suppressions/biome/json.ts +3 -3
  380. package/src/rules/suppressions/biome/resolve.ts +86 -0
  381. package/src/rules/suppressions/biome/weakenings.ts +64 -48
  382. package/src/rules/suppressions/biome-overrides.ts +45 -36
  383. package/src/rules/suppressions/directives.ts +12 -12
  384. package/src/rules/suppressions/no-double-cast.ts +4 -4
  385. package/src/rules/suppressions/no-inline.ts +13 -37
  386. package/src/rules/suppressions/stylesheet-comments.ts +4 -4
  387. package/src/rules/syntax.ts +4 -4
  388. package/src/standard-schema.ts +1 -1
  389. package/src/vitest.ts +22 -0
  390. package/tsconfig/base.json +35 -0
  391. package/tsconfig/package.json +10 -0
@@ -1,15 +1,19 @@
1
+ import type { Chain, Layer } from "./configs.ts";
2
+ import { scoped } from "./declarations.ts";
1
3
  import { entriesOf, isFalse, itemsOf, type Json, member, textOf } from "./json.ts";
2
4
 
3
5
  export interface Weakening {
4
- readonly rule: string;
5
- readonly includes: ReadonlyArray<string>;
6
- readonly file: string;
6
+ readonly includes: readonly string[];
7
+ readonly layer: Layer;
7
8
  readonly line: number;
9
+ readonly rule: string;
8
10
  }
9
11
 
10
12
  interface Setting {
11
- readonly rule: string;
12
13
  readonly line: number;
14
+ readonly rule: string;
15
+ readonly weak: boolean;
16
+ readonly wholeGroup: boolean;
13
17
  }
14
18
 
15
19
  const LINT_WEAK = new Set(["off", "warn", "info"]);
@@ -18,43 +22,49 @@ const PRESETS = new Set(["recommended", "preset"]);
18
22
 
19
23
  const levelOf = (node: Json): string | undefined => textOf(node) ?? textOf(member(node, "level"));
20
24
 
21
- const at = (rule: string, node: Json | undefined): ReadonlyArray<Setting> => (node === undefined ? [] : [{ line: node.line, rule }]);
25
+ const at = (rule: string, node: Json | undefined, weak: boolean, wholeGroup = false): readonly Setting[] =>
26
+ node === undefined ? [] : [{ line: node.line, rule, weak, wholeGroup }];
22
27
 
23
- const disabled = (rule: string, section: Json | undefined): ReadonlyArray<Setting> =>
24
- isFalse(member(section, "enabled")) ? at(rule, member(section, "enabled")) : [];
28
+ const enabled = (rule: string, section: Json | undefined): readonly Setting[] =>
29
+ at(rule, member(section, "enabled"), isFalse(member(section, "enabled")));
25
30
 
26
- const withoutDefaults = (rule: string, set: Json | undefined): ReadonlyArray<Setting> => [
27
- ...(isFalse(member(set, "recommended")) ? at(rule, member(set, "recommended")) : []),
28
- ...(textOf(member(set, "preset")) === "none" ? at(rule, member(set, "preset")) : []),
31
+ const defaults = (rule: string, set: Json | undefined): readonly Setting[] => [
32
+ ...at(rule, member(set, "recommended"), isFalse(member(set, "recommended"))),
33
+ ...at(rule, member(set, "preset"), textOf(member(set, "preset")) === "none"),
29
34
  ];
30
35
 
31
- const groupSettings = (prefix: string, weak: ReadonlySet<string>, groups: Json | undefined): ReadonlyArray<Setting> =>
36
+ const ruleSettings = (group: string, weak: ReadonlySet<string>, rules: Json): readonly Setting[] =>
37
+ entriesOf(rules)
38
+ .filter(([rule]) => !PRESETS.has(rule))
39
+ .flatMap(([rule, setting]) => {
40
+ const level = levelOf(setting);
41
+ return level === undefined ? [] : at(`${group}/${rule}`, setting, weak.has(level));
42
+ });
43
+
44
+ const groupSettings = (prefix: string, weak: ReadonlySet<string>, groups: Json | undefined): readonly Setting[] =>
32
45
  entriesOf(groups)
33
46
  .filter(([group]) => !PRESETS.has(group))
34
- .flatMap(([group, rules]) => [
35
- ...(weak.has(textOf(rules) ?? "") ? at(`${prefix}/${group}`, rules) : []),
36
- ...withoutDefaults(`${prefix}/${group}`, rules),
37
- ...entriesOf(rules)
38
- .filter(([rule, setting]) => !PRESETS.has(rule) && weak.has(levelOf(setting) ?? ""))
39
- .flatMap(([rule, setting]) => at(`${prefix}/${group}/${rule}`, setting)),
40
- ]);
41
-
42
- const linter = (section: Json | undefined): ReadonlyArray<Setting> => [
43
- ...disabled("lint", section),
44
- ...withoutDefaults("lint/recommended", member(section, "rules")),
47
+ .flatMap(([group, rules]) => {
48
+ const severity = textOf(rules);
49
+ return severity === undefined
50
+ ? [...defaults(`${prefix}/${group}`, rules), ...ruleSettings(`${prefix}/${group}`, weak, rules)]
51
+ : at(`${prefix}/${group}`, rules, weak.has(severity), true);
52
+ });
53
+
54
+ const linter = (section: Json | undefined): readonly Setting[] => [
55
+ ...enabled("lint", section),
56
+ ...defaults("lint/recommended", member(section, "rules")),
45
57
  ...groupSettings("lint", LINT_WEAK, member(section, "rules")),
46
- ...entriesOf(member(section, "domains"))
47
- .filter(([, value]) => textOf(value) === "none")
48
- .flatMap(([domain, value]) => at(`lint/domains/${domain}`, value)),
58
+ ...entriesOf(member(section, "domains")).flatMap(([domain, value]) => at(`lint/domains/${domain}`, value, textOf(value) === "none")),
49
59
  ];
50
60
 
51
- const assist = (section: Json | undefined): ReadonlyArray<Setting> => [
52
- ...disabled("assist", section),
53
- ...withoutDefaults("assist/recommended", member(section, "actions")),
61
+ const assist = (section: Json | undefined): readonly Setting[] => [
62
+ ...enabled("assist", section),
63
+ ...defaults("assist/recommended", member(section, "actions")),
54
64
  ...groupSettings("assist", ASSIST_WEAK, member(section, "actions")),
55
65
  ];
56
66
 
57
- const LANGUAGES: ReadonlyArray<string> = ["javascript", "json", "css", "graphql", "grit", "html"];
67
+ const LANGUAGES: readonly string[] = ["javascript", "json", "css", "graphql", "grit", "html"];
58
68
 
59
69
  const TOOLS: ReadonlyArray<readonly [string, string]> = [
60
70
  ["linter", "lint"],
@@ -64,39 +74,45 @@ const TOOLS: ReadonlyArray<readonly [string, string]> = [
64
74
 
65
75
  const SCOPED_SECTIONS: ReadonlyArray<readonly [string, string]> = [["files", "files"], ...TOOLS];
66
76
 
67
- const scopeSettings = (scope: Json): ReadonlyArray<Setting> => [
77
+ const settingsOf = (scope: Json): readonly Setting[] => [
68
78
  ...linter(member(scope, "linter")),
69
79
  ...assist(member(scope, "assist")),
70
- ...disabled("format", member(scope, "formatter")),
71
- ...LANGUAGES.flatMap((language) => TOOLS.flatMap(([key, name]) => disabled(`${language}/${name}`, member(member(scope, language), key)))),
80
+ ...enabled("format", member(scope, "formatter")),
81
+ ...LANGUAGES.flatMap((language) => TOOLS.flatMap(([key, name]) => enabled(`${language}/${name}`, member(member(scope, language), key)))),
72
82
  ];
73
83
 
74
- const scoped = (base: string, glob: string): string => {
75
- const [, negation = "", path = glob] = /^(!*)(.*)$/.exec(glob) ?? [];
76
- return base === "" ? glob : `${negation}${base}/${path}`;
77
- };
84
+ const replaces = (later: Setting, earlier: Setting): boolean =>
85
+ later.rule === earlier.rule || (later.wholeGroup && earlier.rule.startsWith(`${later.rule}/`));
78
86
 
79
- const includesOf = (override: Json): ReadonlyArray<string> => {
87
+ const includesOf = (override: Json): readonly string[] => {
80
88
  const includes = itemsOf(member(override, "includes")).flatMap((item) => textOf(item) ?? []);
81
89
  return includes.length === 0 ? ["**"] : includes;
82
90
  };
83
91
 
84
- const narrowsScope = (globs: ReadonlyArray<string>): boolean =>
85
- globs.length > 0 && (globs.some((glob) => glob.startsWith("!")) || !globs.includes("**"));
92
+ const narrowsScope = (globs: readonly string[]): boolean => globs.length > 0 && (globs.some((glob) => glob.startsWith("!")) || !globs.includes("**"));
86
93
 
87
- const narrowings = (config: Json, file: string, base: string): ReadonlyArray<Weakening> =>
94
+ const narrowings = (config: Json, base: string): readonly Omit<Weakening, "layer">[] =>
88
95
  SCOPED_SECTIONS.flatMap(([key, name]) => {
89
96
  const list = member(member(config, key), "includes");
90
97
  const globs = itemsOf(list).flatMap((item) => textOf(item) ?? []);
91
98
  return list === undefined || !narrowsScope(globs)
92
99
  ? []
93
- : [{ file, includes: globs.map((glob) => scoped(base, glob)), line: list.line, rule: `${name}/includes` }];
100
+ : [{ includes: globs.map((glob) => scoped(base, glob)), line: list.line, rule: `${name}/includes` }];
94
101
  });
95
102
 
96
- export const weakeningsOf = (config: Json, file: string, base: string): ReadonlyArray<Weakening> => [
97
- ...narrowings(config, file, base),
98
- ...scopeSettings(config).map((setting) => ({ ...setting, file, includes: [scoped(base, "**")] })),
99
- ...itemsOf(member(config, "overrides")).flatMap((override) =>
100
- scopeSettings(override).map((setting) => ({ ...setting, file, includes: includesOf(override).map((glob) => scoped(base, glob)) })),
101
- ),
102
- ];
103
+ const layerWeakenings = (layer: Layer, later: readonly Layer[], base: string): readonly Weakening[] => {
104
+ const overriding = later.flatMap((next) => settingsOf(next.json));
105
+ const top = settingsOf(layer.json).filter((setting) => setting.weak && !overriding.some((next) => replaces(next, setting)));
106
+ return [
107
+ ...narrowings(layer.json, base),
108
+ ...top.map(({ line, rule }) => ({ includes: [scoped(base, "**")], line, rule })),
109
+ ...itemsOf(member(layer.json, "overrides")).flatMap((override) =>
110
+ settingsOf(override)
111
+ .filter((setting) => setting.weak)
112
+ .map(({ line, rule }) => ({ includes: includesOf(override).map((glob) => scoped(base, glob)), line, rule })),
113
+ ),
114
+ ].map((weakening) => ({ ...weakening, layer }));
115
+ };
116
+
117
+ export const weakeningsOf = ({ base, layers }: Chain): readonly Weakening[] =>
118
+ layers.flatMap((layer, index) => layerWeakenings(layer, layers.slice(index + 1), base));
@@ -1,61 +1,70 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { defineRule, type Finding } from "../../rule.ts";
3
- import { biomeConfigs, type Config } from "./biome/configs.ts";
3
+ import { biomeConfigs, type Chain } from "./biome/configs.ts";
4
+ import { Declaration, matches, type Scoped, scoped, scopeText } from "./biome/declarations.ts";
4
5
  import { type Weakening, weakeningsOf } from "./biome/weakenings.ts";
5
6
 
6
- const Declaration = Schema.Struct({
7
- rule: Schema.NonEmptyString,
8
- includes: Schema.NonEmptyArray(Schema.NonEmptyString),
9
- reason: Schema.String.check(Schema.isPattern(/\S/, { expected: "a reason that says why the scope needs the rule weakened" })),
10
- });
11
-
12
- type Declaration = typeof Declaration.Type;
13
-
14
7
  const BiomeOverridesOptions = Schema.Struct({
15
8
  declared: Schema.Array(Declaration).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
16
9
  });
17
10
 
18
- const sameScope = (left: ReadonlyArray<string>, right: ReadonlyArray<string>): boolean =>
19
- new Set(left).size === new Set(right).size && left.every((glob) => right.includes(glob));
11
+ interface Shipped extends Scoped {
12
+ readonly specifier: string;
13
+ }
20
14
 
21
- const matches = (declaration: Declaration, weakening: Weakening): boolean =>
22
- declaration.rule === weakening.rule && sameScope(declaration.includes, weakening.includes);
15
+ const shippedBy = ({ base, layers }: Chain): readonly Shipped[] =>
16
+ layers.flatMap(({ preset }) =>
17
+ preset === undefined
18
+ ? []
19
+ : preset.declared.map(({ includes, rule }) => ({ includes: includes.map((glob) => scoped(base, glob)), rule, specifier: preset.specifier })),
20
+ );
23
21
 
24
- const scopeText = (includes: ReadonlyArray<string>): string => includes.map((glob) => `"${glob}"`).join(", ");
22
+ const undeclared = ({ includes, layer, line, rule }: Weakening): Finding =>
23
+ layer.preset === undefined
24
+ ? { file: layer.path, line, message: `Weakens "${rule}" for ${scopeText(includes)} without a declaration.`, subject: rule }
25
+ : {
26
+ file: layer.preset.file,
27
+ line: layer.preset.line,
28
+ message: `Extends "${layer.preset.specifier}", which weakens "${rule}" for ${scopeText(includes)} without a declaration.`,
29
+ subject: rule,
30
+ };
25
31
 
26
- const undeclared = (weakening: Weakening): Finding => ({
27
- file: weakening.file,
28
- line: weakening.line,
29
- message: `Weakens "${weakening.rule}" for ${scopeText(weakening.includes)} without a declaration.`,
30
- subject: weakening.rule,
32
+ const unused = (file: string, declaration: Scoped): Finding => ({
33
+ file,
34
+ message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which no Biome config weakens. Remove the declaration.`,
35
+ subject: declaration.rule,
31
36
  });
32
37
 
33
- const unused = (file: string, declaration: Declaration): Finding => ({
38
+ const repeated = (file: string, declaration: Scoped, shipped: Shipped): Finding => ({
34
39
  file,
35
- message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which no Biome config weakens. Remove the declaration.`,
40
+ message: `Declares "${declaration.rule}" for ${scopeText(declaration.includes)}, which "${shipped.specifier}" already declares. Remove the declaration.`,
36
41
  subject: declaration.rule,
37
42
  });
38
43
 
39
- const unreadable = (config: Config): ReadonlyArray<Finding> =>
40
- config._tag === "Unreadable" ? [{ file: config.path, message: `Cannot read this Biome config: ${config.reason}.` }] : [];
44
+ const staleOrRepeated = (file: string, weakenings: readonly Weakening[], shipped: readonly Shipped[]) => (declaration: Scoped) => {
45
+ if (!weakenings.some((weakening) => matches(declaration, weakening))) {
46
+ return [unused(file, declaration)];
47
+ }
48
+ const already = shipped.find((candidate) => matches(declaration, candidate));
49
+ return already === undefined ? [] : [repeated(file, declaration, already)];
50
+ };
41
51
 
42
52
  export const biomeOverrides = defineRule({
43
- id: "suppressions/biome-overrides",
44
- description:
45
- "A Biome setting that turns a check off or down, or keeps files out of it, is an exception for every file it covers. Fix the code and remove the setting, or declare its rule, includes and reason under this rule's declared option.",
46
- options: Schema.toStandardSchemaV1(BiomeOverridesOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
47
- registrable: false,
48
53
  check: async (inputs) => {
49
- const configs = await biomeConfigs(inputs);
54
+ const { chains, problems, root } = await biomeConfigs(inputs);
50
55
  const { declared } = inputs.options;
51
- const weakenings = configs.flatMap((config) => (config._tag === "Config" ? weakeningsOf(config.json, config.path, config.base) : []));
52
- const root = configs.find((config) => !config.path.includes("/"))?.path ?? "biome.json";
56
+ const weakenings = chains.flatMap(weakeningsOf);
57
+ const shipped = chains.flatMap(shippedBy);
58
+ const covered = (weakening: Weakening): boolean => [...declared, ...shipped].some((declaration) => matches(declaration, weakening));
53
59
  return [
54
- ...configs.flatMap(unreadable),
55
- ...weakenings.filter((weakening) => !declared.some((declaration) => matches(declaration, weakening))).map(undeclared),
56
- ...declared
57
- .filter((declaration) => !weakenings.some((weakening) => matches(declaration, weakening)))
58
- .map((declaration) => unused(root, declaration)),
60
+ ...problems,
61
+ ...weakenings.filter((weakening) => !covered(weakening)).map(undeclared),
62
+ ...declared.flatMap(staleOrRepeated(root, weakenings, shipped)),
59
63
  ];
60
64
  },
65
+ description:
66
+ "A Biome setting that turns a check off or down, or keeps files out of it, is an exception for every file it covers. Fix the code and remove the setting, or declare its rule, includes and reason under this rule's declared option.",
67
+ id: "suppressions/biome-overrides",
68
+ options: Schema.toStandardSchemaV1(BiomeOverridesOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
69
+ registrable: false,
61
70
  });
@@ -1,24 +1,24 @@
1
1
  import type { SourceComment } from "../comments/scan.ts";
2
2
 
3
- export const SUPPRESSIONS: ReadonlyArray<RegExp> = [
4
- /^biome-ignore(?:-all|-start)?(?![\w-])/,
5
- /^@ts-(?:ignore|expect-error|nocheck)(?![\w-])/,
6
- /^(?:eslint|oxlint|stylelint)-disable(?:-next-line|-line)?(?![\w-])/,
7
- /^deno-lint-ignore(?:-file)?(?![\w-])/,
8
- /^tslint:disable/,
9
- /^prettier-ignore(?![\w-])/,
10
- /^\$Flow(?:FixMe|Ignore|ExpectedError|Issue)(?!\w)/,
11
- /^@noflow(?!\w)/,
3
+ export const SUPPRESSIONS: readonly RegExp[] = [
4
+ /^biome-ignore(?:-all|-start)?(?![\w-])/u,
5
+ /^@ts-(?:ignore|expect-error|nocheck)(?![\w-])/u,
6
+ /^(?:eslint|oxlint|stylelint)-disable(?:-next-line|-line)?(?![\w-])/u,
7
+ /^deno-lint-ignore(?:-file)?(?![\w-])/u,
8
+ /^tslint:disable/u,
9
+ /^prettier-ignore(?![\w-])/u,
10
+ /^\$Flow(?:FixMe|Ignore|ExpectedError|Issue)(?!\w)/u,
11
+ /^@noflow(?!\w)/u,
12
12
  ];
13
13
 
14
- const INLINE_ESLINT_CONFIG = /^eslint\s+["']?[\w@/-]+["']?\s*:/;
14
+ const INLINE_ESLINT_CONFIG = /^eslint\s+["']?[\w@/-]+["']?\s*:/u;
15
15
 
16
- const LEADER = /^[\s/*]+/;
16
+ const LEADER = /^[\s/*]+/u;
17
17
 
18
18
  const directiveOn = (comment: SourceComment, line: string): string | undefined => {
19
19
  const content = line.replace(LEADER, "");
20
20
  const patterns = comment.kind === "block" ? [...SUPPRESSIONS, INLINE_ESLINT_CONFIG] : SUPPRESSIONS;
21
- return patterns.map((pattern) => pattern.exec(content)?.[0].replace(/\s*:$/, "")).find((match) => match !== undefined);
21
+ return patterns.map((pattern) => pattern.exec(content)?.[0].replace(/\s*:$/u, "")).find((match) => match !== undefined);
22
22
  };
23
23
 
24
24
  export const suppressionIn = (comment: SourceComment): string | undefined =>
@@ -19,7 +19,7 @@ const bridgeOf = (node: Assertion): string | undefined => {
19
19
  return isAssertion(inner) ? BRIDGES.get(inner.type.kind) : undefined;
20
20
  };
21
21
 
22
- const castsIn = (path: string, source: ts.SourceFile): ReadonlyArray<Finding> => {
22
+ const castsIn = (path: string, source: ts.SourceFile): readonly Finding[] => {
23
23
  const findings: Finding[] = [];
24
24
  const visit = (node: ts.Node): void => {
25
25
  const bridge = isAssertion(node) ? bridgeOf(node) : undefined;
@@ -33,15 +33,15 @@ const castsIn = (path: string, source: ts.SourceFile): ReadonlyArray<Finding> =>
33
33
  return findings;
34
34
  };
35
35
 
36
- const doubleCasts = (file: SourceFile): ReadonlyArray<Finding> => {
36
+ const doubleCasts = (file: SourceFile): readonly Finding[] => {
37
37
  const source = parse(file);
38
38
  return source === undefined ? [] : castsIn(file.path, source);
39
39
  };
40
40
 
41
41
  export const noDoubleCast = defineRule({
42
- id: "suppressions/no-double-cast",
42
+ check: ({ sources }) => sources.flatMap(doubleCasts),
43
43
  description:
44
44
  "A cast through unknown, any or never silences the compiler the way a suppression does. Decode the value at its boundary, narrow it, or fix the type that disagrees.",
45
+ id: "suppressions/no-double-cast",
45
46
  registrable: false,
46
- check: ({ sources }) => sources.flatMap(doubleCasts),
47
47
  });
@@ -1,63 +1,39 @@
1
- import { Effect, Schema } from "effect";
2
- import ignore from "ignore";
3
- import { CONFIG_FILE } from "../../config/file.ts";
4
1
  import { defineRule, type Finding, type RuleInputs } from "../../rule.ts";
5
2
  import { type SourceComment, scanComments } from "../comments/scan.ts";
6
3
  import { suppressionIn } from "./directives.ts";
7
4
  import { STYLESHEET, stylesheetComments } from "./stylesheet-comments.ts";
8
5
 
9
- const Declaration = Schema.Struct({
10
- directive: Schema.Literal("@ts-expect-error"),
11
- includes: Schema.NonEmptyArray(Schema.NonEmptyString),
12
- reason: Schema.String.check(Schema.isPattern(/\S/, { expected: "a reason that says why these files assert type errors" })),
13
- });
14
-
15
- type Declaration = typeof Declaration.Type;
6
+ const TYPE_TEST = /(?:^|[/.])typecheck\.test\.[cm]?[jt]sx?$/u;
16
7
 
17
- const NoInlineOptions = Schema.Struct({
18
- declared: Schema.Array(Declaration).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
19
- });
8
+ const TYPE_TEST_DIRECTIVE = "@ts-expect-error";
20
9
 
21
10
  interface Site extends Finding {
22
11
  readonly subject: string;
23
12
  }
24
13
 
25
- const sitesIn = (file: string, comments: ReadonlyArray<SourceComment>): ReadonlyArray<Site> =>
14
+ const sitesIn = (file: string, comments: readonly SourceComment[]): readonly Site[] =>
26
15
  comments.flatMap((comment) => {
27
16
  const directive = suppressionIn(comment);
28
17
  return directive === undefined ? [] : [{ file, line: comment.line, message: `Suppresses a check: "${directive}".`, subject: directive }];
29
18
  });
30
19
 
31
- const stylesheetSites = async ({ files, readText, sources }: RuleInputs): Promise<ReadonlyArray<Site>> => {
20
+ const stylesheetSites = async ({ files, readText, sources }: RuleInputs): Promise<readonly Site[]> => {
32
21
  const read = files.filter((path) => STYLESHEET.test(path));
33
22
  const texts = await Promise.all(read.map(async (path) => sources.find((source) => source.path === path)?.text ?? (await readText(path))));
34
23
  return read.flatMap((path, index) => sitesIn(path, stylesheetComments(path, texts[index] ?? "")));
35
24
  };
36
25
 
37
- const allows = (declaration: Declaration, site: Site): boolean =>
38
- declaration.directive === site.subject &&
39
- ignore()
40
- .add([...declaration.includes])
41
- .ignores(site.file);
42
-
43
- const unused = (declaration: Declaration): Finding => ({
44
- file: CONFIG_FILE,
45
- message: `Declares "${declaration.directive}" for ${declaration.includes.map((glob) => `"${glob}"`).join(", ")}, which matches no directive. Remove the declaration.`,
46
- subject: declaration.directive,
47
- });
26
+ function allowed(site: Site): boolean {
27
+ return site.subject === TYPE_TEST_DIRECTIVE && TYPE_TEST.test(site.file);
28
+ }
48
29
 
49
30
  export const noInline = defineRule({
50
- id: "suppressions/no-inline",
31
+ check: async (inputs) =>
32
+ [...inputs.sources.flatMap((file) => sitesIn(file.path, scanComments(file))), ...(await stylesheetSites(inputs))].filter(
33
+ (site) => !allowed(site),
34
+ ),
51
35
  description:
52
- "A suppression silences a check at one site instead of fixing the cause. Fix the code; where a lint rule truly cannot apply, turn it off for that scope in the Biome config and declare it under suppressions/biome-overrides.",
53
- options: Schema.toStandardSchemaV1(NoInlineOptions, { parseOptions: { errors: "all", onExcessProperty: "error" } }),
36
+ "A suppression silences a check at one site instead of fixing the cause. Fix the code; where a lint rule truly cannot apply, turn it off for that scope in the Biome config and declare it under suppressions/biome-overrides. A type test asserts a compile error with @ts-expect-error in a *.typecheck.test.ts file.",
37
+ id: "suppressions/no-inline",
54
38
  registrable: false,
55
- check: async (inputs) => {
56
- const { declared } = inputs.options;
57
- const sites = [...inputs.sources.flatMap((file) => sitesIn(file.path, scanComments(file))), ...(await stylesheetSites(inputs))];
58
- return [
59
- ...sites.filter((site) => !declared.some((declaration) => allows(declaration, site))),
60
- ...declared.filter((declaration) => !sites.some((site) => allows(declaration, site))).map(unused),
61
- ];
62
- },
63
39
  });
@@ -1,12 +1,12 @@
1
1
  import { bodyOf, type SourceComment } from "../comments/scan.ts";
2
2
 
3
- export const STYLESHEET = /\.(?:css|scss|less)$/;
3
+ export const STYLESHEET = /\.(?:css|scss|less)$/u;
4
4
 
5
- const LINE_COMMENTS = /\.(?:scss|less)$/;
5
+ const LINE_COMMENTS = /\.(?:scss|less)$/u;
6
6
 
7
7
  const TOKENS = String.raw`"(?:[^"\\\n]|\\.)*"?|'(?:[^'\\\n]|\\.)*'?|url\([^)]*\)?|\/\*[\s\S]*?(?:\*\/|$)`;
8
8
 
9
- const tokensOf = (path: string): RegExp => new RegExp(LINE_COMMENTS.test(path) ? `${TOKENS}|\\/\\/[^\\n]*` : TOKENS, "gi");
9
+ const tokensOf = (path: string): RegExp => new RegExp(LINE_COMMENTS.test(path) ? `${TOKENS}|\\/\\/[^\\n]*` : TOKENS, "giu");
10
10
 
11
11
  const lineOf = (text: string, offset: number): number => text.slice(0, offset).split("\n").length;
12
12
 
@@ -23,5 +23,5 @@ const toComment = (text: string, token: string, offset: number): SourceComment =
23
23
  };
24
24
  };
25
25
 
26
- export const stylesheetComments = (path: string, text: string): ReadonlyArray<SourceComment> =>
26
+ export const stylesheetComments = (path: string, text: string): readonly SourceComment[] =>
27
27
  [...text.matchAll(tokensOf(path))].flatMap((match) => (match[0].startsWith("/") ? [toComment(text, match[0], match.index)] : []));
@@ -2,10 +2,10 @@ import ts from "typescript";
2
2
  import type { SourceFile } from "../rule.ts";
3
3
 
4
4
  const SCRIPT_KINDS: ReadonlyArray<readonly [RegExp, ts.ScriptKind]> = [
5
- [/\.[cm]?ts$/, ts.ScriptKind.TS],
6
- [/\.tsx$/, ts.ScriptKind.TSX],
7
- [/\.[cm]?js$/, ts.ScriptKind.JS],
8
- [/\.jsx$/, ts.ScriptKind.JSX],
5
+ [/\.[cm]?ts$/u, ts.ScriptKind.TS],
6
+ [/\.tsx$/u, ts.ScriptKind.TSX],
7
+ [/\.[cm]?js$/u, ts.ScriptKind.JS],
8
+ [/\.jsx$/u, ts.ScriptKind.JSX],
9
9
  ];
10
10
 
11
11
  export const parse = (file: SourceFile): ts.SourceFile | undefined => {
@@ -9,7 +9,7 @@ export interface StandardSchemaV1<Input = unknown, Output = Input> {
9
9
  };
10
10
  }
11
11
 
12
- export type StandardResult<Output> = { readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<StandardIssue> };
12
+ export type StandardResult<Output> = { readonly value: Output; readonly issues?: undefined } | { readonly issues: readonly StandardIssue[] };
13
13
 
14
14
  export interface StandardIssue {
15
15
  readonly message: string;
package/src/vitest.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { defaultExclude, type TestUserConfig } from "vitest/config";
2
+
3
+ const TEST = "**/*.test.?(c|m)[jt]s?(x)";
4
+ const DOM = "**/*.dom.test.?(c|m)[jt]s?(x)";
5
+ const SLOW = "**/*.slow.test.?(c|m)[jt]s?(x)";
6
+ const TYPECHECK = "**/*.typecheck.test.?(c|m)[jt]s?(x)";
7
+ const TYPECHECK_ALONE = "**/typecheck.test.?(c|m)[jt]s?(x)";
8
+
9
+ function excluding(...patterns: readonly string[]): string[] {
10
+ return [...defaultExclude, TYPECHECK, TYPECHECK_ALONE, ...patterns];
11
+ }
12
+
13
+ export function testProjects(): TestUserConfig {
14
+ return {
15
+ project: ["unit", "dom"],
16
+ projects: [
17
+ { extends: true, test: { environment: "node", exclude: excluding(DOM, SLOW), include: [TEST], name: "unit" } },
18
+ { extends: true, test: { environment: "happy-dom", exclude: excluding(SLOW), include: [DOM], name: "dom" } },
19
+ { extends: true, test: { environment: "node", exclude: excluding(), include: [SLOW], name: "slow" } },
20
+ ],
21
+ };
22
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowImportingTsExtensions": true,
4
+ "allowJs": true,
5
+ "allowUnreachableCode": false,
6
+ "allowUnusedLabels": false,
7
+ "checkJs": true,
8
+ "erasableSyntaxOnly": true,
9
+ "exactOptionalPropertyTypes": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "isolatedModules": true,
12
+ "lib": ["ESNext"],
13
+ "libReplacement": false,
14
+ "module": "ESNext",
15
+ "moduleDetection": "force",
16
+ "moduleResolution": "bundler",
17
+ "noEmit": true,
18
+ "noFallthroughCasesInSwitch": true,
19
+ "noImplicitAny": true,
20
+ "noImplicitOverride": true,
21
+ "noImplicitReturns": true,
22
+ "noUncheckedIndexedAccess": true,
23
+ "noUncheckedSideEffectImports": true,
24
+ "noUnusedLocals": true,
25
+ "noUnusedParameters": true,
26
+ "resolveJsonModule": true,
27
+ "skipLibCheck": true,
28
+ "stableTypeOrdering": true,
29
+ "strict": true,
30
+ "strictBuiltinIteratorReturn": true,
31
+ "target": "ESNext",
32
+ "useUnknownInCatchVariables": true,
33
+ "verbatimModuleSyntax": true
34
+ }
35
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "noEmit": false,
4
+ "declaration": true,
5
+ "declarationMap": true,
6
+ "sourceMap": true,
7
+ "rewriteRelativeImportExtensions": true
8
+ },
9
+ "extends": "./base.json"
10
+ }