pickier 0.1.28 → 0.1.30

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 (263) hide show
  1. package/dist/ast.d.ts +13 -0
  2. package/dist/bin/cli.js +554 -436
  3. package/dist/plugins/eslint.d.ts +2 -0
  4. package/dist/plugins/general.d.ts +2 -0
  5. package/dist/plugins/index.d.ts +2 -0
  6. package/dist/plugins/lockfile.d.ts +22 -0
  7. package/dist/plugins/markdown.d.ts +2 -0
  8. package/dist/plugins/node.d.ts +2 -0
  9. package/dist/plugins/perfectionist.d.ts +6 -0
  10. package/dist/plugins/pickier.d.ts +2 -0
  11. package/dist/plugins/publint.d.ts +10 -0
  12. package/dist/plugins/quality.d.ts +2 -0
  13. package/dist/plugins/regexp.d.ts +2 -0
  14. package/dist/plugins/shell.d.ts +2 -0
  15. package/dist/plugins/spell.d.ts +3 -0
  16. package/dist/plugins/style.d.ts +2 -0
  17. package/dist/plugins/ts.d.ts +2 -0
  18. package/dist/plugins/unused-imports.d.ts +6 -0
  19. package/dist/plugins/utils.d.ts +4 -0
  20. package/dist/rules/general/_template-tracking.d.ts +31 -0
  21. package/dist/rules/general/array-callback-return.d.ts +2 -0
  22. package/dist/rules/general/constructor-super.d.ts +2 -0
  23. package/dist/rules/general/for-direction.d.ts +2 -0
  24. package/dist/rules/general/getter-return.d.ts +2 -0
  25. package/dist/rules/general/no-async-promise-executor.d.ts +2 -0
  26. package/dist/rules/general/no-compare-neg-zero.d.ts +2 -0
  27. package/dist/rules/general/no-cond-assign.d.ts +2 -0
  28. package/dist/rules/general/no-const-assign.d.ts +2 -0
  29. package/dist/rules/general/no-constant-condition.d.ts +2 -0
  30. package/dist/rules/general/no-constructor-return.d.ts +2 -0
  31. package/dist/rules/general/no-dupe-class-members.d.ts +2 -0
  32. package/dist/rules/general/no-dupe-keys.d.ts +2 -0
  33. package/dist/rules/general/no-duplicate-case.d.ts +2 -0
  34. package/dist/rules/general/no-empty-pattern.d.ts +2 -0
  35. package/dist/rules/general/no-fallthrough.d.ts +2 -0
  36. package/dist/rules/general/no-irregular-whitespace.d.ts +2 -0
  37. package/dist/rules/general/no-loss-of-precision.d.ts +2 -0
  38. package/dist/rules/general/no-new.d.ts +13 -0
  39. package/dist/rules/general/no-promise-executor-return.d.ts +2 -0
  40. package/dist/rules/general/no-redeclare.d.ts +2 -0
  41. package/dist/rules/general/no-regex-spaces.d.ts +10 -0
  42. package/dist/rules/general/no-self-assign.d.ts +2 -0
  43. package/dist/rules/general/no-self-compare.d.ts +2 -0
  44. package/dist/rules/general/no-sparse-arrays.d.ts +2 -0
  45. package/dist/rules/general/no-undef.d.ts +2 -0
  46. package/dist/rules/general/no-unreachable.d.ts +2 -0
  47. package/dist/rules/general/no-unsafe-negation.d.ts +2 -0
  48. package/dist/rules/general/no-unused-vars.d.ts +2 -0
  49. package/dist/rules/general/no-useless-catch.d.ts +2 -0
  50. package/dist/rules/general/prefer-const.d.ts +2 -0
  51. package/dist/rules/general/prefer-object-spread.d.ts +2 -0
  52. package/dist/rules/general/prefer-template.d.ts +2 -0
  53. package/dist/rules/general/use-isnan.d.ts +2 -0
  54. package/dist/rules/general/valid-typeof.d.ts +2 -0
  55. package/dist/rules/imports/first.d.ts +2 -0
  56. package/dist/rules/imports/import-dedupe.d.ts +2 -0
  57. package/dist/rules/imports/named.d.ts +2 -0
  58. package/dist/rules/imports/no-cycle.d.ts +2 -0
  59. package/dist/rules/imports/no-duplicate-imports.d.ts +2 -0
  60. package/dist/rules/imports/no-import-dist.d.ts +2 -0
  61. package/dist/rules/imports/no-import-node-modules-by-path.d.ts +2 -0
  62. package/dist/rules/imports/no-unresolved.d.ts +2 -0
  63. package/dist/rules/lockfile/parser.d.ts +79 -0
  64. package/dist/rules/lockfile/validate-host.d.ts +18 -0
  65. package/dist/rules/lockfile/validate-https.d.ts +14 -0
  66. package/dist/rules/lockfile/validate-integrity.d.ts +19 -0
  67. package/dist/rules/lockfile/validate-package-names.d.ts +23 -0
  68. package/dist/rules/lockfile/validate-scheme.d.ts +17 -0
  69. package/dist/rules/markdown/_fence-tracking.d.ts +32 -0
  70. package/dist/rules/markdown/_shared.d.ts +9 -0
  71. package/dist/rules/markdown/blanks-around-fences.d.ts +5 -0
  72. package/dist/rules/markdown/blanks-around-headings.d.ts +5 -0
  73. package/dist/rules/markdown/blanks-around-lists.d.ts +5 -0
  74. package/dist/rules/markdown/blanks-around-tables.d.ts +5 -0
  75. package/dist/rules/markdown/code-block-style.d.ts +5 -0
  76. package/dist/rules/markdown/code-fence-style.d.ts +5 -0
  77. package/dist/rules/markdown/commands-show-output.d.ts +5 -0
  78. package/dist/rules/markdown/descriptive-link-text.d.ts +5 -0
  79. package/dist/rules/markdown/emphasis-style.d.ts +5 -0
  80. package/dist/rules/markdown/fenced-code-language.d.ts +5 -0
  81. package/dist/rules/markdown/first-line-heading.d.ts +5 -0
  82. package/dist/rules/markdown/heading-increment.d.ts +5 -0
  83. package/dist/rules/markdown/heading-start-left.d.ts +5 -0
  84. package/dist/rules/markdown/heading-style.d.ts +5 -0
  85. package/dist/rules/markdown/hr-style.d.ts +5 -0
  86. package/dist/rules/markdown/line-length.d.ts +5 -0
  87. package/dist/rules/markdown/link-fragments.d.ts +5 -0
  88. package/dist/rules/markdown/link-image-reference-definitions.d.ts +5 -0
  89. package/dist/rules/markdown/link-image-style.d.ts +5 -0
  90. package/dist/rules/markdown/list-indent.d.ts +5 -0
  91. package/dist/rules/markdown/list-marker-space.d.ts +5 -0
  92. package/dist/rules/markdown/no-alt-text.d.ts +5 -0
  93. package/dist/rules/markdown/no-bare-urls.d.ts +5 -0
  94. package/dist/rules/markdown/no-blanks-blockquote.d.ts +5 -0
  95. package/dist/rules/markdown/no-duplicate-heading.d.ts +10 -0
  96. package/dist/rules/markdown/no-emphasis-as-heading.d.ts +9 -0
  97. package/dist/rules/markdown/no-empty-links.d.ts +5 -0
  98. package/dist/rules/markdown/no-hard-tabs.d.ts +5 -0
  99. package/dist/rules/markdown/no-inline-html.d.ts +5 -0
  100. package/dist/rules/markdown/no-missing-space-atx.d.ts +5 -0
  101. package/dist/rules/markdown/no-missing-space-closed-atx.d.ts +5 -0
  102. package/dist/rules/markdown/no-multiple-blanks.d.ts +5 -0
  103. package/dist/rules/markdown/no-multiple-space-atx.d.ts +5 -0
  104. package/dist/rules/markdown/no-multiple-space-blockquote.d.ts +5 -0
  105. package/dist/rules/markdown/no-multiple-space-closed-atx.d.ts +5 -0
  106. package/dist/rules/markdown/no-reversed-links.d.ts +5 -0
  107. package/dist/rules/markdown/no-space-in-code.d.ts +5 -0
  108. package/dist/rules/markdown/no-space-in-emphasis.d.ts +5 -0
  109. package/dist/rules/markdown/no-space-in-links.d.ts +5 -0
  110. package/dist/rules/markdown/no-trailing-punctuation.d.ts +5 -0
  111. package/dist/rules/markdown/no-trailing-spaces.d.ts +5 -0
  112. package/dist/rules/markdown/ol-prefix.d.ts +5 -0
  113. package/dist/rules/markdown/proper-names.d.ts +5 -0
  114. package/dist/rules/markdown/reference-links-images.d.ts +14 -0
  115. package/dist/rules/markdown/required-headings.d.ts +5 -0
  116. package/dist/rules/markdown/single-title.d.ts +5 -0
  117. package/dist/rules/markdown/single-trailing-newline.d.ts +5 -0
  118. package/dist/rules/markdown/strong-style.d.ts +5 -0
  119. package/dist/rules/markdown/table-column-count.d.ts +5 -0
  120. package/dist/rules/markdown/table-column-style.d.ts +5 -0
  121. package/dist/rules/markdown/table-pipe-style.d.ts +5 -0
  122. package/dist/rules/markdown/ul-indent.d.ts +14 -0
  123. package/dist/rules/markdown/ul-style.d.ts +5 -0
  124. package/dist/rules/node/prefer-global-buffer.d.ts +9 -0
  125. package/dist/rules/node/prefer-global-process.d.ts +9 -0
  126. package/dist/rules/quality/complexity.d.ts +2 -0
  127. package/dist/rules/quality/default-case.d.ts +2 -0
  128. package/dist/rules/quality/eqeqeq.d.ts +2 -0
  129. package/dist/rules/quality/max-depth.d.ts +2 -0
  130. package/dist/rules/quality/max-lines-per-function.d.ts +2 -0
  131. package/dist/rules/quality/no-alert.d.ts +2 -0
  132. package/dist/rules/quality/no-await-in-loop.d.ts +2 -0
  133. package/dist/rules/quality/no-caller.d.ts +2 -0
  134. package/dist/rules/quality/no-case-declarations.d.ts +2 -0
  135. package/dist/rules/quality/no-else-return.d.ts +2 -0
  136. package/dist/rules/quality/no-empty-function.d.ts +2 -0
  137. package/dist/rules/quality/no-empty.d.ts +2 -0
  138. package/dist/rules/quality/no-eval.d.ts +2 -0
  139. package/dist/rules/quality/no-extend-native.d.ts +2 -0
  140. package/dist/rules/quality/no-extra-boolean-cast.d.ts +2 -0
  141. package/dist/rules/quality/no-global-assign.d.ts +2 -0
  142. package/dist/rules/quality/no-implied-eval.d.ts +2 -0
  143. package/dist/rules/quality/no-iterator.d.ts +2 -0
  144. package/dist/rules/quality/no-lonely-if.d.ts +2 -0
  145. package/dist/rules/quality/no-new-func.d.ts +2 -0
  146. package/dist/rules/quality/no-new-wrappers.d.ts +2 -0
  147. package/dist/rules/quality/no-new.d.ts +2 -0
  148. package/dist/rules/quality/no-octal.d.ts +2 -0
  149. package/dist/rules/quality/no-param-reassign.d.ts +2 -0
  150. package/dist/rules/quality/no-proto.d.ts +2 -0
  151. package/dist/rules/quality/no-return-assign.d.ts +2 -0
  152. package/dist/rules/quality/no-sequences.d.ts +2 -0
  153. package/dist/rules/quality/no-shadow.d.ts +2 -0
  154. package/dist/rules/quality/no-throw-literal.d.ts +2 -0
  155. package/dist/rules/quality/no-use-before-define.d.ts +2 -0
  156. package/dist/rules/quality/no-useless-call.d.ts +2 -0
  157. package/dist/rules/quality/no-useless-concat.d.ts +2 -0
  158. package/dist/rules/quality/no-useless-escape.d.ts +2 -0
  159. package/dist/rules/quality/no-useless-rename.d.ts +2 -0
  160. package/dist/rules/quality/no-useless-return.d.ts +2 -0
  161. package/dist/rules/quality/no-var.d.ts +2 -0
  162. package/dist/rules/quality/no-with.d.ts +2 -0
  163. package/dist/rules/quality/prefer-arrow-callback.d.ts +2 -0
  164. package/dist/rules/quality/require-await.d.ts +2 -0
  165. package/dist/rules/regexp/no-super-linear-backtracking.d.ts +2 -0
  166. package/dist/rules/regexp/no-unused-capturing-group.d.ts +2 -0
  167. package/dist/rules/regexp/no-useless-lazy.d.ts +9 -0
  168. package/dist/rules/shell/_shared.d.ts +24 -0
  169. package/dist/rules/shell/command-substitution.d.ts +6 -0
  170. package/dist/rules/shell/consistent-case-terminators.d.ts +9 -0
  171. package/dist/rules/shell/function-style.d.ts +6 -0
  172. package/dist/rules/shell/heredoc-indent.d.ts +7 -0
  173. package/dist/rules/shell/indent.d.ts +2 -0
  174. package/dist/rules/shell/keyword-spacing.d.ts +10 -0
  175. package/dist/rules/shell/no-broken-redirect.d.ts +7 -0
  176. package/dist/rules/shell/no-cd-without-check.d.ts +6 -0
  177. package/dist/rules/shell/no-eval.d.ts +6 -0
  178. package/dist/rules/shell/no-exit-in-subshell.d.ts +7 -0
  179. package/dist/rules/shell/no-ls-parsing.d.ts +7 -0
  180. package/dist/rules/shell/no-trailing-semicolons.d.ts +6 -0
  181. package/dist/rules/shell/no-trailing-whitespace.d.ts +5 -0
  182. package/dist/rules/shell/no-useless-cat.d.ts +6 -0
  183. package/dist/rules/shell/no-variable-in-single-quotes.d.ts +7 -0
  184. package/dist/rules/shell/operator-spacing.d.ts +11 -0
  185. package/dist/rules/shell/prefer-double-brackets.d.ts +6 -0
  186. package/dist/rules/shell/prefer-printf.d.ts +6 -0
  187. package/dist/rules/shell/quote-variables.d.ts +2 -0
  188. package/dist/rules/shell/set-options.d.ts +8 -0
  189. package/dist/rules/shell/shebang.d.ts +2 -0
  190. package/dist/rules/sort/exports.d.ts +2 -0
  191. package/dist/rules/sort/heritage-clauses.d.ts +2 -0
  192. package/dist/rules/sort/imports.d.ts +2 -0
  193. package/dist/rules/sort/keys.d.ts +2 -0
  194. package/dist/rules/sort/named-imports.d.ts +2 -0
  195. package/dist/rules/sort/objects.d.ts +2 -0
  196. package/dist/rules/sort/tailwind-classes.d.ts +5 -0
  197. package/dist/rules/style/array-bracket-spacing.d.ts +2 -0
  198. package/dist/rules/style/arrow-parens.d.ts +2 -0
  199. package/dist/rules/style/arrow-spacing.d.ts +2 -0
  200. package/dist/rules/style/block-spacing.d.ts +2 -0
  201. package/dist/rules/style/brace-style.d.ts +10 -0
  202. package/dist/rules/style/comma-dangle.d.ts +2 -0
  203. package/dist/rules/style/comma-spacing.d.ts +2 -0
  204. package/dist/rules/style/comma-style.d.ts +2 -0
  205. package/dist/rules/style/computed-property-spacing.d.ts +2 -0
  206. package/dist/rules/style/consistent-chaining.d.ts +2 -0
  207. package/dist/rules/style/consistent-list-newline.d.ts +2 -0
  208. package/dist/rules/style/curly.d.ts +5 -0
  209. package/dist/rules/style/dot-location.d.ts +2 -0
  210. package/dist/rules/style/function-call-spacing.d.ts +2 -0
  211. package/dist/rules/style/generator-star-spacing.d.ts +2 -0
  212. package/dist/rules/style/if-newline.d.ts +2 -0
  213. package/dist/rules/style/indent-binary-ops.d.ts +2 -0
  214. package/dist/rules/style/indent-unindent.d.ts +2 -0
  215. package/dist/rules/style/key-spacing.d.ts +2 -0
  216. package/dist/rules/style/keyword-spacing.d.ts +2 -0
  217. package/dist/rules/style/lines-between-class-members.d.ts +2 -0
  218. package/dist/rules/style/max-statements-per-line.d.ts +2 -0
  219. package/dist/rules/style/multiline-ternary.d.ts +2 -0
  220. package/dist/rules/style/new-parens.d.ts +2 -0
  221. package/dist/rules/style/no-extra-parens.d.ts +2 -0
  222. package/dist/rules/style/no-floating-decimal.d.ts +2 -0
  223. package/dist/rules/style/no-mixed-operators.d.ts +2 -0
  224. package/dist/rules/style/no-mixed-spaces-and-tabs.d.ts +2 -0
  225. package/dist/rules/style/no-multi-spaces.d.ts +10 -0
  226. package/dist/rules/style/no-multiple-empty-lines.d.ts +9 -0
  227. package/dist/rules/style/no-tabs.d.ts +2 -0
  228. package/dist/rules/style/no-trailing-spaces.d.ts +9 -0
  229. package/dist/rules/style/no-whitespace-before-property.d.ts +2 -0
  230. package/dist/rules/style/object-curly-spacing.d.ts +2 -0
  231. package/dist/rules/style/operator-linebreak.d.ts +2 -0
  232. package/dist/rules/style/padded-blocks.d.ts +2 -0
  233. package/dist/rules/style/quote-props.d.ts +2 -0
  234. package/dist/rules/style/rest-spread-spacing.d.ts +2 -0
  235. package/dist/rules/style/semi-spacing.d.ts +2 -0
  236. package/dist/rules/style/space-before-blocks.d.ts +2 -0
  237. package/dist/rules/style/space-before-function-paren.d.ts +2 -0
  238. package/dist/rules/style/space-in-parens.d.ts +2 -0
  239. package/dist/rules/style/space-infix-ops.d.ts +2 -0
  240. package/dist/rules/style/space-unary-ops.d.ts +2 -0
  241. package/dist/rules/style/spaced-comment.d.ts +2 -0
  242. package/dist/rules/style/switch-colon-spacing.d.ts +2 -0
  243. package/dist/rules/style/template-curly-spacing.d.ts +2 -0
  244. package/dist/rules/style/template-tag-spacing.d.ts +2 -0
  245. package/dist/rules/style/top-level-function.d.ts +6 -0
  246. package/dist/rules/style/wrap-iife.d.ts +2 -0
  247. package/dist/rules/style/yield-star-spacing.d.ts +2 -0
  248. package/dist/rules/ts/member-delimiter-style.d.ts +4 -0
  249. package/dist/rules/ts/no-explicit-any.d.ts +2 -0
  250. package/dist/rules/ts/no-floating-promises.d.ts +2 -0
  251. package/dist/rules/ts/no-misused-promises.d.ts +2 -0
  252. package/dist/rules/ts/no-require-imports.d.ts +2 -0
  253. package/dist/rules/ts/no-top-level-await.d.ts +4 -0
  254. package/dist/rules/ts/no-ts-export-equal.d.ts +2 -0
  255. package/dist/rules/ts/no-unsafe-assignment.d.ts +2 -0
  256. package/dist/rules/ts/prefer-nullish-coalescing.d.ts +2 -0
  257. package/dist/rules/ts/prefer-optional-chain.d.ts +2 -0
  258. package/dist/rules/ts/type-annotation-spacing.d.ts +2 -0
  259. package/dist/rules/ts/type-generic-spacing.d.ts +2 -0
  260. package/dist/rules/ts/type-named-tuple-spacing.d.ts +2 -0
  261. package/dist/src/index.js +527 -423
  262. package/dist/utils.d.ts +12 -3
  263. package/package.json +3 -2
package/dist/bin/cli.js CHANGED
@@ -530,6 +530,16 @@ function unmaskStrings(text, strings) {
530
530
  return text;
531
531
  return text.replace(/@@S(\d+)@@/g, (_, idx) => strings[Number(idx)] ?? "");
532
532
  }
533
+ function collectIdentifierSet(text) {
534
+ const identifiers = new Set;
535
+ const identifierRe = /[$A-Z_][\w$]*/gi;
536
+ let match = identifierRe.exec(text);
537
+ while (match !== null) {
538
+ identifiers.add(match[0]);
539
+ match = identifierRe.exec(text);
540
+ }
541
+ return identifiers;
542
+ }
533
543
  function formatImports(source) {
534
544
  const firstChar = source[0];
535
545
  if (firstChar !== "i" && firstChar !== " " && firstChar !== "\t" && firstChar !== "/" && firstChar !== `
@@ -557,17 +567,8 @@ function formatImports(source) {
557
567
  return source;
558
568
  const rest = lines.slice(idx).join(`
559
569
  `);
560
- const codeText = rest;
561
- const isWordChar = (c) => c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c >= "0" && c <= "9" || c === "_" || c === "$";
562
- const used = (name) => {
563
- for (let pos = codeText.indexOf(name, 0);pos !== -1; pos = codeText.indexOf(name, pos + name.length)) {
564
- const before = pos > 0 ? codeText[pos - 1] : " ";
565
- const after = pos + name.length < codeText.length ? codeText[pos + name.length] : " ";
566
- if (!isWordChar(before) && !isWordChar(after))
567
- return true;
568
- }
569
- return false;
570
- };
570
+ const usedIdentifiers = collectIdentifierSet(rest);
571
+ const used = (name) => usedIdentifiers.has(name);
571
572
  for (const imp of imports) {
572
573
  if (imp.kind !== "value")
573
574
  continue;
@@ -9909,15 +9910,7 @@ function globToRegex(pattern) {
9909
9910
  }
9910
9911
  return new RegExp(`^${src}$`);
9911
9912
  }
9912
- function matchesAnyPattern(filePath, patterns) {
9913
- for (const p of patterns) {
9914
- const re = globToRegex(p);
9915
- if (re.test(filePath) || re.test(filePath.replace(/\\/g, "/")))
9916
- return true;
9917
- }
9918
- return false;
9919
- }
9920
- function* walkDir(dir, ignore, dot, cwd) {
9913
+ function* walkDirWithMatcher(dir, ignoreMatcher, dot) {
9921
9914
  let entries;
9922
9915
  try {
9923
9916
  entries = readdirSync6(dir);
@@ -9928,8 +9921,7 @@ function* walkDir(dir, ignore, dot, cwd) {
9928
9921
  if (!dot && name.startsWith("."))
9929
9922
  continue;
9930
9923
  const full = join7(dir, name);
9931
- const rel = full.startsWith(`${cwd}/`) ? full.slice(cwd.length + 1) : full;
9932
- if (ignore.length && matchesAnyPattern(rel, ignore))
9924
+ if (ignoreMatcher(full))
9933
9925
  continue;
9934
9926
  let st;
9935
9927
  try {
@@ -9938,17 +9930,21 @@ function* walkDir(dir, ignore, dot, cwd) {
9938
9930
  continue;
9939
9931
  }
9940
9932
  if (st.isDirectory()) {
9941
- yield* walkDir(full, ignore, dot, cwd);
9933
+ yield* walkDirWithMatcher(full, ignoreMatcher, dot);
9942
9934
  } else {
9943
9935
  yield full;
9944
9936
  }
9945
9937
  }
9946
9938
  }
9939
+ function* walkDir(dir, ignore, dot, cwd) {
9940
+ yield* walkDirWithMatcher(dir, createIgnoreMatcher(ignore, cwd), dot);
9941
+ }
9947
9942
  async function glob(patterns, opts = {}) {
9948
9943
  const cwd = opts.cwd ?? process19.cwd();
9949
9944
  const ignore = opts.ignore ?? [];
9950
9945
  const dot = opts.dot ?? false;
9951
9946
  const absolute = opts.absolute ?? true;
9947
+ const ignoreMatcher = createIgnoreMatcher(ignore, cwd);
9952
9948
  if (typeof globalThis.Bun?.Glob !== "undefined") {
9953
9949
  const BunGlob = globalThis.Bun.Glob;
9954
9950
  const results2 = [];
@@ -9957,7 +9953,7 @@ async function glob(patterns, opts = {}) {
9957
9953
  for await (const file of g.scan({ cwd, dot, onlyFiles: opts.onlyFiles ?? true, followSymlinks: false })) {
9958
9954
  const full = isAbsolute3(file) ? file : join7(cwd, file);
9959
9955
  const rel = full.startsWith(`${cwd}/`) ? full.slice(cwd.length + 1) : full;
9960
- if (ignore.length && matchesAnyPattern(rel, ignore))
9956
+ if (ignoreMatcher(full))
9961
9957
  continue;
9962
9958
  results2.push(absolute ? full : rel);
9963
9959
  }
@@ -9972,7 +9968,7 @@ async function glob(patterns, opts = {}) {
9972
9968
  const st = statSync3(full);
9973
9969
  if (!st.isDirectory()) {
9974
9970
  const rel = full.startsWith(`${cwd}/`) ? full.slice(cwd.length + 1) : full;
9975
- if (!ignore.length || !matchesAnyPattern(rel, ignore))
9971
+ if (!ignoreMatcher(full))
9976
9972
  results.push(absolute ? full : rel);
9977
9973
  } else {
9978
9974
  for (const f of walkDir(full, ignore, dot, cwd))
@@ -10147,36 +10143,60 @@ function isCodeFile(file, allowedExts) {
10147
10143
  function toPosixPath(p) {
10148
10144
  return p.replace(/\\/g, "/").replace(/\/+/g, "/");
10149
10145
  }
10150
- function shouldIgnorePath(absPath, ignoreGlobs) {
10151
- const isOutsideProject = !absPath.startsWith(process19.cwd());
10152
- const universalIgnores = ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**"];
10153
- const effectiveIgnores = isOutsideProject ? ignoreGlobs.filter((pattern) => universalIgnores.includes(pattern)) : ignoreGlobs;
10154
- const rel = toPosixPath(isOutsideProject ? absPath : absPath.slice(process19.cwd().length));
10155
- for (const g of effectiveIgnores) {
10146
+ function compileIgnoreGlobs(ignoreGlobs) {
10147
+ const compiled = [];
10148
+ for (const g of ignoreGlobs) {
10156
10149
  const gg = toPosixPath(g.trim());
10150
+ if (!gg)
10151
+ continue;
10157
10152
  const filePattern = gg.match(/\*\*\/\*\.(.+)$/);
10158
10153
  if (filePattern) {
10159
- const extension = filePattern[1];
10160
- if (rel.endsWith(`.${extension}`))
10161
- return true;
10154
+ compiled.push({ raw: gg, kind: "extension", value: filePattern[1] });
10162
10155
  continue;
10163
10156
  }
10164
10157
  const m = gg.match(/\*\*\/(.+?)\/\*\*$/);
10165
10158
  if (m) {
10166
- const name = m[1];
10167
- if (rel.includes(`/${name}/`) || rel.endsWith(`/${name}`))
10168
- return true;
10159
+ compiled.push({ raw: gg, kind: "segment", value: m[1] });
10169
10160
  continue;
10170
10161
  }
10171
10162
  const m2 = gg.match(/\*\*\/(.+)$/);
10172
10163
  if (m2) {
10173
- const name = m2[1].replace(/\/$/, "");
10174
- if (rel.includes(`/${name}/`) || rel.endsWith(`/${name}`))
10175
- return true;
10176
- continue;
10164
+ compiled.push({ raw: gg, kind: "suffix", value: m2[1].replace(/\/$/, "") });
10165
+ }
10166
+ }
10167
+ return compiled;
10168
+ }
10169
+ function createIgnoreMatcher(ignoreGlobs, cwd = process19.cwd()) {
10170
+ if (ignoreGlobs.length === 0)
10171
+ return () => false;
10172
+ const compiled = compileIgnoreGlobs(ignoreGlobs);
10173
+ if (compiled.length === 0)
10174
+ return () => false;
10175
+ const universalRaw = new Set(UNIVERSAL_IGNORES);
10176
+ return (absPath) => {
10177
+ const normalizedAbs = toPosixPath(absPath);
10178
+ const normalizedCwd = toPosixPath(cwd).replace(/\/$/, "");
10179
+ const isOutsideProject = !normalizedAbs.startsWith(normalizedCwd);
10180
+ const rel = isOutsideProject ? normalizedAbs : normalizedAbs.slice(normalizedCwd.length);
10181
+ for (const pattern of compiled) {
10182
+ if (isOutsideProject && !universalRaw.has(pattern.raw))
10183
+ continue;
10184
+ if (pattern.kind === "extension") {
10185
+ if (rel.endsWith(`.${pattern.value}`))
10186
+ return true;
10187
+ continue;
10188
+ }
10189
+ if (pattern.kind === "segment" || pattern.kind === "suffix") {
10190
+ const name = pattern.value;
10191
+ if (rel.includes(`/${name}/`) || rel.endsWith(`/${name}`))
10192
+ return true;
10193
+ }
10177
10194
  }
10178
- }
10179
- return false;
10195
+ return false;
10196
+ };
10197
+ }
10198
+ function shouldIgnorePath(absPath, ignoreGlobs) {
10199
+ return createIgnoreMatcher(ignoreGlobs)(absPath);
10180
10200
  }
10181
10201
  var MAX_FIXER_PASSES = 5, ENV, UNIVERSAL_IGNORES, colors, _cachedDefaultConfig = null;
10182
10202
  var init_utils = __esm(() => {
@@ -20705,11 +20725,11 @@ var init_no_unused_vars = __esm(() => {
20705
20725
  }
20706
20726
  };
20707
20727
  computeTemplateLines();
20728
+ const declRe = new RegExp("^\\s*(?:const|let|var)\\s+(.+?)" + ";" + "?\\s*$");
20708
20729
  for (let i = 0;i < lines.length; i++) {
20709
20730
  if (lineStartsInTemplate[i])
20710
20731
  continue;
20711
20732
  const line = lines[i];
20712
- const declRe = new RegExp("^\\s*(?:const|let|var)\\s+(.+?)" + ";" + "?\\s*$");
20713
20733
  const decl = line.match(declRe);
20714
20734
  if (!decl)
20715
20735
  continue;
@@ -21268,6 +21288,50 @@ var init_no_unused_vars = __esm(() => {
21268
21288
  }
21269
21289
  return null;
21270
21290
  };
21291
+ const collectArrowExpressionBody = (startLine, arrowCol) => {
21292
+ const state = {
21293
+ parenDepth: 0,
21294
+ braceDepth: 0,
21295
+ bracketDepth: 0,
21296
+ inTemplate: false
21297
+ };
21298
+ const updateState = (text2) => {
21299
+ for (let k = 0;k < text2.length; k++) {
21300
+ const ch = text2[k];
21301
+ if (ch === "`")
21302
+ state.inTemplate = !state.inTemplate;
21303
+ else if (ch === "(")
21304
+ state.parenDepth++;
21305
+ else if (ch === ")")
21306
+ state.parenDepth--;
21307
+ else if (ch === "{")
21308
+ state.braceDepth++;
21309
+ else if (ch === "}")
21310
+ state.braceDepth--;
21311
+ else if (ch === "[")
21312
+ state.bracketDepth++;
21313
+ else if (ch === "]")
21314
+ state.bracketDepth--;
21315
+ }
21316
+ };
21317
+ const isOpen = () => state.parenDepth > 0 || state.braceDepth > 0 || state.bracketDepth > 0 || state.inTemplate;
21318
+ const endsWithContinuation = (text2) => /(?:\?|:|\.|,|&&|\|\||\?\?|\+|-|\*|\/|%|\*\*)$/.test(text2.trimEnd());
21319
+ const startsWithContinuation = (text2) => /^(?:\?|:|\.|,|&&|\|\||\?\?|\+|-|\*|\/|%|\*\*)/.test(text2.trimStart());
21320
+ let bodyText = lines[startLine].slice(arrowCol + 2);
21321
+ updateState(bodyText);
21322
+ let nextLine = startLine + 1;
21323
+ while (nextLine < lines.length) {
21324
+ const previousLine = nextLine === startLine + 1 ? bodyText : lines[nextLine - 1];
21325
+ const shouldContinue = !bodyText.trim() || isOpen() || endsWithContinuation(previousLine) || startsWithContinuation(lines[nextLine]);
21326
+ if (!shouldContinue)
21327
+ break;
21328
+ bodyText += `
21329
+ ${lines[nextLine]}`;
21330
+ updateState(lines[nextLine]);
21331
+ nextLine++;
21332
+ }
21333
+ return bodyText;
21334
+ };
21271
21335
  const mainTmplStack = [];
21272
21336
  let mainInSingle = false;
21273
21337
  let mainInDouble = false;
@@ -21631,73 +21695,7 @@ ${lines.slice(bodyRange.from + 1, bodyRange.to + 1).join(`
21631
21695
  }
21632
21696
  }
21633
21697
  } else {
21634
- bodyText = line.slice(arrowIdx + 2);
21635
- let parenDepth = 0;
21636
- let braceDepth = 0;
21637
- let bracketDepth = 0;
21638
- let inTemplate = false;
21639
- for (let k = arrowIdx + 2;k < line.length; k++) {
21640
- const ch = line[k];
21641
- if (ch === "`")
21642
- inTemplate = !inTemplate;
21643
- else if (ch === "(")
21644
- parenDepth++;
21645
- else if (ch === ")")
21646
- parenDepth--;
21647
- else if (ch === "{")
21648
- braceDepth++;
21649
- else if (ch === "}")
21650
- braceDepth--;
21651
- else if (ch === "[")
21652
- bracketDepth++;
21653
- else if (ch === "]")
21654
- bracketDepth--;
21655
- }
21656
- let nextLine = i + 1;
21657
- if ((!bodyText.trim() || inTemplate) && nextLine < lines.length) {
21658
- bodyText += `
21659
- ${lines[nextLine]}`;
21660
- for (let k = 0;k < lines[nextLine].length; k++) {
21661
- const ch = lines[nextLine][k];
21662
- if (ch === "`")
21663
- inTemplate = !inTemplate;
21664
- else if (ch === "(")
21665
- parenDepth++;
21666
- else if (ch === ")")
21667
- parenDepth--;
21668
- else if (ch === "{")
21669
- braceDepth++;
21670
- else if (ch === "}")
21671
- braceDepth--;
21672
- else if (ch === "[")
21673
- bracketDepth++;
21674
- else if (ch === "]")
21675
- bracketDepth--;
21676
- }
21677
- nextLine++;
21678
- }
21679
- while (nextLine < lines.length && (parenDepth > 0 || braceDepth > 0 || bracketDepth > 0 || inTemplate)) {
21680
- bodyText += `
21681
- ${lines[nextLine]}`;
21682
- for (let k = 0;k < lines[nextLine].length; k++) {
21683
- const ch = lines[nextLine][k];
21684
- if (ch === "`")
21685
- inTemplate = !inTemplate;
21686
- else if (ch === "(")
21687
- parenDepth++;
21688
- else if (ch === ")")
21689
- parenDepth--;
21690
- else if (ch === "{")
21691
- braceDepth++;
21692
- else if (ch === "}")
21693
- braceDepth--;
21694
- else if (ch === "[")
21695
- bracketDepth++;
21696
- else if (ch === "]")
21697
- bracketDepth--;
21698
- }
21699
- nextLine++;
21700
- }
21698
+ bodyText = collectArrowExpressionBody(i, arrowIdx);
21701
21699
  }
21702
21700
  for (const name of params) {
21703
21701
  if (!name || argIgnoreRe.test(name) || name === "undefined")
@@ -21754,73 +21752,7 @@ ${lines.slice(bodyRange.from + 1, bodyRange.to + 1).join(`
21754
21752
  }
21755
21753
  }
21756
21754
  } else {
21757
- bodyText = line.slice(arrowIdx2 + 2);
21758
- let parenDepth = 0;
21759
- let braceDepth = 0;
21760
- let bracketDepth = 0;
21761
- let inTemplate = false;
21762
- for (let k = arrowIdx2 + 2;k < line.length; k++) {
21763
- const ch = line[k];
21764
- if (ch === "`")
21765
- inTemplate = !inTemplate;
21766
- else if (ch === "(")
21767
- parenDepth++;
21768
- else if (ch === ")")
21769
- parenDepth--;
21770
- else if (ch === "{")
21771
- braceDepth++;
21772
- else if (ch === "}")
21773
- braceDepth--;
21774
- else if (ch === "[")
21775
- bracketDepth++;
21776
- else if (ch === "]")
21777
- bracketDepth--;
21778
- }
21779
- let nextLine = i + 1;
21780
- if ((!bodyText.trim() || inTemplate) && nextLine < lines.length) {
21781
- bodyText += `
21782
- ${lines[nextLine]}`;
21783
- for (let k = 0;k < lines[nextLine].length; k++) {
21784
- const ch = lines[nextLine][k];
21785
- if (ch === "`")
21786
- inTemplate = !inTemplate;
21787
- else if (ch === "(")
21788
- parenDepth++;
21789
- else if (ch === ")")
21790
- parenDepth--;
21791
- else if (ch === "{")
21792
- braceDepth++;
21793
- else if (ch === "}")
21794
- braceDepth--;
21795
- else if (ch === "[")
21796
- bracketDepth++;
21797
- else if (ch === "]")
21798
- bracketDepth--;
21799
- }
21800
- nextLine++;
21801
- }
21802
- while (nextLine < lines.length && (parenDepth > 0 || braceDepth > 0 || bracketDepth > 0 || inTemplate)) {
21803
- bodyText += `
21804
- ${lines[nextLine]}`;
21805
- for (let k = 0;k < lines[nextLine].length; k++) {
21806
- const ch = lines[nextLine][k];
21807
- if (ch === "`")
21808
- inTemplate = !inTemplate;
21809
- else if (ch === "(")
21810
- parenDepth++;
21811
- else if (ch === ")")
21812
- parenDepth--;
21813
- else if (ch === "{")
21814
- braceDepth++;
21815
- else if (ch === "}")
21816
- braceDepth--;
21817
- else if (ch === "[")
21818
- bracketDepth++;
21819
- else if (ch === "]")
21820
- bracketDepth--;
21821
- }
21822
- nextLine++;
21823
- }
21755
+ bodyText = collectArrowExpressionBody(i, arrowIdx2);
21824
21756
  }
21825
21757
  const useRe = new RegExp(`\\b${name}\\b`, "g");
21826
21758
  if (!useRe.test(bodyText)) {
@@ -22139,6 +22071,90 @@ function findTopLevelEquals(s) {
22139
22071
  }
22140
22072
  return -1;
22141
22073
  }
22074
+ function destructuringReassignsName(text, name) {
22075
+ const re = new RegExp(`\\b${name}\\b`);
22076
+ let i = 0;
22077
+ let inStr = null;
22078
+ let escaped = false;
22079
+ while (i < text.length) {
22080
+ const c = text[i];
22081
+ if (escaped) {
22082
+ escaped = false;
22083
+ i++;
22084
+ continue;
22085
+ }
22086
+ if (c === "\\" && inStr) {
22087
+ escaped = true;
22088
+ i++;
22089
+ continue;
22090
+ }
22091
+ if (inStr) {
22092
+ if (inStr === "single" && c === "'" || inStr === "double" && c === '"' || inStr === "template" && c === "`")
22093
+ inStr = null;
22094
+ i++;
22095
+ continue;
22096
+ }
22097
+ if (c === "'") {
22098
+ inStr = "single";
22099
+ i++;
22100
+ continue;
22101
+ }
22102
+ if (c === '"') {
22103
+ inStr = "double";
22104
+ i++;
22105
+ continue;
22106
+ }
22107
+ if (c === "`") {
22108
+ inStr = "template";
22109
+ i++;
22110
+ continue;
22111
+ }
22112
+ if (c === "[" || c === "{") {
22113
+ const open = c;
22114
+ const close = c === "[" ? "]" : "}";
22115
+ let depth = 1;
22116
+ let j = i + 1;
22117
+ while (j < text.length && depth > 0) {
22118
+ const cj = text[j];
22119
+ if (cj === "\\") {
22120
+ j += 2;
22121
+ continue;
22122
+ }
22123
+ if (cj === open)
22124
+ depth++;
22125
+ else if (cj === close)
22126
+ depth--;
22127
+ if (depth === 0)
22128
+ break;
22129
+ j++;
22130
+ }
22131
+ if (depth === 0 && j < text.length) {
22132
+ let k = j + 1;
22133
+ while (k < text.length && (text[k] === " " || text[k] === "\t" || text[k] === "\r" || text[k] === `
22134
+ `))
22135
+ k++;
22136
+ if (text[k] === "=" && text[k + 1] !== "=" && text[k + 1] !== ">") {
22137
+ const inside = text.slice(i + 1, j);
22138
+ if (re.test(inside)) {
22139
+ const keyOnly = new RegExp(`\\b${name}\\b\\s*:`);
22140
+ const valueAfterColon = new RegExp(`:\\s*\\b${name}\\b`);
22141
+ if (open === "{") {
22142
+ const isKeyOnly = keyOnly.test(inside) && !valueAfterColon.test(inside) && !new RegExp(`(?:^|[\\s,{])\\s*${name}\\s*(?:,|\\s*=|\\s*})`).test(inside);
22143
+ if (!isKeyOnly)
22144
+ return true;
22145
+ } else {
22146
+ return true;
22147
+ }
22148
+ }
22149
+ }
22150
+ }
22151
+ i = j + 1;
22152
+ continue;
22153
+ }
22154
+ i++;
22155
+ }
22156
+ return false;
22157
+ }
22142
22158
  function analyzeLetDecl(line, text) {
22143
22159
  const declRe = new RegExp("^\\s*(?:let|var)\\s+(.+?)" + ";" + "?\\s*$");
22144
22160
  const decl = line.match(declRe);
@@ -22176,7 +22192,8 @@ function analyzeLetDecl(line, text) {
22176
22192
  const assignPattern = `\\b${name}\\s*(?:${assignOps.map((op) => op.replace(/[|\\^$*+?.(){}[\]]/g, (r) => `\\${r}`)).join("|")})`;
22177
22193
  const directAssign = new RegExp(assignPattern).test(rest);
22178
22194
  const incDecChanged = new RegExp(`(?:^|[^$w])(?:\\+\\+|--)\\s*${name}\\b|\\b${name}\\s*(?:\\+\\+|--)`).test(rest);
22179
- result.push({ name, fixable: !directAssign && !incDecChanged });
22195
+ const destructReassigned = destructuringReassignsName(rest, name);
22196
+ result.push({ name, fixable: !directAssign && !incDecChanged && !destructReassigned });
22180
22197
  }
22181
22198
  return result;
22182
22199
  }
@@ -22205,8 +22222,20 @@ var init_prefer_const = __esm(() => {
22205
22222
  },
22206
22223
  fix: (text) => {
22207
22224
  const lines = text.split(/\r?\n/);
22225
+ const disabledLines = new Set;
22226
+ const disableNextRe = /(?:eslint|pickier)-disable-next-line\b([^*\n]*)/;
22227
+ for (let i = 0;i < lines.length; i++) {
22228
+ const m = lines[i].match(disableNextRe);
22229
+ if (!m)
22230
+ continue;
22231
+ const ruleList = m[1].trim();
22232
+ if (ruleList === "" || /\bprefer-const\b/.test(ruleList))
22233
+ disabledLines.add(i + 2);
22234
+ }
22208
22235
  let changed = false;
22209
22236
  for (let i = 0;i < lines.length; i++) {
22237
+ if (disabledLines.has(i + 1))
22238
+ continue;
22210
22239
  const line = lines[i];
22211
22240
  if (!/^\s*let\b/.test(line))
22212
22241
  continue;
@@ -28856,14 +28885,27 @@ function getVariantPriority(cls) {
28856
28885
  }
28857
28886
  return priority;
28858
28887
  }
28888
+ function getClassSortKey(cls) {
28889
+ const cached = sortKeyCache.get(cls);
28890
+ if (cached)
28891
+ return cached;
28892
+ const key = {
28893
+ group: getGroupIndex(cls),
28894
+ variant: getVariantPriority(cls)
28895
+ };
28896
+ sortKeyCache.set(cls, key);
28897
+ return key;
28898
+ }
28859
28899
  function sortClasses(classes) {
28860
28900
  return [...classes].sort((a, b) => {
28861
- const ga = getGroupIndex(a);
28862
- const gb = getGroupIndex(b);
28901
+ const aKey = getClassSortKey(a);
28902
+ const bKey = getClassSortKey(b);
28903
+ const ga = aKey.group;
28904
+ const gb = bKey.group;
28863
28905
  if (ga !== gb)
28864
28906
  return ga - gb;
28865
- const va = getVariantPriority(a);
28866
- const vb = getVariantPriority(b);
28907
+ const va = aKey.variant;
28908
+ const vb = bKey.variant;
28867
28909
  if (va !== vb)
28868
28910
  return va - vb;
28869
28911
  return a.localeCompare(b);
@@ -28882,6 +28924,8 @@ function looksLikeJsExpression(value) {
28882
28924
  }
28883
28925
  function extractClassValues(content) {
28884
28926
  const matches = [];
28927
+ if (!content.includes("class") && !content.includes("clsx") && !content.includes("cn(") && !content.includes("tw(") && !content.includes("cva(") && !content.includes("tv("))
28928
+ return matches;
28885
28929
  for (const re of [ATTR_RE, ATTR_TMPL_RE, UTIL_FN_RE]) {
28886
28930
  re.lastIndex = 0;
28887
28931
  let m;
@@ -28928,7 +28972,7 @@ function isSorted(classes) {
28928
28972
  const sorted = sortClasses(classes);
28929
28973
  return classes.every((c, i) => c === sorted[i]);
28930
28974
  }
28931
- var GROUP_ORDER, VARIANT_RE, ATTR_RE, ATTR_TMPL_RE, UTIL_FN_RE, sortTailwindClassesRule;
28975
+ var GROUP_ORDER, VARIANT_RE, sortKeyCache, ATTR_RE, ATTR_TMPL_RE, UTIL_FN_RE, sortTailwindClassesRule;
28932
28976
  var init_tailwind_classes = __esm(() => {
28933
28977
  GROUP_ORDER = [
28934
28978
  [/^(block|inline|inline-block|flex|inline-flex|grid|inline-grid|flow-root|contents|hidden|table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row-group|table-row|list-item|subgrid)$/, 0],
@@ -28952,6 +28996,7 @@ var init_tailwind_classes = __esm(() => {
28952
28996
  [/^(sr-only|not-sr-only)$/, 15]
28953
28997
  ];
28954
28998
  VARIANT_RE = /^([a-z0-9][-a-z0-9]{0,50}:)+(?!\[)/;
28999
+ sortKeyCache = new Map;
28955
29000
  ATTR_RE = /\b(?:class|className|:class)\s*=\s*(?:"([^"]*?)"|'([^']*?)')/g;
28956
29001
  ATTR_TMPL_RE = /\b(?:class|className|:class)\s*=\s*\{`([^`]*?)`\}/g;
28957
29002
  UTIL_FN_RE = /\b(?:clsx|cn|tw|cva|tv)\s*\(\s*(?:"([^"]*?)"|'([^']*?)')/g;
@@ -37647,6 +37692,7 @@ async function runFormat(globs, options) {
37647
37692
  return !absBase.startsWith(process23.cwd());
37648
37693
  });
37649
37694
  const globIgnores = isGlobbingOutsideProject ? [...UNIVERSAL_IGNORES] : cfg.ignores;
37695
+ const ignoreMatcher = createIgnoreMatcher(globIgnores);
37650
37696
  let entries = [];
37651
37697
  const simpleDirPattern = patterns.length === 1 && /\*\*\/\*$/.test(patterns[0]);
37652
37698
  if (simpleDirPattern) {
@@ -37661,7 +37707,7 @@ async function runFormat(globs, options) {
37661
37707
  for (const it of items) {
37662
37708
  const full = join8(dir, it);
37663
37709
  const st = statSync4(full);
37664
- if (shouldIgnorePath(full, globIgnores))
37710
+ if (ignoreMatcher(full))
37665
37711
  continue;
37666
37712
  if (st.isDirectory())
37667
37713
  stack.push(full);
@@ -37687,7 +37733,7 @@ async function runFormat(globs, options) {
37687
37733
  }
37688
37734
  trace("globbed entries", entries.length);
37689
37735
  const files = entries.filter((f) => {
37690
- if (shouldIgnorePath(f, globIgnores))
37736
+ if (ignoreMatcher(f))
37691
37737
  return false;
37692
37738
  const idx = f.lastIndexOf(".");
37693
37739
  if (idx < 0)
@@ -37759,24 +37805,21 @@ function trace2(...args) {
37759
37805
  getLogger2().error("[pickier:trace]", args);
37760
37806
  }
37761
37807
  async function lintText(text, cfg, filePath = "untitled", signal) {
37762
- if (signal?.aborted) {
37808
+ if (signal?.aborted)
37763
37809
  throw new Error("AbortError");
37764
- }
37765
- const cfg2 = cfg;
37766
- cfg2._internalSkipPluginRulesInScan = true;
37767
- const issues = scanContent(filePath, text, cfg);
37810
+ const suppress = parseDisableDirectives(text);
37811
+ const commentLines = getCommentLines(text);
37812
+ const issues = scanContentOptimized(filePath, text, cfg, suppress, commentLines);
37768
37813
  if (signal?.aborted)
37769
37814
  throw new Error("AbortError");
37770
37815
  try {
37771
37816
  const pluginIssues = await applyPlugins(filePath, text, cfg);
37772
- const suppress = parseDisableDirectives(text);
37773
- const commentLines = getCommentLines(text);
37774
37817
  for (const i of pluginIssues) {
37775
37818
  if (signal?.aborted)
37776
37819
  throw new Error("AbortError");
37777
37820
  if (isSuppressed(i.ruleId, i.line, suppress))
37778
37821
  continue;
37779
- if (commentLines.has(i.line))
37822
+ if (commentLines.has(i.line) && shouldSkipCommentOnlyPluginIssue(i.ruleId))
37780
37823
  continue;
37781
37824
  issues.push({
37782
37825
  filePath: i.filePath,
@@ -37810,6 +37853,7 @@ async function runLintProgrammatic(globs, options, signal) {
37810
37853
  return !absBase.startsWith(process25.cwd());
37811
37854
  });
37812
37855
  const globIgnores = isGlobbingOutsideProject ? [...UNIVERSAL_IGNORES] : cfg.ignores;
37856
+ const ignoreMatcher = createIgnoreMatcher(globIgnores);
37813
37857
  let entries = [];
37814
37858
  const nonGlobSingle = patterns.length === 1 && !/[*?[\]{}()!]/.test(patterns[0]);
37815
37859
  if (nonGlobSingle) {
@@ -37835,7 +37879,7 @@ async function runLintProgrammatic(globs, options, signal) {
37835
37879
  for (const it of items) {
37836
37880
  const full = join11(dir, it);
37837
37881
  const st = statSync6(full);
37838
- if (shouldIgnorePath(full, globIgnores))
37882
+ if (ignoreMatcher(full))
37839
37883
  continue;
37840
37884
  if (st.isDirectory())
37841
37885
  stack.push(full);
@@ -37874,7 +37918,7 @@ async function runLintProgrammatic(globs, options, signal) {
37874
37918
  cntNodeModules++;
37875
37919
  continue;
37876
37920
  }
37877
- if (shouldIgnorePath(f, globIgnores)) {
37921
+ if (ignoreMatcher(f)) {
37878
37922
  cntIgnored++;
37879
37923
  continue;
37880
37924
  }
@@ -37887,15 +37931,12 @@ async function runLintProgrammatic(globs, options, signal) {
37887
37931
  }
37888
37932
  trace2("filter:programmatic", { total: cntTotal, included: cntIncluded, node_modules: cntNodeModules, ignored: cntIgnored, wrongExt: cntWrongExt });
37889
37933
  const concurrency = ENV.CONCURRENCY;
37890
- const limit = createLimiter(concurrency);
37891
37934
  const processFile = async (file) => {
37892
37935
  if (signal?.aborted)
37893
37936
  throw new Error("AbortError");
37894
37937
  const src = readFileSync10(file, "utf8");
37895
37938
  const suppress = parseDisableDirectives(src);
37896
37939
  const commentLines = getCommentLines(src);
37897
- const cfgAny = cfg;
37898
- cfgAny._internalSkipPluginRulesInScan = true;
37899
37940
  let issues = scanContentOptimized(file, src, cfg, suppress, commentLines);
37900
37941
  try {
37901
37942
  const pluginIssues = await applyPlugins(file, src, cfg);
@@ -37904,7 +37945,7 @@ async function runLintProgrammatic(globs, options, signal) {
37904
37945
  throw new Error("AbortError");
37905
37946
  if (isSuppressed(i.ruleId, i.line, suppress))
37906
37947
  continue;
37907
- if (commentLines.has(i.line))
37948
+ if (commentLines.has(i.line) && shouldSkipCommentOnlyPluginIssue(i.ruleId))
37908
37949
  continue;
37909
37950
  issues.push({
37910
37951
  filePath: i.filePath,
@@ -37954,7 +37995,7 @@ async function runLintProgrammatic(globs, options, signal) {
37954
37995
  }
37955
37996
  return issues;
37956
37997
  };
37957
- const issueArrays = await Promise.all(files.map((file) => limit(() => processFile(file))));
37998
+ const issueArrays = await processWithConcurrency(files, concurrency, processFile);
37958
37999
  const allIssues = issueArrays.flat();
37959
38000
  const errors = allIssues.filter((i) => i.severity === "error").length;
37960
38001
  const warnings = allIssues.filter((i) => i.severity === "warning").length;
@@ -37976,10 +38017,10 @@ function parseDisableDirectives(content) {
37976
38017
  for (let i = 0;i < lines.length; i++) {
37977
38018
  const t = lines[i].trim();
37978
38019
  const lineNo = i + 1;
37979
- const nextLineMatch = t.match(/^\/\/\s*(?:eslint|pickier)-disable-next-line\s+(\S.*)$/);
38020
+ const nextLineMatch = t.match(/^\/\/\s*(?:eslint|pickier)-disable-next-line(?:\s+(\S.*))?$/);
37980
38021
  if (nextLineMatch) {
37981
- const ruleText = nextLineMatch[1].replace(/\s+--\s.*$/, "");
37982
- const list = ruleText.split(",").map((s) => s.trim()).filter(Boolean);
38022
+ const ruleText = nextLineMatch[1]?.replace(/\s+--\s.*$/, "");
38023
+ const list = ruleText ? ruleText.split(",").map((s) => s.trim()).filter(Boolean) : ["*"];
37983
38024
  if (list.length > 0) {
37984
38025
  const target = lineNo + 1;
37985
38026
  const set = nextLine.get(target) || new Set;
@@ -38070,23 +38111,6 @@ function parseDisableDirectives(content) {
38070
38111
  const sortedEnableLines = Array.from(rangeEnable.keys()).sort((a, b) => a - b);
38071
38112
  return { nextLine, fileLevel, rangeDisable, rangeEnable, sortedDisableLines, sortedEnableLines };
38072
38113
  }
38073
- function binarySearchLargestLessThan(arr, target) {
38074
- if (arr.length === 0 || arr[0] >= target)
38075
- return -1;
38076
- let left = 0;
38077
- let right = arr.length - 1;
38078
- let result = -1;
38079
- while (left <= right) {
38080
- const mid = Math.floor((left + right) / 2);
38081
- if (arr[mid] < target) {
38082
- result = arr[mid];
38083
- left = mid + 1;
38084
- } else {
38085
- right = mid - 1;
38086
- }
38087
- }
38088
- return result;
38089
- }
38090
38114
  function isSuppressed(ruleId, line, directives) {
38091
38115
  if (directives instanceof Map) {
38092
38116
  const set = directives.get(line);
@@ -38101,14 +38125,28 @@ function isSuppressed(ruleId, line, directives) {
38101
38125
  const nextLineSet = directives.nextLine.get(line);
38102
38126
  if (nextLineSet && matchesRule(ruleId, nextLineSet))
38103
38127
  return true;
38104
- const lastDisableLine = binarySearchLargestLessThan(directives.sortedDisableLines, line);
38105
- const lastEnableLine = binarySearchLargestLessThan(directives.sortedEnableLines, line);
38106
- if (lastDisableLine !== -1 && lastDisableLine > lastEnableLine) {
38107
- const disabledRules = directives.rangeDisable.get(lastDisableLine);
38108
- if (matchesRule(ruleId, disabledRules))
38109
- return true;
38128
+ let disabled = false;
38129
+ let disableIndex = 0;
38130
+ let enableIndex = 0;
38131
+ while (true) {
38132
+ const nextDisable = disableIndex < directives.sortedDisableLines.length ? directives.sortedDisableLines[disableIndex] : Number.POSITIVE_INFINITY;
38133
+ const nextEnable = enableIndex < directives.sortedEnableLines.length ? directives.sortedEnableLines[enableIndex] : Number.POSITIVE_INFINITY;
38134
+ const nextDirectiveLine = Math.min(nextDisable, nextEnable);
38135
+ if (nextDirectiveLine >= line)
38136
+ break;
38137
+ if (nextDisable === nextDirectiveLine) {
38138
+ const disabledRules = directives.rangeDisable.get(nextDisable);
38139
+ if (matchesRule(ruleId, disabledRules))
38140
+ disabled = true;
38141
+ disableIndex++;
38142
+ continue;
38143
+ }
38144
+ const enabledRules = directives.rangeEnable.get(nextEnable);
38145
+ if (enabledRules.has("*") || matchesRule(ruleId, enabledRules))
38146
+ disabled = false;
38147
+ enableIndex++;
38110
38148
  }
38111
- return false;
38149
+ return disabled;
38112
38150
  }
38113
38151
  function matchesRule(ruleId, ruleSet) {
38114
38152
  if (ruleSet.size === 0)
@@ -38128,6 +38166,9 @@ function matchesRule(ruleId, ruleSet) {
38128
38166
  }
38129
38167
  return false;
38130
38168
  }
38169
+ function shouldSkipCommentOnlyPluginIssue(ruleId) {
38170
+ return ruleId !== "spaced-comment" && !ruleId.endsWith("/spaced-comment");
38171
+ }
38131
38172
  function ensureHelpText(issue, ruleId) {
38132
38173
  if (issue.help) {
38133
38174
  return issue;
@@ -38164,8 +38205,22 @@ async function withTimeout2(p, ms, label) {
38164
38205
  throw e;
38165
38206
  }
38166
38207
  }
38167
- async function applyPlugins(filePath, content, cfg) {
38168
- const issues = [];
38208
+ async function processWithConcurrency(items, concurrency, worker) {
38209
+ const results = new Array(items.length);
38210
+ if (items.length === 0)
38211
+ return results;
38212
+ let nextIndex = 0;
38213
+ const workerCount = Math.max(1, Math.min(Math.max(1, concurrency), items.length));
38214
+ async function runWorker() {
38215
+ while (nextIndex < items.length) {
38216
+ const index = nextIndex++;
38217
+ results[index] = await worker(items[index], index);
38218
+ }
38219
+ }
38220
+ await Promise.all(Array.from({ length: workerCount }, runWorker));
38221
+ return results;
38222
+ }
38223
+ function getPluginDefinitions(cfg) {
38169
38224
  let pluginDefs = getAllPlugins();
38170
38225
  if (cfg.plugins && cfg.plugins.length > 0) {
38171
38226
  const coreNames = new Set(["pickier", "style", "regexp", "ts"]);
@@ -38175,6 +38230,9 @@ async function applyPlugins(filePath, content, cfg) {
38175
38230
  for (const p of userPlugins)
38176
38231
  pluginDefs.push(p);
38177
38232
  }
38233
+ return pluginDefs;
38234
+ }
38235
+ function getRulesConfig(cfg, pluginDefs) {
38178
38236
  const rulesConfig = { ...cfg.pluginRules || {} };
38179
38237
  if (cfg.rules?.noUnusedCapturingGroup)
38180
38238
  rulesConfig["regexp/no-unused-capturing-group"] = cfg.rules.noUnusedCapturingGroup;
@@ -38184,115 +38242,168 @@ async function applyPlugins(filePath, content, cfg) {
38184
38242
  "antfu/no-top-level-await": "ts/no-top-level-await"
38185
38243
  };
38186
38244
  for (const [alias, target] of Object.entries(ruleAliases)) {
38187
- if (rulesConfig[alias]) {
38245
+ if (rulesConfig[alias])
38188
38246
  rulesConfig[target] = rulesConfig[alias];
38189
- }
38190
38247
  }
38191
38248
  for (const key of Object.keys(cfg.pluginRules || {})) {
38192
38249
  if (!key.includes("/")) {
38193
38250
  for (const p of pluginDefs) {
38194
- if (p.rules && Object.prototype.hasOwnProperty.call(p.rules, key)) {
38251
+ if (p.rules && Object.prototype.hasOwnProperty.call(p.rules, key))
38195
38252
  rulesConfig[`${p.name}/${key}`] = cfg.pluginRules[key];
38196
- }
38197
38253
  }
38198
38254
  }
38199
38255
  }
38200
- const baseCtx = { filePath, config: cfg };
38256
+ return rulesConfig;
38257
+ }
38258
+ function getPluginPlan(cfg) {
38259
+ const cached = pluginPlanCache.get(cfg);
38260
+ if (cached)
38261
+ return cached;
38262
+ const pluginDefs = getPluginDefinitions(cfg);
38263
+ const rulesConfig = getRulesConfig(cfg, pluginDefs);
38264
+ const checkRules = [];
38265
+ const fixRules = [];
38266
+ const fixableRuleIds = new Set(["no-debugger"]);
38267
+ const fixableBareRuleNames = new Set(["no-debugger"]);
38201
38268
  const executedRules = new Set;
38202
38269
  for (const plugin of pluginDefs) {
38203
- const r = plugin.rules;
38204
- for (const ruleName in r) {
38270
+ for (const ruleName in plugin.rules) {
38205
38271
  const fullRuleId = `${plugin.name}/${ruleName}`;
38206
38272
  const setting = getRuleSetting(rulesConfig, fullRuleId);
38207
38273
  if (!setting.enabled)
38208
38274
  continue;
38209
- if (executedRules.has(ruleName)) {
38275
+ if (executedRules.has(ruleName))
38210
38276
  continue;
38211
- }
38212
38277
  executedRules.add(ruleName);
38213
- const rule = r[ruleName];
38214
- const overrideSeverity = setting.severity;
38215
- if (!rule || typeof rule.check !== "function") {
38216
- if (overrideSeverity === "error") {
38217
- issues.push({
38218
- filePath,
38219
- line: 1,
38220
- column: 1,
38221
- ruleId: `${fullRuleId}-internal`,
38222
- message: "Rule missing implementation (check function is undefined)",
38223
- severity: "error"
38224
- });
38225
- }
38226
- continue;
38278
+ const rule = plugin.rules[ruleName];
38279
+ const planned = {
38280
+ pluginName: plugin.name,
38281
+ ruleName,
38282
+ fullRuleId,
38283
+ rule,
38284
+ severity: setting.severity,
38285
+ options: setting.options
38286
+ };
38287
+ if (typeof rule?.check === "function")
38288
+ checkRules.push(planned);
38289
+ else if (setting.severity === "error") {
38290
+ checkRules.push(planned);
38291
+ }
38292
+ if (typeof rule?.fix === "function") {
38293
+ fixRules.push(planned);
38294
+ fixableRuleIds.add(fullRuleId);
38295
+ fixableBareRuleNames.add(ruleName);
38296
+ }
38297
+ }
38298
+ }
38299
+ const plan = { checkRules, fixRules, fixableRuleIds, fixableBareRuleNames };
38300
+ pluginPlanCache.set(cfg, plan);
38301
+ return plan;
38302
+ }
38303
+ function isShellPath(filePath, content) {
38304
+ return /\.(?:sh|bash|zsh|ksh|dash)$/.test(filePath) || /^#!\s*(?:\/usr\/bin\/env\s+)?(?:ba|z|k|da)?sh\b/.test(content);
38305
+ }
38306
+ function isLockfilePath(filePath) {
38307
+ return /(?:^|[/\\])(?:bun\.lock|bun\.lockb|package-lock\.json|pnpm-lock\.yaml|yarn\.lock|npm-shrinkwrap\.json)$/.test(filePath);
38308
+ }
38309
+ function shouldRunPlannedRule(rule, filePath, content) {
38310
+ switch (rule.pluginName) {
38311
+ case "markdown":
38312
+ return filePath.endsWith(".md");
38313
+ case "shell":
38314
+ return isShellPath(filePath, content);
38315
+ case "publint":
38316
+ return /(?:^|[/\\])package\.json$/.test(filePath);
38317
+ case "lockfile":
38318
+ return isLockfilePath(filePath);
38319
+ case "node":
38320
+ case "ts":
38321
+ case "general":
38322
+ case "quality":
38323
+ case "eslint":
38324
+ case "regexp":
38325
+ case "unused-imports":
38326
+ case "perfectionist":
38327
+ return /\.(?:ts|js|tsx|jsx|mts|mjs|cts|cjs)$/.test(filePath);
38328
+ default:
38329
+ return true;
38330
+ }
38331
+ }
38332
+ async function applyPlugins(filePath, content, cfg) {
38333
+ const issues = [];
38334
+ const plan = getPluginPlan(cfg);
38335
+ const baseCtx = { filePath, config: cfg };
38336
+ for (const planned of plan.checkRules) {
38337
+ if (!shouldRunPlannedRule(planned, filePath, content))
38338
+ continue;
38339
+ const { fullRuleId, rule, severity: overrideSeverity } = planned;
38340
+ if (!rule || typeof rule.check !== "function") {
38341
+ if (overrideSeverity === "error") {
38342
+ issues.push({
38343
+ filePath,
38344
+ line: 1,
38345
+ column: 1,
38346
+ ruleId: `${fullRuleId}-internal`,
38347
+ message: "Rule missing implementation (check function is undefined)",
38348
+ severity: "error"
38349
+ });
38227
38350
  }
38228
- try {
38229
- trace2("rule:start", fullRuleId);
38230
- const ruleTimeoutMs = ENV.RULE_TIMEOUT_MS;
38231
- const ctx = { ...baseCtx, options: setting.options };
38232
- const out = await withTimeout2(Promise.resolve().then(() => rule.check(content, ctx)), ruleTimeoutMs, `rule:${fullRuleId}`);
38233
- trace2("rule:end", fullRuleId, Array.isArray(out) ? out.length : 0);
38234
- for (const i of out) {
38235
- const issueWithHelp = ensureHelpText(i, fullRuleId);
38236
- if (overrideSeverity)
38237
- issues.push({ ...issueWithHelp, severity: overrideSeverity });
38238
- else
38239
- issues.push(issueWithHelp);
38240
- }
38241
- } catch (e) {
38351
+ continue;
38352
+ }
38353
+ try {
38354
+ trace2("rule:start", fullRuleId);
38355
+ const ruleTimeoutMs = ENV.RULE_TIMEOUT_MS;
38356
+ const ctx = { ...baseCtx, options: planned.options };
38357
+ const started = performance.now();
38358
+ const out = await withTimeout2(Promise.resolve().then(() => rule.check(content, ctx)), ruleTimeoutMs, `rule:${fullRuleId}`);
38359
+ const elapsed = performance.now() - started;
38360
+ if (elapsed > ruleTimeoutMs) {
38242
38361
  issues.push({
38243
38362
  filePath,
38244
38363
  line: 1,
38245
38364
  column: 1,
38246
38365
  ruleId: `${fullRuleId}-internal`,
38247
- message: `Rule threw: ${e?.message || e}`,
38366
+ message: `Rule exceeded timeout budget: ${Math.round(elapsed)}ms > ${ruleTimeoutMs}ms`,
38248
38367
  severity: "error"
38249
38368
  });
38250
38369
  }
38370
+ trace2("rule:end", fullRuleId, Array.isArray(out) ? out.length : 0);
38371
+ for (const i of out) {
38372
+ const issueWithHelp = ensureHelpText(i, fullRuleId);
38373
+ if (overrideSeverity)
38374
+ issues.push({ ...issueWithHelp, severity: overrideSeverity });
38375
+ else
38376
+ issues.push(issueWithHelp);
38377
+ }
38378
+ } catch (e) {
38379
+ issues.push({
38380
+ filePath,
38381
+ line: 1,
38382
+ column: 1,
38383
+ ruleId: `${fullRuleId}-internal`,
38384
+ message: `Rule threw: ${e?.message || e}`,
38385
+ severity: "error"
38386
+ });
38251
38387
  }
38252
38388
  }
38253
38389
  return issues;
38254
38390
  }
38255
38391
  function applyPluginFixes(filePath, content, cfg) {
38256
- const pluginDefs = getAllPlugins();
38257
- if (cfg.plugins && cfg.plugins.length > 0) {
38258
- for (const p of cfg.plugins) {
38259
- if (typeof p === "string")
38260
- continue;
38261
- pluginDefs.push(p);
38262
- }
38263
- }
38264
- const rulesConfig = { ...cfg.pluginRules || {} };
38265
- if (cfg.rules?.noUnusedCapturingGroup)
38266
- rulesConfig["regexp/no-unused-capturing-group"] = cfg.rules.noUnusedCapturingGroup;
38267
- for (const key of Object.keys(cfg.pluginRules || {})) {
38268
- if (!key.includes("/")) {
38269
- for (const p of pluginDefs) {
38270
- if (p.rules && Object.prototype.hasOwnProperty.call(p.rules, key))
38271
- rulesConfig[`${p.name}/${key}`] = cfg.pluginRules[key];
38272
- }
38273
- }
38274
- }
38392
+ const plan = getPluginPlan(cfg);
38275
38393
  const baseCtx = { filePath, config: cfg };
38276
38394
  let out = content;
38277
38395
  let changed = true;
38278
38396
  let passes = 0;
38279
38397
  while (changed && passes++ < MAX_FIXER_PASSES) {
38280
38398
  changed = false;
38281
- for (const plugin of pluginDefs) {
38282
- for (const ruleName in plugin.rules) {
38283
- const fullRuleId = `${plugin.name}/${ruleName}`;
38284
- const setting = getRuleSetting(rulesConfig, fullRuleId);
38285
- if (!setting.enabled)
38286
- continue;
38287
- const rule = plugin.rules[ruleName];
38288
- if (typeof rule.fix !== "function")
38289
- continue;
38290
- const ctx = { ...baseCtx, options: setting.options };
38291
- const next = rule.fix(out, ctx);
38292
- if (next !== out) {
38293
- out = next;
38294
- changed = true;
38295
- }
38399
+ for (const planned of plan.fixRules) {
38400
+ if (!shouldRunPlannedRule(planned, filePath, out))
38401
+ continue;
38402
+ const ctx = { ...baseCtx, options: planned.options };
38403
+ const next = planned.rule.fix(out, ctx);
38404
+ if (next !== out) {
38405
+ out = next;
38406
+ changed = true;
38296
38407
  }
38297
38408
  }
38298
38409
  }
@@ -38461,6 +38572,7 @@ function getCommentLines(content) {
38461
38572
  let state = "code";
38462
38573
  let lineNo = 1;
38463
38574
  let lineHasCode = false;
38575
+ let lineSawComment = false;
38464
38576
  let lineStartedInBlockComment = false;
38465
38577
  for (let i = 0;i < content.length; i++) {
38466
38578
  const ch = content[i];
@@ -38470,11 +38582,14 @@ function getCommentLines(content) {
38470
38582
  `) {
38471
38583
  if (lineStartedInBlockComment && state === "block-comment") {
38472
38584
  commentLines.add(lineNo);
38473
- } else if (!lineHasCode && state !== "block-comment") {} else if (!lineHasCode) {
38585
+ } else if (!lineHasCode && lineSawComment && state !== "block-comment") {
38586
+ commentLines.add(lineNo);
38587
+ } else if (!lineHasCode && state === "block-comment") {
38474
38588
  commentLines.add(lineNo);
38475
38589
  }
38476
38590
  lineNo++;
38477
38591
  lineHasCode = false;
38592
+ lineSawComment = false;
38478
38593
  lineStartedInBlockComment = state === "block-comment";
38479
38594
  if (state === "line-comment") {
38480
38595
  state = "code";
@@ -38485,6 +38600,7 @@ function getCommentLines(content) {
38485
38600
  case "code":
38486
38601
  if (ch === "/" && next === "/") {
38487
38602
  state = "line-comment";
38603
+ lineSawComment = true;
38488
38604
  i++;
38489
38605
  } else if (ch === "/" && next === "*") {
38490
38606
  let isRegex = false;
@@ -38526,6 +38642,7 @@ function getCommentLines(content) {
38526
38642
  }
38527
38643
  i--;
38528
38644
  } else {
38645
+ lineSawComment = true;
38529
38646
  state = "block-comment";
38530
38647
  i++;
38531
38648
  }
@@ -38620,6 +38737,8 @@ function getCommentLines(content) {
38620
38737
  }
38621
38738
  if (lineStartedInBlockComment && state === "block-comment") {
38622
38739
  commentLines.add(lineNo);
38740
+ } else if (!lineHasCode && lineSawComment && state !== "block-comment") {
38741
+ commentLines.add(lineNo);
38623
38742
  } else if (!lineHasCode && state === "block-comment") {
38624
38743
  commentLines.add(lineNo);
38625
38744
  }
@@ -38636,6 +38755,10 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
38636
38755
  const quotesDisabled = quotesRuleSetting === "off";
38637
38756
  const skipQuotesCheck = quotesDisabled || fileExt === "json" || fileExt === "jsonc" || fileExt === "lock" || isMd || fileExt === "yaml" || fileExt === "yml" || fileExt === "stx" || fileExt === "html" || fileExt === "htm" || fileExt === "vue" || isShell || filePath.endsWith("bun.lock");
38638
38757
  const skipCodeRules = isMd || fileExt === "yaml" || fileExt === "yml" || fileExt === "json" || fileExt === "jsonc" || isShell;
38758
+ const indentRuleSetting = cfg.rules?.indent ?? cfg.pluginRules?.indent ?? cfg.pluginRules?.["style/indent"];
38759
+ const indentDisabled = indentRuleSetting === "off";
38760
+ const isTemplate = fileExt === "stx" || fileExt === "html" || fileExt === "htm" || fileExt === "vue";
38761
+ const shouldCheckIndent = !indentDisabled && !isMd && !isTemplate;
38639
38762
  let quotesReported = false;
38640
38763
  const sevMap = (s) => s === "warn" ? "warning" : s === "error" ? "error" : undefined;
38641
38764
  const wantDebugger = sevMap(cfg.rules.noDebugger);
@@ -38657,33 +38780,34 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
38657
38780
  }
38658
38781
  }
38659
38782
  const linesInTemplate = new Set;
38660
- let inTemplate = false;
38661
- let escaped = false;
38662
- let currentLine = 1;
38663
- for (let i = 0;i < content.length; i++) {
38664
- const ch = content[i];
38665
- if (escaped) {
38666
- escaped = false;
38667
- if (ch === `
38783
+ if (content.includes("`")) {
38784
+ let inTemplate = false;
38785
+ let escaped = false;
38786
+ let currentLine = 1;
38787
+ for (let i = 0;i < content.length; i++) {
38788
+ const ch = content[i];
38789
+ if (escaped) {
38790
+ escaped = false;
38791
+ if (ch === `
38668
38792
  `)
38669
- currentLine++;
38670
- continue;
38671
- }
38672
- if (ch === "\\") {
38673
- escaped = true;
38674
- continue;
38675
- }
38676
- if (ch === `
38793
+ currentLine++;
38794
+ continue;
38795
+ }
38796
+ if (ch === "\\") {
38797
+ escaped = true;
38798
+ continue;
38799
+ }
38800
+ if (ch === `
38677
38801
  `) {
38678
- currentLine++;
38679
- continue;
38680
- }
38681
- if (ch === "`") {
38682
- inTemplate = !inTemplate;
38683
- continue;
38684
- }
38685
- if (inTemplate) {
38686
- linesInTemplate.add(currentLine);
38802
+ currentLine++;
38803
+ continue;
38804
+ }
38805
+ if (ch === "`") {
38806
+ inTemplate = !inTemplate;
38807
+ continue;
38808
+ }
38809
+ if (inTemplate)
38810
+ linesInTemplate.add(currentLine);
38687
38811
  }
38688
38812
  }
38689
38813
  for (let i = 0;i < lines.length; i++) {
@@ -38702,12 +38826,11 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
38702
38826
  quotesReported = true;
38703
38827
  }
38704
38828
  }
38705
- const indentRuleSetting = cfg.rules?.indent ?? cfg.pluginRules?.indent ?? cfg.pluginRules?.["style/indent"];
38706
- const indentDisabled = indentRuleSetting === "off";
38707
- const isTemplate = fileExt === "stx" || fileExt === "html" || fileExt === "htm" || fileExt === "vue";
38708
- const leadingMatch = line.match(/^[ \t]*/);
38709
- const leading = leadingMatch ? leadingMatch[0] : "";
38710
- if (!indentDisabled && !isMd && !isTemplate && leading.length > 0 && !linesInFencedCodeBlock.has(lineNo) && hasIndentIssue(leading, cfg.format.indent, cfg.format.indentStyle, line)) {
38829
+ let wsEnd = 0;
38830
+ while (wsEnd < line.length && (line.charCodeAt(wsEnd) === 32 || line.charCodeAt(wsEnd) === 9))
38831
+ wsEnd++;
38832
+ const leading = wsEnd > 0 ? line.slice(0, wsEnd) : "";
38833
+ if (shouldCheckIndent && leading.length > 0 && !linesInFencedCodeBlock.has(lineNo) && hasIndentIssue(leading, cfg.format.indent, cfg.format.indentStyle, line)) {
38711
38834
  if (!isSuppressed("indent", lineNo, suppress))
38712
38835
  issues.push({ filePath, line: lineNo, column: 1, ruleId: "indent", message: "Incorrect indentation detected", severity: "warning", help: `Use ${cfg.format.indentStyle === "spaces" ? `${cfg.format.indent} spaces` : "tabs"} for indentation. Configure with format.indent and format.indentStyle in your config` });
38713
38836
  }
@@ -38812,24 +38935,43 @@ function scanContentOptimized(filePath, content, cfg, suppress, commentLines) {
38812
38935
  }
38813
38936
  if (!skipCodeRules && wantNoCondAssign && !linesInTemplate.has(lineNo)) {
38814
38937
  const strippedLine = stripComments2(stripRegexLiterals(line));
38815
- const checkCond = (cond) => /[^=!<>]=(?![=>])/.test(cond.replace(/'[^']*'|"[^"]*"/g, '""'));
38816
- const m1 = strippedLine.match(/\b(?:if|while)\s*\(([^)]*)\)/);
38938
+ const conditionLine = strippedLine.replace(/'[^']*'|"[^"]*"/g, '""');
38939
+ const checkCond = (cond) => /[^=!<>]=(?![=>])/.test(cond);
38940
+ const m1 = conditionLine.match(/\b(?:if|while)\s*\(([^)]*)\)/);
38817
38941
  if (m1) {
38818
38942
  const cond = m1[1];
38819
38943
  if (checkCond(cond)) {
38820
- if (!isSuppressed("no-cond-assign", lineNo, suppress))
38821
- issues.push({ filePath, line: lineNo, column: Math.max(1, line.indexOf("(") + 1), ruleId: "no-cond-assign", message: "Unexpected assignment within a conditional expression", severity: wantNoCondAssign, help: "Use === or == for comparison instead of = (assignment). If assignment was intentional, wrap it in parentheses: if ((x = value))" });
38944
+ if (!isSuppressed("no-cond-assign", lineNo, suppress)) {
38945
+ issues.push({
38946
+ filePath,
38947
+ line: lineNo,
38948
+ column: Math.max(1, line.indexOf("(") + 1),
38949
+ ruleId: "no-cond-assign",
38950
+ message: "Unexpected assignment within a conditional expression",
38951
+ severity: wantNoCondAssign,
38952
+ help: "Use === or == for comparison instead of = (assignment). Wrap intentional assignments in extra parentheses."
38953
+ });
38954
+ }
38822
38955
  }
38823
38956
  }
38824
- const mFor = strippedLine.match(/\bfor\s*\(([^)]*)\)/);
38957
+ const mFor = conditionLine.match(/\bfor\s*\(([^)]*)\)/);
38825
38958
  if (mFor) {
38826
38959
  const inside = mFor[1];
38827
38960
  const parts = inside.split(";");
38828
38961
  if (parts.length >= 2) {
38829
38962
  const cond = parts[1];
38830
38963
  if (checkCond(cond)) {
38831
- if (!isSuppressed("no-cond-assign", lineNo, suppress))
38832
- issues.push({ filePath, line: lineNo, column: Math.max(1, line.indexOf("(") + 1), ruleId: "no-cond-assign", message: "Unexpected assignment within a conditional expression", severity: wantNoCondAssign, help: "Use === or == for comparison instead of = (assignment). If assignment was intentional, wrap it in parentheses: for (let i = 0; (x = arr[i]); i++)" });
38964
+ if (!isSuppressed("no-cond-assign", lineNo, suppress)) {
38965
+ issues.push({
38966
+ filePath,
38967
+ line: lineNo,
38968
+ column: Math.max(1, line.indexOf("(") + 1),
38969
+ ruleId: "no-cond-assign",
38970
+ message: "Unexpected assignment within a conditional expression",
38971
+ severity: wantNoCondAssign,
38972
+ help: "Use === or == for comparison instead of = (assignment). Wrap intentional assignments in extra parentheses."
38973
+ });
38974
+ }
38833
38975
  }
38834
38976
  }
38835
38977
  }
@@ -38841,67 +38983,25 @@ function scanContent(filePath, content, cfg) {
38841
38983
  const suppress = parseDisableDirectives(content);
38842
38984
  const commentLines = getCommentLines(content);
38843
38985
  const issues = scanContentOptimized(filePath, content, cfg, suppress, commentLines);
38844
- if (!cfg._internalSkipPluginRulesInScan) {
38845
- try {
38846
- let pluginDefs = getAllPlugins();
38847
- if (cfg.plugins && cfg.plugins.length > 0) {
38848
- const coreNames = new Set(["pickier", "style", "regexp", "ts"]);
38849
- const userPlugins = cfg.plugins.filter((p) => typeof p !== "string");
38850
- const hasCoreMatch = userPlugins.some((p) => coreNames.has(p.name));
38851
- pluginDefs = hasCoreMatch ? pluginDefs : [];
38852
- for (const p of userPlugins)
38853
- pluginDefs.push(p);
38854
- }
38855
- const rulesConfig = { ...cfg.pluginRules || {} };
38856
- if (cfg.rules?.noUnusedCapturingGroup)
38857
- rulesConfig["regexp/no-unused-capturing-group"] = cfg.rules.noUnusedCapturingGroup;
38858
- for (const key of Object.keys(cfg.pluginRules || {})) {
38859
- if (!key.includes("/")) {
38860
- for (const p of pluginDefs) {
38861
- if (p.rules && Object.prototype.hasOwnProperty.call(p.rules, key))
38862
- rulesConfig[`${p.name}/${key}`] = cfg.pluginRules[key];
38863
- }
38864
- }
38865
- }
38866
- const isRuleEnabled = (ruleId) => {
38867
- const raw = rulesConfig[ruleId];
38868
- const setting = typeof raw === "string" ? raw : undefined;
38869
- return setting === "error" || setting === "warn" || setting === "warning";
38870
- };
38871
- const getRuleSeverity = (ruleId) => {
38872
- const raw = rulesConfig[ruleId];
38873
- const setting = typeof raw === "string" ? raw : undefined;
38874
- if (setting === "error")
38875
- return "error";
38876
- if (setting === "warn" || setting === "warning")
38877
- return "warning";
38878
- return;
38879
- };
38880
- const ctx = { filePath, config: cfg };
38881
- const executedRulesInScan = new Set;
38882
- for (const plugin of pluginDefs) {
38883
- const r = plugin.rules;
38884
- for (const ruleName in r) {
38885
- const fullRuleId = `${plugin.name}/${ruleName}`;
38886
- if (!isRuleEnabled(fullRuleId))
38887
- continue;
38888
- if (executedRulesInScan.has(ruleName))
38889
- continue;
38890
- executedRulesInScan.add(ruleName);
38891
- const rule = r[ruleName];
38892
- if (!rule || typeof rule.check !== "function")
38893
- continue;
38894
- const out = rule.check(content, ctx);
38895
- for (const i of out) {
38896
- if (!isSuppressed(i.ruleId, i.line, suppress)) {
38897
- const sev = getRuleSeverity(fullRuleId);
38898
- issues.push(sev ? { ...i, severity: sev } : i);
38899
- }
38900
- }
38901
- }
38986
+ try {
38987
+ const plan = getPluginPlan(cfg);
38988
+ const ctx = { filePath, config: cfg };
38989
+ for (const planned of plan.checkRules) {
38990
+ if (!shouldRunPlannedRule(planned, filePath, content))
38991
+ continue;
38992
+ if (!planned.rule || typeof planned.rule.check !== "function")
38993
+ continue;
38994
+ const out = planned.rule.check(content, { ...ctx, options: planned.options });
38995
+ for (const i of out) {
38996
+ if (isSuppressed(i.ruleId, i.line, suppress))
38997
+ continue;
38998
+ if (commentLines.has(i.line) && shouldSkipCommentOnlyPluginIssue(i.ruleId))
38999
+ continue;
39000
+ const issueWithHelp = ensureHelpText(i, planned.fullRuleId);
39001
+ issues.push(planned.severity ? { ...issueWithHelp, severity: planned.severity } : issueWithHelp);
38902
39002
  }
38903
- } catch {}
38904
- }
39003
+ }
39004
+ } catch {}
38905
39005
  return issues;
38906
39006
  }
38907
39007
  async function runLint(globs, options) {
@@ -38935,6 +39035,7 @@ async function runLint(globs, options) {
38935
39035
  return !absBase.startsWith(process25.cwd());
38936
39036
  });
38937
39037
  const globIgnores = isGlobbingOutsideProject ? [...UNIVERSAL_IGNORES] : cfg.ignores;
39038
+ const ignoreMatcher = createIgnoreMatcher(globIgnores);
38938
39039
  if (enableDiagnostics) {
38939
39040
  getLogger2().info(`[pickier:diagnostics] Globbing outside project: ${isGlobbingOutsideProject}, ignore patterns: ${globIgnores.length}`);
38940
39041
  if (isGlobbingOutsideProject)
@@ -38971,7 +39072,7 @@ async function runLint(globs, options) {
38971
39072
  for (const it of items) {
38972
39073
  const full = join11(dir, it);
38973
39074
  const st = statSync6(full);
38974
- if (shouldIgnorePath(full, globIgnores))
39075
+ if (ignoreMatcher(full))
38975
39076
  continue;
38976
39077
  if (st.isDirectory())
38977
39078
  stack.push(full);
@@ -39033,7 +39134,7 @@ async function runLint(globs, options) {
39033
39134
  cntNodeModules++;
39034
39135
  continue;
39035
39136
  }
39036
- if (shouldIgnorePath(f, globIgnores)) {
39137
+ if (ignoreMatcher(f)) {
39037
39138
  cntIgnored++;
39038
39139
  continue;
39039
39140
  }
@@ -39064,7 +39165,6 @@ async function runLint(globs, options) {
39064
39165
  }
39065
39166
  }
39066
39167
  const concurrency = ENV.CONCURRENCY;
39067
- const limit = createLimiter(concurrency);
39068
39168
  if (enableDiagnostics)
39069
39169
  getLogger2().info(`[pickier:diagnostics] Starting to process ${files.length} files with concurrency ${concurrency}...`);
39070
39170
  let processedCount = 0;
@@ -39078,23 +39178,33 @@ async function runLint(globs, options) {
39078
39178
  const src = readFileSync10(file, "utf8");
39079
39179
  if (formatOnly) {
39080
39180
  const fixed = formatCode(src, cfg, file);
39081
- if (fixed !== src && !options.dryRun) {
39082
- writeFileSync11(file, fixed, "utf8");
39181
+ if (fixed !== src) {
39182
+ if (!options.dryRun) {
39183
+ writeFileSync11(file, fixed, "utf8");
39184
+ } else {
39185
+ return [{
39186
+ filePath: file,
39187
+ line: 1,
39188
+ column: 1,
39189
+ ruleId: "format",
39190
+ message: "File is not formatted",
39191
+ severity: "error",
39192
+ help: "Run pickier format with --write to apply formatting."
39193
+ }];
39194
+ }
39083
39195
  }
39084
39196
  return [];
39085
39197
  }
39086
39198
  const suppress = parseDisableDirectives(src);
39087
39199
  const isCodeFileForComments = /\.(?:ts|js|tsx|jsx|mts|mjs|cts|cjs)$/.test(file);
39088
39200
  const commentLines = isCodeFileForComments ? getCommentLines(src) : new Set;
39089
- const cfgAny = cfg;
39090
- cfgAny._internalSkipPluginRulesInScan = true;
39091
39201
  let issues = scanContentOptimized(file, src, cfg, suppress, commentLines);
39092
39202
  try {
39093
39203
  const pluginIssues = await applyPlugins(file, src, cfg);
39094
39204
  for (const i of pluginIssues) {
39095
39205
  if (isSuppressed(i.ruleId, i.line, suppress))
39096
39206
  continue;
39097
- if (commentLines.has(i.line))
39207
+ if (commentLines.has(i.line) && shouldSkipCommentOnlyPluginIssue(i.ruleId))
39098
39208
  continue;
39099
39209
  issues.push({
39100
39210
  filePath: i.filePath,
@@ -39153,7 +39263,7 @@ async function runLint(globs, options) {
39153
39263
  trace2("scan done", relative7(process25.cwd(), file), issues.length);
39154
39264
  return issues;
39155
39265
  };
39156
- const issueArrays = await Promise.all(files.map((file) => limit(() => processFile(file))));
39266
+ const issueArrays = await processWithConcurrency(files, concurrency, processFile);
39157
39267
  const allIssues = issueArrays.flat();
39158
39268
  if (enableDiagnostics)
39159
39269
  getLogger2().info(`[pickier:diagnostics] Processing complete! Found ${allIssues.length} issues total`);
@@ -39178,22 +39288,12 @@ async function runLint(globs, options) {
39178
39288
  const problemsText = total === 1 ? "problem" : "problems";
39179
39289
  const errorsText = errors === 1 ? "error" : "errors";
39180
39290
  const warningsText = warnings === 1 ? "warning" : "warnings";
39181
- const pluginDefs = getAllPlugins();
39182
- const fixableRuleIds = new Set;
39183
- fixableRuleIds.add("no-debugger");
39184
- for (const plugin of pluginDefs) {
39185
- for (const ruleName in plugin.rules) {
39186
- const rule = plugin.rules[ruleName];
39187
- if (rule && typeof rule.fix === "function") {
39188
- fixableRuleIds.add(`${plugin.name}/${ruleName}`);
39189
- }
39190
- }
39191
- }
39291
+ const pluginPlan = getPluginPlan(cfg);
39192
39292
  let fixableErrors = 0;
39193
39293
  let fixableWarnings = 0;
39194
39294
  for (const issue of allIssues) {
39195
39295
  const ruleId = issue.ruleId;
39196
- const isFixable = fixableRuleIds.has(ruleId) || Array.from(fixableRuleIds).some((id) => id.endsWith(`/${ruleId}`));
39296
+ const isFixable = pluginPlan.fixableRuleIds.has(ruleId) || pluginPlan.fixableBareRuleNames.has(ruleId);
39197
39297
  if (isFixable) {
39198
39298
  if (issue.severity === "error")
39199
39299
  fixableErrors++;
@@ -39234,13 +39334,14 @@ async function runLint(globs, options) {
39234
39334
  return 1;
39235
39335
  }
39236
39336
  }
39237
- var _logger2 = null;
39337
+ var _logger2 = null, pluginPlanCache;
39238
39338
  var init_linter = __esm(() => {
39239
39339
  init_src();
39240
39340
  init_format();
39241
39341
  init_formatter();
39242
39342
  init_plugins();
39243
39343
  init_utils();
39344
+ pluginPlanCache = new WeakMap;
39244
39345
  });
39245
39346
 
39246
39347
  // src/run.ts
@@ -39262,6 +39363,8 @@ async function runUnified(globs, options) {
39262
39363
  const cfg = await loadConfigFromPath(options.config);
39263
39364
  const src = readFileSync11(filePath, "utf8");
39264
39365
  const fmt = formatCode(src, cfg, filePath);
39366
+ if (options.check && fmt !== src)
39367
+ return 1;
39265
39368
  if (options.write && fmt !== src) {
39266
39369
  writeFileSync12(filePath, fmt, "utf8");
39267
39370
  }
@@ -39919,7 +40022,13 @@ class Command {
39919
40022
  return this;
39920
40023
  }
39921
40024
  isMatched(name) {
39922
- return this.name === name || this.aliasNames.includes(name);
40025
+ if (this.aliasNames.includes(name))
40026
+ return true;
40027
+ if (this.name === name)
40028
+ return true;
40029
+ if (this.namespace && `${this.namespace}:${this.name}` === name)
40030
+ return true;
40031
+ return false;
39923
40032
  }
39924
40033
  get isDefaultCommand() {
39925
40034
  return this.name === "" || this.aliasNames.includes("!");
@@ -40346,7 +40455,7 @@ function onUnknownSubcommand(cliInstance, prefix) {
40346
40455
  cliInstance.on(`${prefix}:*`, () => {
40347
40456
  const args = cliInstance.args ?? [];
40348
40457
  process63.stderr.write(`Unknown ${prefix} subcommand: ${[...args].join(" ")}
40349
- ` + `Run \`${cliInstance.name} ${prefix} --help\` to see available subcommands.
40458
+ ` + `Run \`${cliInstance.name ?? "cli"} ${prefix} --help\` to see available subcommands.
40350
40459
  `);
40351
40460
  process63.exit(64);
40352
40461
  });
@@ -42481,10 +42590,8 @@ Received ${signal}, cleaning up...`);
42481
42590
  console.log(style.dim("Run"), `${this.name} --help`, style.dim("to see all available commands"));
42482
42591
  process53.exit(1);
42483
42592
  }
42484
- async parse(argv = processArgs2, {
42485
- run = true,
42486
- exitOnError = false
42487
- } = {}) {
42593
+ async parse(argv = processArgs2, options = {}) {
42594
+ let { run = true, exitOnError = false } = options;
42488
42595
  if (exitOnError) {
42489
42596
  try {
42490
42597
  return await this.parse(argv, { run });
@@ -43168,7 +43275,7 @@ Run \`${this.name ?? "cli"} --help\` for usage.`;
43168
43275
  this.placeholder = opts.placeholder;
43169
43276
  this.on("key", (char) => {
43170
43277
  if (char === "\t" && this.placeholder) {
43171
- if (!this.value) {
43278
+ if (!this.userInput || this.userInput === "\t") {
43172
43279
  this._setValue(this.placeholder);
43173
43280
  this._setUserInput(this.placeholder, true);
43174
43281
  }
@@ -43392,7 +43499,7 @@ var require_package = __commonJS((exports, module) => {
43392
43499
  module.exports = {
43393
43500
  name: "pickier",
43394
43501
  type: "module",
43395
- version: "0.1.28",
43502
+ version: "0.1.30",
43396
43503
  description: "Format, lint and more in a fraction of seconds.",
43397
43504
  author: "Chris Breuer <chris@stacksjs.org>",
43398
43505
  license: "MIT",
@@ -43468,13 +43575,14 @@ var require_package = __commonJS((exports, module) => {
43468
43575
  "test:watch": "PICKIER_NO_AUTO_CONFIG=1 bun test --watch"
43469
43576
  },
43470
43577
  dependencies: {
43578
+ "@stacksjs/clarity": "^0.3.24",
43471
43579
  "@stacksjs/clapp": "^0.2.3"
43472
43580
  },
43473
43581
  optionalDependencies: {
43474
43582
  "@stacksjs/ts-spell-check": "^0.1.0"
43475
43583
  },
43476
43584
  devDependencies: {
43477
- bunfig: "^0.15.11"
43585
+ bunfig: "^0.15.13"
43478
43586
  }
43479
43587
  };
43480
43588
  });
@@ -43526,7 +43634,14 @@ async function main() {
43526
43634
  const { CLI: CLI2 } = await Promise.resolve().then(() => (init_dist4(), exports_dist3));
43527
43635
  const { version: version3 } = await Promise.resolve().then(() => __toESM(require_package(), 1));
43528
43636
  const cli2 = new CLI2("pickier");
43529
- cli2.command("[...globs]", "Lint files (default)").option("--fix", "Auto-fix lint problems").option("--format", "Format files instead of linting").option("--dry-run", "Simulate fixes without writing").option("--check", "Check formatting without writing (CI-friendly)").option("--max-warnings <n>", "Max warnings before non-zero exit", { default: -1 }).option("--reporter <name>", "stylish|json|compact", { default: "stylish" }).option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache").option("--verbose", "Verbose output").example("pickier .").example("pickier . --fix").example("pickier . --format").example("pickier src --fix --verbose").action(async (cmdGlobs, opts) => {
43637
+ const normalizeActionArgs = (args) => {
43638
+ const [cmdGlobsRaw, optsRaw] = args;
43639
+ const cmdGlobs = Array.isArray(cmdGlobsRaw) ? cmdGlobsRaw.filter((item) => typeof item === "string") : [];
43640
+ const opts = optsRaw && typeof optsRaw === "object" ? optsRaw : {};
43641
+ return [cmdGlobs, opts];
43642
+ };
43643
+ cli2.command("[...globs]", "Lint files (default)").option("--fix", "Auto-fix lint problems").option("--format", "Format files instead of linting").option("--dry-run", "Simulate fixes without writing").option("--check", "Check formatting without writing (CI-friendly)").option("--max-warnings <n>", "Max warnings before non-zero exit", { default: -1 }).option("--reporter <name>", "stylish|json|compact", { default: "stylish" }).option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache").option("--verbose", "Verbose output").example("pickier .").example("pickier . --fix").example("pickier . --format").example("pickier src --fix --verbose").action(async (...args) => {
43644
+ const [cmdGlobs, opts] = normalizeActionArgs(args);
43530
43645
  if (cmdGlobs.length === 0) {
43531
43646
  cli2.outputHelp();
43532
43647
  return;
@@ -43543,17 +43658,20 @@ async function main() {
43543
43658
  const code = await runUnified2(cmdGlobs, { ...opts, mode: runMode });
43544
43659
  process28.exit(code);
43545
43660
  });
43546
- cli2.command("lint [...globs]", "[DEPRECATION] Use `pickier [...globs]` instead. Lint files").option("--fix", "Auto-fix problems").option("--dry-run", "Simulate fixes without writing").option("--max-warnings <n>", "Max warnings before non-zero exit", { default: -1 }).option("--reporter <name>", "stylish|json|compact", { default: "stylish" }).option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache").option("--verbose", "Verbose output").example("pickier lint .").example("pickier lint src --fix").example('pickier lint "src/**/*.{ts,tsx}" --reporter json').action(async (cmdGlobs, opts) => {
43661
+ cli2.command("lint [...globs]", "[DEPRECATION] Use `pickier [...globs]` instead. Lint files").option("--fix", "Auto-fix problems").option("--dry-run", "Simulate fixes without writing").option("--max-warnings <n>", "Max warnings before non-zero exit", { default: -1 }).option("--reporter <name>", "stylish|json|compact", { default: "stylish" }).option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache").option("--verbose", "Verbose output").example("pickier lint .").example("pickier lint src --fix").example('pickier lint "src/**/*.{ts,tsx}" --reporter json').action(async (...args) => {
43662
+ const [cmdGlobs, opts] = normalizeActionArgs(args);
43547
43663
  const { runUnified: runUnified2 } = await Promise.resolve().then(() => (init_run(), exports_run));
43548
43664
  const code = await runUnified2(cmdGlobs, { ...opts, mode: "lint" });
43549
43665
  process28.exit(code);
43550
43666
  });
43551
- cli2.command("format [...globs]", "[DEPRECATION] Use `pickier [...globs] --format` instead. Format files").option("--write", "Write changes to files").option("--check", "Check without writing (CI-friendly)").option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file").option("--ext <exts>", "Comma-separated extensions").option("--verbose", "Verbose output").example("pickier format . --write").example("pickier format . --check").action(async (cmdGlobs, opts) => {
43667
+ cli2.command("format [...globs]", "[DEPRECATION] Use `pickier [...globs] --format` instead. Format files").option("--write", "Write changes to files").option("--check", "Check without writing (CI-friendly)").option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file").option("--ext <exts>", "Comma-separated extensions").option("--verbose", "Verbose output").example("pickier format . --write").example("pickier format . --check").action(async (...args) => {
43668
+ const [cmdGlobs, opts] = normalizeActionArgs(args);
43552
43669
  const { runUnified: runUnified2 } = await Promise.resolve().then(() => (init_run(), exports_run));
43553
43670
  const code = await runUnified2(cmdGlobs, { ...opts, mode: "format" });
43554
43671
  process28.exit(code);
43555
43672
  });
43556
- cli2.command("run [...globs]", "Unified mode (auto, lint, or format)").option("--mode <mode>", "auto|lint|format", { default: "auto" }).option("--fix", "Auto-fix problems (lint mode)").option("--dry-run", "Simulate fixes without writing (lint mode)").option("--max-warnings <n>", "Max warnings before non-zero exit (lint mode)", { default: -1 }).option("--reporter <name>", "stylish|json|compact (lint mode)", { default: "stylish" }).option("--write", "Write changes to files (format mode)").option("--check", "Check without writing (format mode)").option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache (lint mode)").option("--verbose", "Verbose output").example("pickier run . --mode lint --fix").example("pickier run . --mode format --write").action(async (cmdGlobs, opts) => {
43673
+ cli2.command("run [...globs]", "Unified mode (auto, lint, or format)").option("--mode <mode>", "auto|lint|format", { default: "auto" }).option("--fix", "Auto-fix problems (lint mode)").option("--dry-run", "Simulate fixes without writing (lint mode)").option("--max-warnings <n>", "Max warnings before non-zero exit (lint mode)", { default: -1 }).option("--reporter <name>", "stylish|json|compact (lint mode)", { default: "stylish" }).option("--write", "Write changes to files (format mode)").option("--check", "Check without writing (format mode)").option("--config <path>", "Path to pickier config").option("--ignore-path <file>", "Ignore file (like .gitignore)").option("--ext <exts>", "Comma-separated extensions").option("--cache", "Enable cache (lint mode)").option("--verbose", "Verbose output").example("pickier run . --mode lint --fix").example("pickier run . --mode format --write").action(async (...args) => {
43674
+ const [cmdGlobs, opts] = normalizeActionArgs(args);
43557
43675
  const { runUnified: runUnified2 } = await Promise.resolve().then(() => (init_run(), exports_run));
43558
43676
  const code = await runUnified2(cmdGlobs, opts);
43559
43677
  process28.exit(code);