@codefast/cli 0.10.0 → 0.12.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 (303) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +66 -41
  3. package/dist/arrange/command.js +99 -136
  4. package/dist/arrange/domain/ast/collectors-cn.d.ts +2 -2
  5. package/dist/arrange/domain/ast/collectors-cn.js +2 -2
  6. package/dist/arrange/domain/ast/collectors-jsx.d.ts +2 -2
  7. package/dist/arrange/domain/ast/collectors-jsx.js +1 -1
  8. package/dist/arrange/domain/ast/collectors-tv.d.ts +2 -2
  9. package/dist/arrange/domain/ast/collectors-tv.js +5 -5
  10. package/dist/arrange/domain/ast/helpers.d.ts +2 -2
  11. package/dist/arrange/domain/ast/helpers.js +3 -4
  12. package/dist/arrange/domain/ast/simplify-targets.d.ts +1 -1
  13. package/dist/arrange/domain/ast/simplify-targets.js +23 -28
  14. package/dist/arrange/domain/ast/targets.d.ts +2 -2
  15. package/dist/arrange/domain/ast/targets.js +9 -9
  16. package/dist/arrange/{typescript-ast-translator.d.ts → domain/ast/translator.d.ts} +6 -5
  17. package/dist/arrange/{typescript-ast-translator.js → domain/ast/translator.js} +20 -23
  18. package/dist/arrange/domain/constants.d.ts +1 -1
  19. package/dist/arrange/domain/grouping-service.d.ts +2 -2
  20. package/dist/arrange/domain/grouping-service.js +3 -3
  21. package/dist/arrange/domain/grouping.js +3 -3
  22. package/dist/arrange/domain/imports.d.ts +1 -1
  23. package/dist/arrange/domain/imports.js +2 -2
  24. package/dist/arrange/domain/source-text-formatters.js +1 -1
  25. package/dist/arrange/domain/tailwind-token.js +1 -1
  26. package/dist/arrange/domain/token-classifier.d.ts +1 -1
  27. package/dist/arrange/domain/token-classifier.js +2 -2
  28. package/dist/arrange/domain/types.d.ts +3 -3
  29. package/dist/arrange/group/cli-result.d.ts +7 -0
  30. package/dist/arrange/group/cli-result.js +12 -0
  31. package/dist/arrange/group/cli-schema.d.ts +17 -0
  32. package/dist/arrange/group/cli-schema.js +13 -0
  33. package/dist/arrange/group/output.d.ts +7 -0
  34. package/dist/arrange/group/output.js +10 -0
  35. package/dist/arrange/group/suggest.d.ts +8 -0
  36. package/dist/arrange/{suggest.js → group/suggest.js} +2 -2
  37. package/dist/arrange/inspect/cli-result.d.ts +7 -0
  38. package/dist/arrange/inspect/cli-result.js +8 -0
  39. package/dist/arrange/inspect/cli-schema.d.ts +15 -0
  40. package/dist/arrange/inspect/cli-schema.js +9 -0
  41. package/dist/arrange/{domain → inspect/domain}/analyze-service.d.ts +2 -2
  42. package/dist/arrange/{domain → inspect/domain}/analyze-service.js +7 -7
  43. package/dist/arrange/inspect/output.d.ts +7 -0
  44. package/dist/arrange/inspect/output.js +42 -0
  45. package/dist/arrange/inspect/run.d.ts +10 -0
  46. package/dist/arrange/{analyze.js → inspect/run.js} +7 -7
  47. package/dist/arrange/prepare.d.ts +13 -0
  48. package/dist/arrange/{workspace.js → prepare.js} +9 -12
  49. package/dist/arrange/regroup/cli-result.d.ts +13 -0
  50. package/dist/arrange/regroup/cli-result.js +23 -0
  51. package/dist/arrange/regroup/cli-schema.d.ts +20 -0
  52. package/dist/arrange/regroup/cli-schema.js +14 -0
  53. package/dist/arrange/regroup/output.d.ts +14 -0
  54. package/dist/arrange/regroup/output.js +72 -0
  55. package/dist/arrange/{process-file.d.ts → regroup/process-file.d.ts} +3 -3
  56. package/dist/arrange/{process-file.js → regroup/process-file.js} +3 -3
  57. package/dist/arrange/regroup/run.d.ts +11 -0
  58. package/dist/arrange/{sync.js → regroup/run.js} +5 -5
  59. package/dist/arrange/resolve-target.d.ts +2 -2
  60. package/dist/arrange/resolve-target.js +2 -2
  61. package/dist/arrange/scan-target.d.ts +2 -2
  62. package/dist/arrange/scan-target.js +3 -3
  63. package/dist/arrange/simplify/cli-result.d.ts +7 -0
  64. package/dist/arrange/simplify/cli-result.js +8 -0
  65. package/dist/arrange/simplify/cli-schema.d.ts +17 -0
  66. package/dist/arrange/simplify/cli-schema.js +11 -0
  67. package/dist/arrange/simplify/fold-targets.d.ts +13 -0
  68. package/dist/arrange/simplify/fold-targets.js +139 -0
  69. package/dist/arrange/simplify/output.d.ts +7 -0
  70. package/dist/arrange/simplify/output.js +15 -0
  71. package/dist/arrange/simplify/process-file.d.ts +13 -0
  72. package/dist/arrange/simplify/process-file.js +49 -0
  73. package/dist/arrange/simplify/run.d.ts +14 -0
  74. package/dist/arrange/simplify/run.js +38 -0
  75. package/dist/arrange/simplify/variant-classname-probe.d.ts +35 -0
  76. package/dist/arrange/simplify/variant-classname-probe.js +95 -0
  77. package/dist/arrange/source-parse.d.ts +1 -1
  78. package/dist/arrange/source-parse.js +3 -3
  79. package/dist/audit/command.js +152 -212
  80. package/dist/audit/comments/cli-result.d.ts +13 -0
  81. package/dist/audit/comments/cli-result.js +22 -0
  82. package/dist/audit/comments/cli-schema.d.ts +19 -0
  83. package/dist/audit/comments/cli-schema.js +13 -0
  84. package/dist/audit/comments/output.d.ts +7 -0
  85. package/dist/audit/comments/output.js +27 -0
  86. package/dist/audit/comments/prepare.d.ts +16 -0
  87. package/dist/audit/comments/prepare.js +12 -0
  88. package/dist/audit/{run-comments.d.ts → comments/run.d.ts} +5 -5
  89. package/dist/audit/{run-comments.js → comments/run.js} +9 -9
  90. package/dist/audit/display-names/cli-result.d.ts +13 -0
  91. package/dist/audit/display-names/cli-result.js +22 -0
  92. package/dist/audit/display-names/cli-schema.d.ts +18 -0
  93. package/dist/audit/display-names/cli-schema.js +12 -0
  94. package/dist/audit/{domain → display-names/domain}/display-names.d.ts +1 -1
  95. package/dist/audit/display-names/output.d.ts +7 -0
  96. package/dist/audit/display-names/output.js +21 -0
  97. package/dist/audit/display-names/prepare.d.ts +16 -0
  98. package/dist/audit/display-names/prepare.js +12 -0
  99. package/dist/audit/display-names/run.d.ts +14 -0
  100. package/dist/audit/{run-display-names.js → display-names/run.js} +5 -5
  101. package/dist/audit/domain/types.d.ts +43 -0
  102. package/dist/audit/imports/cli-result.d.ts +13 -0
  103. package/dist/audit/imports/cli-result.js +22 -0
  104. package/dist/audit/imports/cli-schema.d.ts +18 -0
  105. package/dist/audit/imports/cli-schema.js +12 -0
  106. package/dist/audit/{domain → imports/domain}/import-policy.d.ts +3 -3
  107. package/dist/audit/{domain → imports/domain}/import-policy.js +4 -11
  108. package/dist/audit/imports/output.d.ts +7 -0
  109. package/dist/audit/imports/output.js +21 -0
  110. package/dist/audit/imports/prepare.d.ts +16 -0
  111. package/dist/audit/imports/prepare.js +12 -0
  112. package/dist/audit/imports/run.d.ts +14 -0
  113. package/dist/audit/{run-imports.js → imports/run.js} +6 -6
  114. package/dist/audit/links/cli-result.d.ts +13 -0
  115. package/dist/audit/links/cli-result.js +22 -0
  116. package/dist/audit/links/cli-schema.d.ts +18 -0
  117. package/dist/audit/links/cli-schema.js +12 -0
  118. package/dist/audit/{domain → links/domain}/markdown-links.d.ts +3 -3
  119. package/dist/audit/{domain → links/domain}/markdown-links.js +22 -8
  120. package/dist/audit/links/output.d.ts +7 -0
  121. package/dist/audit/links/output.js +21 -0
  122. package/dist/audit/links/prepare.d.ts +16 -0
  123. package/dist/audit/links/prepare.js +12 -0
  124. package/dist/audit/links/run.d.ts +14 -0
  125. package/dist/audit/{run-links.js → links/run.js} +4 -4
  126. package/dist/audit/prepare.d.ts +13 -52
  127. package/dist/audit/prepare.js +13 -136
  128. package/dist/audit/publish/cli-result.d.ts +13 -0
  129. package/dist/audit/publish/cli-result.js +22 -0
  130. package/dist/audit/publish/cli-schema.d.ts +18 -0
  131. package/dist/audit/publish/cli-schema.js +12 -0
  132. package/dist/audit/publish/domain/legacy-subpath.d.ts +8 -0
  133. package/dist/audit/publish/domain/legacy-subpath.js +22 -0
  134. package/dist/audit/publish/output.d.ts +7 -0
  135. package/dist/audit/publish/output.js +24 -0
  136. package/dist/audit/publish/prepare.d.ts +16 -0
  137. package/dist/audit/publish/prepare.js +12 -0
  138. package/dist/audit/publish/run.d.ts +14 -0
  139. package/dist/audit/publish/run.js +62 -0
  140. package/dist/audit/rtl/cli-result.d.ts +13 -0
  141. package/dist/audit/rtl/cli-result.js +22 -0
  142. package/dist/audit/rtl/cli-schema.d.ts +18 -0
  143. package/dist/audit/rtl/cli-schema.js +12 -0
  144. package/dist/audit/{domain → rtl/domain}/audit-file.d.ts +1 -1
  145. package/dist/audit/{domain → rtl/domain}/audit-file.js +2 -2
  146. package/dist/audit/{domain → rtl/domain}/tokenize.d.ts +1 -1
  147. package/dist/audit/rtl/output.d.ts +7 -0
  148. package/dist/audit/rtl/output.js +21 -0
  149. package/dist/audit/rtl/prepare.d.ts +13 -0
  150. package/dist/audit/rtl/prepare.js +41 -0
  151. package/dist/audit/rtl/run.d.ts +14 -0
  152. package/dist/audit/{run.js → rtl/run.js} +4 -4
  153. package/dist/bin.js +1 -1
  154. package/dist/cli.js +5 -5
  155. package/dist/core/cli/command-pipeline.d.ts +90 -0
  156. package/dist/core/cli/command-pipeline.js +83 -0
  157. package/dist/core/cli/format-error.d.ts +1 -1
  158. package/dist/core/cli/global-options.d.ts +1 -1
  159. package/dist/core/cli/global-options.js +1 -1
  160. package/dist/core/cli/resolve-root.d.ts +9 -0
  161. package/dist/core/cli/resolve-root.js +16 -0
  162. package/dist/core/cli/result-handle.d.ts +3 -9
  163. package/dist/core/cli/result-handle.js +4 -17
  164. package/dist/core/config/define-config.d.ts +1 -1
  165. package/dist/core/config/loader.d.ts +3 -3
  166. package/dist/core/config/loader.js +2 -2
  167. package/dist/core/config/schema.d.ts +1 -1
  168. package/dist/core/config/schema.js +1 -1
  169. package/dist/core/config/warnings.js +1 -1
  170. package/dist/core/config.d.ts +5 -5
  171. package/dist/core/config.js +4 -4
  172. package/dist/core/filesystem/{port.d.ts → filesystem.d.ts} +1 -1
  173. package/dist/core/filesystem/node.d.ts +3 -3
  174. package/dist/core/filesystem/node.js +1 -1
  175. package/dist/core/schema-parse.d.ts +2 -2
  176. package/dist/core/schema-parse.js +2 -2
  177. package/dist/core/source-text-edit.d.ts +14 -0
  178. package/dist/core/source-text-edit.js +22 -0
  179. package/dist/core/workspace/markdown-walk.d.ts +2 -2
  180. package/dist/core/workspace/markdown-walk.js +1 -1
  181. package/dist/core/workspace/package-version.d.ts +2 -2
  182. package/dist/core/workspace/package-version.js +2 -2
  183. package/dist/core/workspace/resolver.d.ts +3 -3
  184. package/dist/core/workspace/resolver.js +5 -5
  185. package/dist/core/workspace/source-walk.d.ts +2 -2
  186. package/dist/core/workspace/source-walk.js +1 -1
  187. package/dist/core/workspace/typescript-walk.d.ts +2 -2
  188. package/dist/core/workspace/typescript-walk.js +1 -1
  189. package/dist/core/workspace/walk-files.d.ts +2 -2
  190. package/dist/core/workspace/walk-files.js +1 -1
  191. package/dist/index.d.ts +3 -3
  192. package/dist/index.js +2 -2
  193. package/dist/mirror/cli-result.d.ts +1 -1
  194. package/dist/mirror/cli-result.js +1 -1
  195. package/dist/mirror/cli-schema.d.ts +2 -2
  196. package/dist/mirror/cli-schema.js +1 -1
  197. package/dist/mirror/command.js +36 -65
  198. package/dist/mirror/dist-filesystem-node.d.ts +8 -0
  199. package/dist/mirror/{dist-filesystem-impl.js → dist-filesystem-node.js} +3 -3
  200. package/dist/mirror/domain/dirent-guard.d.ts +1 -1
  201. package/dist/mirror/domain/exports.d.ts +2 -2
  202. package/dist/mirror/domain/exports.js +1 -1
  203. package/dist/mirror/domain/types.d.ts +59 -2
  204. package/dist/mirror/output.d.ts +1 -3
  205. package/dist/mirror/output.js +127 -2
  206. package/dist/mirror/package-path.d.ts +5 -5
  207. package/dist/mirror/package-path.js +3 -3
  208. package/dist/mirror/prepare.d.ts +6 -6
  209. package/dist/mirror/prepare.js +8 -12
  210. package/dist/mirror/run.d.ts +12 -0
  211. package/dist/mirror/{sync.js → run.js} +7 -7
  212. package/dist/mirror/supplement-exports.d.ts +3 -3
  213. package/dist/mirror/supplement-exports.js +2 -2
  214. package/dist/mirror/sync-workspace-package.d.ts +4 -4
  215. package/dist/mirror/sync-workspace-package.js +11 -14
  216. package/dist/mirror/write-exports.d.ts +3 -3
  217. package/dist/mirror/write-exports.js +3 -3
  218. package/dist/pack-slim/cli-result.d.ts +1 -1
  219. package/dist/pack-slim/cli-result.js +1 -1
  220. package/dist/pack-slim/cli-schema.d.ts +1 -1
  221. package/dist/pack-slim/cli-schema.js +1 -1
  222. package/dist/pack-slim/command.js +36 -71
  223. package/dist/pack-slim/domain/transform.d.ts +22 -1
  224. package/dist/pack-slim/domain/transform.js +65 -8
  225. package/dist/pack-slim/output.d.ts +1 -1
  226. package/dist/pack-slim/output.js +1 -1
  227. package/dist/pack-slim/prepare.d.ts +21 -0
  228. package/dist/pack-slim/prepare.js +14 -0
  229. package/dist/pack-slim/{sync.d.ts → run.d.ts} +6 -6
  230. package/dist/pack-slim/{sync.js → run.js} +5 -5
  231. package/dist/pack-slim/working-tree.d.ts +2 -2
  232. package/dist/pack-slim/working-tree.js +2 -2
  233. package/dist/tag/cli-result.d.ts +8 -2
  234. package/dist/tag/cli-result.js +15 -2
  235. package/dist/tag/cli-schema.d.ts +4 -4
  236. package/dist/tag/cli-schema.js +3 -4
  237. package/dist/tag/command.js +34 -61
  238. package/dist/tag/domain/skip-filter.d.ts +13 -0
  239. package/dist/tag/domain/skip-filter.js +29 -0
  240. package/dist/tag/domain/types.d.ts +22 -2
  241. package/dist/tag/domain/version-summary.d.ts +13 -0
  242. package/dist/tag/domain/version-summary.js +24 -0
  243. package/dist/tag/output.d.ts +4 -4
  244. package/dist/tag/output.js +7 -10
  245. package/dist/tag/prepare.d.ts +5 -5
  246. package/dist/tag/prepare.js +5 -5
  247. package/dist/tag/run.d.ts +10 -0
  248. package/dist/tag/{sync.js → run.js} +23 -53
  249. package/dist/tag/target/candidates.d.ts +8 -0
  250. package/dist/tag/{target-candidates.js → target/candidates.js} +3 -3
  251. package/dist/tag/{resolve-target-path.d.ts → target/resolve-path.d.ts} +2 -2
  252. package/dist/tag/target/runner.d.ts +8 -0
  253. package/dist/tag/{target-runner.js → target/runner.js} +3 -3
  254. package/dist/tag/{since-writer.d.ts → writer/since-writer.d.ts} +3 -3
  255. package/dist/tag/{since-writer.js → writer/since-writer.js} +1 -1
  256. package/dist/tag/{version-resolver.d.ts → writer/version-resolver.d.ts} +2 -2
  257. package/dist/tag/{version-resolver.js → writer/version-resolver.js} +1 -1
  258. package/package.json +15 -7
  259. package/dist/arrange/analyze.d.ts +0 -10
  260. package/dist/arrange/cli-schema.d.ts +0 -50
  261. package/dist/arrange/cli-schema.js +0 -34
  262. package/dist/arrange/output.d.ts +0 -26
  263. package/dist/arrange/output.js +0 -127
  264. package/dist/arrange/simplify-process-file.d.ts +0 -11
  265. package/dist/arrange/simplify-process-file.js +0 -30
  266. package/dist/arrange/simplify-sync.d.ts +0 -13
  267. package/dist/arrange/simplify-sync.js +0 -30
  268. package/dist/arrange/suggest.d.ts +0 -8
  269. package/dist/arrange/sync.d.ts +0 -11
  270. package/dist/arrange/workspace.d.ts +0 -13
  271. package/dist/audit/cli-schema.d.ts +0 -93
  272. package/dist/audit/cli-schema.js +0 -66
  273. package/dist/audit/output.d.ts +0 -91
  274. package/dist/audit/output.js +0 -213
  275. package/dist/audit/run-display-names.d.ts +0 -14
  276. package/dist/audit/run-imports.d.ts +0 -14
  277. package/dist/audit/run-links.d.ts +0 -14
  278. package/dist/audit/run.d.ts +0 -14
  279. package/dist/mirror/dist-filesystem-impl.d.ts +0 -8
  280. package/dist/mirror/sync-reporter.d.ts +0 -60
  281. package/dist/mirror/sync-reporter.js +0 -128
  282. package/dist/mirror/sync-types.d.ts +0 -43
  283. package/dist/mirror/sync-types.js +0 -1
  284. package/dist/mirror/sync.d.ts +0 -12
  285. package/dist/tag/sync.d.ts +0 -42
  286. package/dist/tag/target-candidates.d.ts +0 -8
  287. package/dist/tag/target-runner.d.ts +0 -8
  288. /package/dist/audit/{domain → comments/domain}/comment-content.d.ts +0 -0
  289. /package/dist/audit/{domain → comments/domain}/comment-content.js +0 -0
  290. /package/dist/audit/{domain → comments/domain}/comment-dividers.d.ts +0 -0
  291. /package/dist/audit/{domain → comments/domain}/comment-dividers.js +0 -0
  292. /package/dist/audit/{domain → comments/domain}/link-references.d.ts +0 -0
  293. /package/dist/audit/{domain → comments/domain}/link-references.js +0 -0
  294. /package/dist/audit/{domain → comments/domain}/since-versions.d.ts +0 -0
  295. /package/dist/audit/{domain → comments/domain}/since-versions.js +0 -0
  296. /package/dist/audit/{domain → comments/domain}/tsdoc-syntax.d.ts +0 -0
  297. /package/dist/audit/{domain → comments/domain}/tsdoc-syntax.js +0 -0
  298. /package/dist/audit/{domain → display-names/domain}/display-names.js +0 -0
  299. /package/dist/audit/{domain → rtl/domain}/mappings.d.ts +0 -0
  300. /package/dist/audit/{domain → rtl/domain}/mappings.js +0 -0
  301. /package/dist/audit/{domain → rtl/domain}/tokenize.js +0 -0
  302. /package/dist/core/filesystem/{port.js → filesystem.js} +0 -0
  303. /package/dist/tag/{resolve-target-path.js → target/resolve-path.js} +0 -0
@@ -1,8 +1,8 @@
1
- import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainJsxAttribute, isDomainJsxExpression, isDomainObjectLiteralExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainTailwindClassLiteral, } from "#/arrange/domain/ast/ast-node";
2
- import { buildKnownCnTvBindings, isCnOrTvIdentifier } from "#/arrange/domain/ast/helpers";
3
- import { MAX_OBJECT_DEPTH } from "#/arrange/domain/constants";
4
- import { escapeTsStringLiteralContent } from "#/arrange/domain/source-text-formatters";
5
- import { indentOfLineContaining } from "#/core/source-text-edit";
1
+ import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainJsxAttribute, isDomainJsxExpression, isDomainObjectLiteralExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainTailwindClassLiteral, } from "#arrange/domain/ast/ast-node";
2
+ import { buildKnownCnTvBindings, isCnOrTvIdentifier } from "#arrange/domain/ast/helpers";
3
+ import { MAX_OBJECT_DEPTH } from "#arrange/domain/constants";
4
+ import { escapeTsStringLiteralContent } from "#arrange/domain/source-text-formatters";
5
+ import { indentOfLineContaining } from "#core/source-text-edit";
6
6
  function toFlatString(text) {
7
7
  return `"${escapeTsStringLiteralContent(text.trim())}"`;
8
8
  }
@@ -15,47 +15,42 @@ function joinLiterals(args) {
15
15
  function isAllStaticLiterals(args) {
16
16
  return args.length > 0 && args.every(isDomainTailwindClassLiteral);
17
17
  }
18
- // ---------------------------------------------------------------------------
19
- // Mixed cn() merge: ALL static args → one string first, dynamic args follow
20
- // ---------------------------------------------------------------------------
21
18
  /**
22
- * For a cn() call that has both static and dynamic args:
23
- * - Merge ALL static string literals (regardless of position) into one string.
24
- * - Place the merged string first.
25
- * - Append all dynamic args in their original relative order.
19
+ * Builds a mixed cn() replacement that coalesces each run of adjacent static literals into one string.
26
20
  *
27
- * Returns `null` when nothing changes (0 statics, or already 1 static at arg[0]).
21
+ * @remarks Argument order is preserved so tailwind-merge precedence is unchanged — a later cn()
22
+ * argument still overrides an earlier one. Returns `null` when no run of two-or-more adjacent statics
23
+ * exists, since reordering a lone static across a dynamic argument would change what renders.
28
24
  */
29
25
  function buildMixedCnReplacement(call, sourceText) {
30
26
  const args = [...call.arguments];
31
27
  if (args.length === 0) {
32
28
  return null;
33
29
  }
34
- const staticTexts = [];
35
- const dynamicSrcs = [];
30
+ const pieces = [];
36
31
  for (const arg of args) {
37
32
  if (isDomainTailwindClassLiteral(arg)) {
38
- staticTexts.push(arg.text);
33
+ const last = pieces.at(-1);
34
+ if (last?.kind === "static") {
35
+ last.texts.push(arg.text);
36
+ }
37
+ else {
38
+ pieces.push({ kind: "static", texts: [arg.text] });
39
+ }
39
40
  }
40
41
  else {
41
- dynamicSrcs.push(sourceText.slice(arg.pos, arg.end));
42
+ pieces.push({ kind: "dynamic", src: sourceText.slice(arg.pos, arg.end) });
42
43
  }
43
44
  }
44
- if (staticTexts.length === 0) {
45
- return null;
46
- }
47
- // Already simplest form: 1 static arg already at the front.
48
- const firstArg = args[0];
49
- if (staticTexts.length === 1 && firstArg !== undefined && isDomainTailwindClassLiteral(firstArg)) {
45
+ const merged = pieces.some((piece) => piece.kind === "static" && piece.texts.length > 1);
46
+ if (!merged) {
50
47
  return null;
51
48
  }
52
- const flatStatic = staticTexts.join(" ").trim();
53
49
  const baseIndent = indentOfLineContaining(sourceText, call.pos);
54
50
  const argIndent = `${baseIndent} `;
55
- const lines = [
56
- `${argIndent}"${escapeTsStringLiteralContent(flatStatic)}",`,
57
- ...dynamicSrcs.map((src) => `${argIndent}${src},`),
58
- ];
51
+ const lines = pieces.map((piece) => piece.kind === "static"
52
+ ? `${argIndent}"${escapeTsStringLiteralContent(piece.texts.join(" ").trim())}",`
53
+ : `${argIndent}${piece.src},`);
59
54
  return `cn(\n${lines.join("\n")}\n${baseIndent})`;
60
55
  }
61
56
  // ── tv() array collector ─────────────────────────────────────────────────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
- import type { DomainSourceFile } from "#/arrange/domain/ast/ast-node";
2
- import type { GroupTarget, PlannedGroupEdit } from "#/arrange/domain/types";
1
+ import type { DomainSourceFile } from "#arrange/domain/ast/ast-node";
2
+ import type { GroupTarget, PlannedGroupEdit } from "#arrange/domain/types";
3
3
  /**
4
4
  * Resolves the source position where a group target's replacement begins.
5
5
  *
@@ -1,12 +1,12 @@
1
- import { isDomainArrayLiteralExpression, isDomainJsxAttribute, isDomainPropertyAssignment, isDomainTailwindClassLiteral, forEachDomainChild, } from "#/arrange/domain/ast/ast-node";
2
- import { isUnsafeLiteralForCnStyleApplySplit } from "#/arrange/domain/ast/collectors-cn";
3
- import { jsxClassNameStaticLiteral } from "#/arrange/domain/ast/collectors-jsx";
4
- import { collectGroupableStringNodes, slotClassString } from "#/arrange/domain/ast/collectors-tv";
5
- import { APPLY_MIN_TOKENS } from "#/arrange/domain/constants";
6
- import { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels, } from "#/arrange/domain/grouping";
7
- import { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatJsxCnAttributeValue, } from "#/arrange/domain/source-text-formatters";
8
- import { tokenizeClassString } from "#/arrange/domain/tailwind-token";
9
- import { endAfterOptionalCommaFollowingInSource, indentOfLineContaining, textPrefixFromLineStartToPosition, } from "#/core/source-text-edit";
1
+ import { isDomainArrayLiteralExpression, isDomainJsxAttribute, isDomainPropertyAssignment, isDomainTailwindClassLiteral, forEachDomainChild, } from "#arrange/domain/ast/ast-node";
2
+ import { isUnsafeLiteralForCnStyleApplySplit } from "#arrange/domain/ast/collectors-cn";
3
+ import { jsxClassNameStaticLiteral } from "#arrange/domain/ast/collectors-jsx";
4
+ import { collectGroupableStringNodes, slotClassString } from "#arrange/domain/ast/collectors-tv";
5
+ import { APPLY_MIN_TOKENS } from "#arrange/domain/constants";
6
+ import { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels, } from "#arrange/domain/grouping";
7
+ import { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatJsxCnAttributeValue, } from "#arrange/domain/source-text-formatters";
8
+ import { tokenizeClassString } from "#arrange/domain/tailwind-token";
9
+ import { endAfterOptionalCommaFollowingInSource, indentOfLineContaining, textPrefixFromLineStartToPosition, } from "#core/source-text-edit";
10
10
  /**
11
11
  * Resolves the source position where a group target's replacement begins.
12
12
  *
@@ -2,7 +2,7 @@
2
2
  * Anti-corruption layer: maps the oxc-parser ESTree AST to the arrange domain AST.
3
3
  * This is the only place that parses TypeScript source for arrange AST translation.
4
4
  */
5
- import type { DomainSourceFile } from "#/arrange/domain/ast/ast-node";
5
+ import type { DomainSourceFile } from "#arrange/domain/ast/ast-node";
6
6
  /**
7
7
  * The translator mapping the `oxc-parser` ESTree AST to the arrange domain AST.
8
8
  *
@@ -11,11 +11,12 @@ import type { DomainSourceFile } from "#/arrange/domain/ast/ast-node";
11
11
  export declare class TypeScriptAstTranslator {
12
12
  translateSourceFile(filePath: string, sourceText: string): DomainSourceFile;
13
13
  /**
14
- * Own child nodes in source-declaration order, mirroring `ts.forEachChild`:
15
- * recurses into nested node objects and arrays of nodes, skipping primitives
16
- * and plain records (e.g. a template element's `value`) that carry no `type`.
14
+ * Translates any node the typed cases do not cover, recursing into own child nodes and arrays of
15
+ * nodes in source-declaration order and skipping primitives and records that carry no `type`.
16
+ *
17
+ * @remarks Children are walked inline rather than through a generator — the `yield` per child is
18
+ * several times slower than a plain loop on this hot path, and this fallback runs for most nodes.
17
19
  */
18
- private childNodesOf;
19
20
  private translateUnknown;
20
21
  private stringLiteralText;
21
22
  private noSubstitutionTemplateText;
@@ -3,7 +3,7 @@
3
3
  * This is the only place that parses TypeScript source for arrange AST translation.
4
4
  */
5
5
  import { parseSync } from "oxc-parser";
6
- import { DomainBinaryOperator, DomainSyntaxKind } from "#/arrange/domain/ast/ast-node";
6
+ import { DomainBinaryOperator, DomainSyntaxKind } from "#arrange/domain/ast/ast-node";
7
7
  function isOxcNode(value) {
8
8
  return typeof value === "object" && value !== null && typeof value.type === "string";
9
9
  }
@@ -20,11 +20,21 @@ export class TypeScriptAstTranslator {
20
20
  return this.parseDomainSourceFile(filePath, sourceText);
21
21
  }
22
22
  /**
23
- * Own child nodes in source-declaration order, mirroring `ts.forEachChild`:
24
- * recurses into nested node objects and arrays of nodes, skipping primitives
25
- * and plain records (e.g. a template element's `value`) that carry no `type`.
23
+ * Translates any node the typed cases do not cover, recursing into own child nodes and arrays of
24
+ * nodes in source-declaration order and skipping primitives and records that carry no `type`.
25
+ *
26
+ * @remarks Children are walked inline rather than through a generator — the `yield` per child is
27
+ * several times slower than a plain loop on this hot path, and this fallback runs for most nodes.
26
28
  */
27
- *childNodesOf(node) {
29
+ translateUnknown(node, parent) {
30
+ const self = {
31
+ kind: DomainSyntaxKind.Unknown,
32
+ pos: node.start,
33
+ end: node.end,
34
+ parent,
35
+ children: [],
36
+ };
37
+ const childList = [];
28
38
  for (const key in node) {
29
39
  if (key === "type" || key === "start" || key === "end" || key === "range") {
30
40
  continue;
@@ -33,29 +43,16 @@ export class TypeScriptAstTranslator {
33
43
  if (Array.isArray(value)) {
34
44
  for (const element of value) {
35
45
  if (isOxcNode(element)) {
36
- yield element;
46
+ childList.push(this.translateNode(element, self));
37
47
  }
38
48
  }
39
- continue;
40
49
  }
41
- if (isOxcNode(value)) {
42
- yield value;
50
+ else if (isOxcNode(value)) {
51
+ childList.push(this.translateNode(value, self));
43
52
  }
44
53
  }
45
- }
46
- translateUnknown(node, parent) {
47
- const self = {
48
- kind: DomainSyntaxKind.Unknown,
49
- pos: node.start,
50
- end: node.end,
51
- parent,
52
- children: [],
53
- };
54
- const childList = [];
55
- for (const child of this.childNodesOf(node)) {
56
- childList.push(this.translateNode(child, self));
57
- }
58
- return { ...self, children: childList };
54
+ self.children = childList;
55
+ return self;
59
56
  }
60
57
  stringLiteralText(node) {
61
58
  if (node.type === "Literal" && typeof node.value === "string") {
@@ -1,4 +1,4 @@
1
- import type { Bucket } from "#/arrange/domain/types";
1
+ import type { Bucket } from "#arrange/domain/types";
2
2
  /**
3
3
  * Analyze report: long literal threshold (token count).
4
4
  *
@@ -2,8 +2,8 @@
2
2
  * Rich domain: plan Tailwind class grouping / cn-in-tv unwrap for a single file.
3
3
  * Pure: only DomainSourceFile, source strings, and options — no I/O.
4
4
  */
5
- import type { DomainCallExpression, DomainSourceFile } from "#/arrange/domain/ast/ast-node";
6
- import type { GroupFileResult, PlannedGroupEdit } from "#/arrange/domain/types";
5
+ import type { DomainCallExpression, DomainSourceFile } from "#arrange/domain/ast/ast-node";
6
+ import type { GroupFileResult, PlannedGroupEdit } from "#arrange/domain/types";
7
7
  /**
8
8
  * A planned replacement unwrapping one `cn()` call nested in `tv({ ... })`.
9
9
  *
@@ -2,9 +2,9 @@
2
2
  * Rich domain: plan Tailwind class grouping / cn-in-tv unwrap for a single file.
3
3
  * Pure: only DomainSourceFile, source strings, and options — no I/O.
4
4
  */
5
- import { listAllCnCallsInsideTvInSourceFile } from "#/arrange/domain/ast/collectors-tv";
6
- import { applyEditsDescending, buildKnownCnTvBindings, unwrapCnInsideTvCallReplacement, } from "#/arrange/domain/ast/helpers";
7
- import { collectGroupTargets, planGroupEditForTarget, targetReplaceStart } from "#/arrange/domain/ast/targets";
5
+ import { listAllCnCallsInsideTvInSourceFile } from "#arrange/domain/ast/collectors-tv";
6
+ import { applyEditsDescending, buildKnownCnTvBindings, unwrapCnInsideTvCallReplacement, } from "#arrange/domain/ast/helpers";
7
+ import { collectGroupTargets, planGroupEditForTarget, targetReplaceStart } from "#arrange/domain/ast/targets";
8
8
  function toUnwrapPlans(cnInTvCalls, sourceText) {
9
9
  return cnInTvCalls
10
10
  .map((call) => {
@@ -1,6 +1,6 @@
1
- import { BUCKET_ORDER, MAX_GROUPS_BASE, MAX_GROUPS_CAP, MAX_GROUPS_HEADROOM, MIN_GROUP_TOKENS, } from "#/arrange/domain/constants";
2
- import { stripVariants, tokenizeClassString } from "#/arrange/domain/tailwind-token";
3
- import { bucketsCompatible, bucketsMergeCompatible, classifyToken, compositeSecondaryOrder, selectorKey, stateKey, } from "#/arrange/domain/token-classifier";
1
+ import { BUCKET_ORDER, MAX_GROUPS_BASE, MAX_GROUPS_CAP, MAX_GROUPS_HEADROOM, MIN_GROUP_TOKENS, } from "#arrange/domain/constants";
2
+ import { stripVariants, tokenizeClassString } from "#arrange/domain/tailwind-token";
3
+ import { bucketsCompatible, bucketsMergeCompatible, classifyToken, compositeSecondaryOrder, selectorKey, stateKey, } from "#arrange/domain/token-classifier";
4
4
  /**
5
5
  * `cn()` grouping: bucket sequence is {@link BUCKET_ORDER} only; tokens are classified with
6
6
  * {@link classifyToken}. Comparators here (`compareClassifiedTailwindTokensForCnGrouping`, …)
@@ -1,4 +1,4 @@
1
- import type { DomainSourceFile } from "#/arrange/domain/ast/ast-node";
1
+ import type { DomainSourceFile } from "#arrange/domain/ast/ast-node";
2
2
  /**
3
3
  * After simplify rewrites, drop the `cn` import specifier when `cn` is no
4
4
  * longer referenced anywhere outside the import declarations.
@@ -1,5 +1,5 @@
1
- import { forEachDomainChild, isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, isDomainStringLiteral, } from "#/arrange/domain/ast/ast-node";
2
- import { endAfterOptionalCommaFollowingInSource } from "#/core/source-text-edit";
1
+ import { forEachDomainChild, isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, isDomainStringLiteral, } from "#arrange/domain/ast/ast-node";
2
+ import { endAfterOptionalCommaFollowingInSource } from "#core/source-text-edit";
3
3
  function sourceFileImportsCn(sourceFile) {
4
4
  for (const statement of sourceFile.statements) {
5
5
  if (!isDomainImportDeclaration(statement) || !statement.importClause) {
@@ -1,4 +1,4 @@
1
- import { indentOfLineContaining } from "#/core/source-text-edit";
1
+ import { indentOfLineContaining } from "#core/source-text-edit";
2
2
  /**
3
3
  * Escapes backslashes and double quotes for embedding in a double-quoted TypeScript string literal.
4
4
  *
@@ -1,4 +1,4 @@
1
- import { MAX_STRIP_VARIANT_PASSES } from "#/arrange/domain/constants";
1
+ import { MAX_STRIP_VARIANT_PASSES } from "#arrange/domain/constants";
2
2
  /**
3
3
  * Splits a class string into its whitespace-separated tokens.
4
4
  *
@@ -1,4 +1,4 @@
1
- import type { Bucket } from "#/arrange/domain/types";
1
+ import type { Bucket } from "#arrange/domain/types";
2
2
  /**
3
3
  * Secondary sort inside the **composite** bucket: opacity / blend / isolation →
4
4
  * 3D context → 3D transforms → 2D transforms → filters → will-change.
@@ -1,5 +1,5 @@
1
- import { COMPATIBLE_BUCKET_SETS, RESPONSIVE_PREFIX, STATE_PREFIXES } from "#/arrange/domain/constants";
2
- import { indexOfFirstVariantColon, stripVariants } from "#/arrange/domain/tailwind-token";
1
+ import { COMPATIBLE_BUCKET_SETS, RESPONSIVE_PREFIX, STATE_PREFIXES } from "#arrange/domain/constants";
2
+ import { indexOfFirstVariantColon, stripVariants } from "#arrange/domain/tailwind-token";
3
3
  /**
4
4
  * Bare-token classification is **total** (always returns a {@link Bucket}). The `Result` pattern
5
5
  * (`isOk` / `isErr`) belongs at arrange use-case / I/O boundaries, not on this hot path.
@@ -7,9 +7,9 @@
7
7
  *
8
8
  * `arbitrary` and `other` are non-pipeline tails for `[prop:value]` syntax and unknown utilities.
9
9
  */
10
- import type { DomainAstNode, DomainCallExpression, DomainSourceFile, DomainTailwindClassLiteral } from "#/arrange/domain/ast/ast-node";
11
- import type { GroupFileWorkPlan } from "#/arrange/domain/grouping-service";
12
- import type { CodefastConfig } from "#/core/config/schema";
10
+ import type { DomainAstNode, DomainCallExpression, DomainSourceFile, DomainTailwindClassLiteral } from "#arrange/domain/ast/ast-node";
11
+ import type { GroupFileWorkPlan } from "#arrange/domain/grouping-service";
12
+ import type { CodefastConfig } from "#core/config/schema";
13
13
  /**
14
14
  * The render-pipeline bucket a Tailwind token classifies into.
15
15
  *
@@ -0,0 +1,7 @@
1
+ import type { ArrangeSuggestGroupsOutput } from "#arrange/domain/types";
2
+ /**
3
+ * Machine-readable `arrange group` suggestion for `--json`.
4
+ *
5
+ * @since 0.11.0
6
+ */
7
+ export declare function formatArrangeGroupJsonOutput(output: ArrangeSuggestGroupsOutput): string;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Machine-readable `arrange group` suggestion for `--json`.
3
+ *
4
+ * @since 0.11.0
5
+ */
6
+ export function formatArrangeGroupJsonOutput(output) {
7
+ return JSON.stringify({
8
+ schemaVersion: 1,
9
+ primaryLine: output.primaryLine,
10
+ bucketsCommentLine: output.bucketsCommentLine,
11
+ });
12
+ }
@@ -0,0 +1,17 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * The request payload for `arrange group`.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export type ArrangeSuggestGroupsRequest = {
8
+ inlineClasses: string;
9
+ emitTvStyleArray: boolean;
10
+ trailingClassName: boolean;
11
+ };
12
+ /**
13
+ * The `zod` schema validating an `arrange group` request.
14
+ *
15
+ * @since 0.3.16-canary.0
16
+ */
17
+ export declare const arrangeSuggestGroupsRequestSchema: z.ZodType<ArrangeSuggestGroupsRequest>;
@@ -0,0 +1,13 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * The `zod` schema validating an `arrange group` request.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export const arrangeSuggestGroupsRequestSchema = z.object({
8
+ inlineClasses: z
9
+ .string()
10
+ .min(1, 'Pass a class string. Example: codefast arrange group "flex gap-2 text-sm rounded-md"'),
11
+ emitTvStyleArray: z.boolean(),
12
+ trailingClassName: z.boolean(),
13
+ });
@@ -0,0 +1,7 @@
1
+ import type { ArrangeSuggestGroupsOutput } from "#arrange/domain/types";
2
+ /**
3
+ * Presents the suggested grouping lines for an `arrange group` run.
4
+ *
5
+ * @since 0.11.0
6
+ */
7
+ export declare function presentArrangeGroupResult(output: ArrangeSuggestGroupsOutput): void;
@@ -0,0 +1,10 @@
1
+ import { logger } from "#core/logger";
2
+ /**
3
+ * Presents the suggested grouping lines for an `arrange group` run.
4
+ *
5
+ * @since 0.11.0
6
+ */
7
+ export function presentArrangeGroupResult(output) {
8
+ logger.out(output.primaryLine);
9
+ logger.out(output.bucketsCommentLine);
10
+ }
@@ -0,0 +1,8 @@
1
+ import type { ArrangeSuggestGroupsOutput } from "#arrange/domain/types";
2
+ import type { ArrangeSuggestGroupsRequest } from "#arrange/group/cli-schema";
3
+ /**
4
+ * Formats the suggested grouping for an inline class string as `arrange group` output lines.
5
+ *
6
+ * @since 0.3.16-canary.0
7
+ */
8
+ export declare function suggestCnGroupsFromCli(request: ArrangeSuggestGroupsRequest): ArrangeSuggestGroupsOutput;
@@ -1,5 +1,5 @@
1
- import { suggestCnGroups, summarizeGroupBucketLabels } from "#/arrange/domain/grouping";
2
- import { formatArray, formatCnCall } from "#/arrange/domain/source-text-formatters";
1
+ import { suggestCnGroups, summarizeGroupBucketLabels } from "#arrange/domain/grouping";
2
+ import { formatArray, formatCnCall } from "#arrange/domain/source-text-formatters";
3
3
  /**
4
4
  * Formats the suggested grouping for an inline class string as `arrange group` output lines.
5
5
  *
@@ -0,0 +1,7 @@
1
+ import type { AnalyzeReport } from "#arrange/domain/types";
2
+ /**
3
+ * Machine-readable `arrange inspect` report for `--json`.
4
+ *
5
+ * @since 0.11.0
6
+ */
7
+ export declare function formatArrangeAnalyzeJsonOutput(analyzeRootPath: string, report: AnalyzeReport): string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Machine-readable `arrange inspect` report for `--json`.
3
+ *
4
+ * @since 0.11.0
5
+ */
6
+ export function formatArrangeAnalyzeJsonOutput(analyzeRootPath, report) {
7
+ return JSON.stringify({ schemaVersion: 1, analyzeRootPath, report });
8
+ }
@@ -0,0 +1,15 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * The request payload for `arrange inspect`.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export type ArrangeAnalyzeDirectoryRequest = {
8
+ analyzeRootPath: string;
9
+ };
10
+ /**
11
+ * The `zod` schema validating an `arrange inspect` request.
12
+ *
13
+ * @since 0.3.16-canary.0
14
+ */
15
+ export declare const arrangeAnalyzeDirectoryRequestSchema: z.ZodType<ArrangeAnalyzeDirectoryRequest>;
@@ -0,0 +1,9 @@
1
+ import * as z from "zod";
2
+ /**
3
+ * The `zod` schema validating an `arrange inspect` request.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export const arrangeAnalyzeDirectoryRequestSchema = z.object({
8
+ analyzeRootPath: z.string().min(1, "analyzeRootPath is required"),
9
+ });
@@ -2,8 +2,8 @@
2
2
  * Rich domain: Tailwind/cn/tv analysis rules (counts, long literals, nested cn in tv).
3
3
  * Pure orchestration of domain collectors and invariants — no I/O.
4
4
  */
5
- import type { DomainSourceFile } from "#/arrange/domain/ast/ast-node";
6
- import type { AnalyzeReport } from "#/arrange/domain/types";
5
+ import type { DomainSourceFile } from "#arrange/domain/ast/ast-node";
6
+ import type { AnalyzeReport } from "#arrange/domain/types";
7
7
  /**
8
8
  * Creates a zeroed analyze report ready for accumulation.
9
9
  *
@@ -2,13 +2,13 @@
2
2
  * Rich domain: Tailwind/cn/tv analysis rules (counts, long literals, nested cn in tv).
3
3
  * Pure orchestration of domain collectors and invariants — no I/O.
4
4
  */
5
- import { isDomainCallExpression, isDomainJsxAttribute, isDomainObjectLiteralExpression, forEachDomainChild, } from "#/arrange/domain/ast/ast-node";
6
- import { forEachStringLiteralInClassExpression } from "#/arrange/domain/ast/collectors-cn";
7
- import { jsxClassNameStaticLiteral } from "#/arrange/domain/ast/collectors-jsx";
8
- import { collectCnCallsInsideTv, traverseTvObject } from "#/arrange/domain/ast/collectors-tv";
9
- import { buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf } from "#/arrange/domain/ast/helpers";
10
- import { LONG_STRING_TOKEN_THRESHOLD } from "#/arrange/domain/constants";
11
- import { tokenizeClassString } from "#/arrange/domain/tailwind-token";
5
+ import { isDomainCallExpression, isDomainJsxAttribute, isDomainObjectLiteralExpression, forEachDomainChild, } from "#arrange/domain/ast/ast-node";
6
+ import { forEachStringLiteralInClassExpression } from "#arrange/domain/ast/collectors-cn";
7
+ import { jsxClassNameStaticLiteral } from "#arrange/domain/ast/collectors-jsx";
8
+ import { collectCnCallsInsideTv, traverseTvObject } from "#arrange/domain/ast/collectors-tv";
9
+ import { buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf } from "#arrange/domain/ast/helpers";
10
+ import { LONG_STRING_TOKEN_THRESHOLD } from "#arrange/domain/constants";
11
+ import { tokenizeClassString } from "#arrange/domain/tailwind-token";
12
12
  const PREVIEW_MAX_LENGTH = 72;
13
13
  function previewText(text) {
14
14
  return text.length > PREVIEW_MAX_LENGTH ? `${text.slice(0, PREVIEW_MAX_LENGTH)}…` : text;
@@ -0,0 +1,7 @@
1
+ import type { AnalyzeReport } from "#arrange/domain/types";
2
+ /**
3
+ * Presents the human-readable summary of an `arrange inspect` report.
4
+ *
5
+ * @since 0.3.16-canary.0
6
+ */
7
+ export declare function presentAnalyzeReport(resolvedTargetPath: string, report: AnalyzeReport): void;
@@ -0,0 +1,42 @@
1
+ import path from "node:path";
2
+ import { LONG_STRING_TOKEN_THRESHOLD, MAX_REPORT_LINES } from "#arrange/domain/constants";
3
+ import { logger } from "#core/logger";
4
+ /**
5
+ * Presents the human-readable summary of an `arrange inspect` report.
6
+ *
7
+ * @since 0.3.16-canary.0
8
+ */
9
+ export function presentAnalyzeReport(resolvedTargetPath, report) {
10
+ logger.out(`Path: ${path.resolve(resolvedTargetPath)}`);
11
+ logger.out(`.ts/.tsx files: ${report.files}`);
12
+ logger.out(`cn(...) call sites: ${report.cnCallExpressions}`);
13
+ logger.out(`tv(...) call sites: ${report.tvCallExpressions}`);
14
+ logger.out(`\nLong cn(...) string literals (≥${LONG_STRING_TOKEN_THRESHOLD} tokens — consider splitting arguments): ${report.longCnStringLiterals.length}`);
15
+ for (const findingEntry of report.longCnStringLiterals.slice(0, MAX_REPORT_LINES)) {
16
+ logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
17
+ }
18
+ if (report.longCnStringLiterals.length > MAX_REPORT_LINES) {
19
+ logger.out(` … and ${report.longCnStringLiterals.length - MAX_REPORT_LINES} more`);
20
+ }
21
+ logger.out(`\nLong tv({...}) string literals in base/variants/… (≥${LONG_STRING_TOKEN_THRESHOLD} tokens): ${report.longTvStringLiterals.length}`);
22
+ for (const findingEntry of report.longTvStringLiterals.slice(0, MAX_REPORT_LINES)) {
23
+ logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
24
+ }
25
+ if (report.longTvStringLiterals.length > MAX_REPORT_LINES) {
26
+ logger.out(` … and ${report.longTvStringLiterals.length - MAX_REPORT_LINES} more`);
27
+ }
28
+ logger.out(`\nJSX className="..." or className={'...'} (static strings, ≥${LONG_STRING_TOKEN_THRESHOLD} tokens): ${report.longJsxClassNameLiterals.length}`);
29
+ for (const findingEntry of report.longJsxClassNameLiterals.slice(0, MAX_REPORT_LINES)) {
30
+ logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.tokenCount} tokens) ${findingEntry.preview}`);
31
+ }
32
+ if (report.longJsxClassNameLiterals.length > MAX_REPORT_LINES) {
33
+ logger.out(` … and ${report.longJsxClassNameLiterals.length - MAX_REPORT_LINES} more`);
34
+ }
35
+ logger.out(`\ncn(...) nested inside tv({...}) (prefer a string or array — preview/apply can rewrite): ${report.cnInsideTvCalls.length}`);
36
+ for (const findingEntry of report.cnInsideTvCalls.slice(0, MAX_REPORT_LINES)) {
37
+ logger.out(` ${findingEntry.file}:${findingEntry.line} (${findingEntry.argCount} args) ${findingEntry.preview}`);
38
+ }
39
+ if (report.cnInsideTvCalls.length > MAX_REPORT_LINES) {
40
+ logger.out(` … and ${report.cnInsideTvCalls.length - MAX_REPORT_LINES} more`);
41
+ }
42
+ }
@@ -0,0 +1,10 @@
1
+ import type { AnalyzeReport } from "#arrange/domain/types";
2
+ import { AppError } from "#core/errors";
3
+ import type { Filesystem } from "#core/filesystem/filesystem";
4
+ import type { Result } from "#core/result";
5
+ /**
6
+ * Scans a directory's arrange targets and returns the accumulated analyze report.
7
+ *
8
+ * @since 0.3.16-canary.0
9
+ */
10
+ export declare function runArrangeInspect(fs: Filesystem, analyzeRootPath: string): Result<AnalyzeReport, AppError>;
@@ -1,15 +1,15 @@
1
- import { accumulateAnalyzeReportForSourceFile, createEmptyAnalyzeReport } from "#/arrange/domain/analyze-service";
2
- import { scanArrangeTargets } from "#/arrange/scan-target";
3
- import { parseDomainSourceFile } from "#/arrange/source-parse";
4
- import { AppError } from "#/core/errors";
5
- import { messageFrom } from "#/core/errors";
6
- import { err, ok } from "#/core/result";
1
+ import { accumulateAnalyzeReportForSourceFile, createEmptyAnalyzeReport, } from "#arrange/inspect/domain/analyze-service";
2
+ import { scanArrangeTargets } from "#arrange/scan-target";
3
+ import { parseDomainSourceFile } from "#arrange/source-parse";
4
+ import { AppError } from "#core/errors";
5
+ import { messageFrom } from "#core/errors";
6
+ import { err, ok } from "#core/result";
7
7
  /**
8
8
  * Scans a directory's arrange targets and returns the accumulated analyze report.
9
9
  *
10
10
  * @since 0.3.16-canary.0
11
11
  */
12
- export function analyzeDirectory(fs, analyzeRootPath) {
12
+ export function runArrangeInspect(fs, analyzeRootPath) {
13
13
  const report = createEmptyAnalyzeReport();
14
14
  try {
15
15
  const files = scanArrangeTargets(fs, analyzeRootPath);
@@ -0,0 +1,13 @@
1
+ import type { ArrangeTargetWorkspaceAndConfig } from "#arrange/domain/types";
2
+ import { AppError } from "#core/errors";
3
+ import type { Filesystem } from "#core/filesystem/filesystem";
4
+ import type { Result } from "#core/result";
5
+ /**
6
+ * Resolves the arrange target, repo root, and loaded config an arrange run needs.
7
+ *
8
+ * @since 0.3.16-canary.0
9
+ */
10
+ export declare function prepareArrangeWorkspace(fs: Filesystem, args: {
11
+ readonly currentWorkingDirectory: string;
12
+ readonly rawTarget: string | undefined;
13
+ }): Promise<Result<ArrangeTargetWorkspaceAndConfig, AppError>>;