@codefast/cli 0.3.15 → 0.3.16-canary.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 (209) hide show
  1. package/README.md +1 -1
  2. package/dist/arrange/analyze.mjs +24 -0
  3. package/dist/{domains/arrange/presentation/presenters/arrange-cli.schema.mjs → arrange/cli-schema.mjs} +10 -1
  4. package/dist/arrange/command.mjs +106 -0
  5. package/dist/{domains/arrange/domain/arrange-analyze.domain-service.mjs → arrange/domain/analyze-service.mjs} +17 -10
  6. package/dist/{domains/arrange/domain/ast/ast-node.model.mjs → arrange/domain/ast/ast-node.mjs} +57 -3
  7. package/dist/{domains/arrange/domain/ast/collectors-cn.collector.mjs → arrange/domain/ast/collectors-cn.mjs} +21 -9
  8. package/dist/{domains/arrange/domain/ast/collectors-jsx.collector.mjs → arrange/domain/ast/collectors-jsx.mjs} +5 -2
  9. package/dist/{domains/arrange/domain/ast/collectors-tv.collector.mjs → arrange/domain/ast/collectors-tv.mjs} +21 -6
  10. package/dist/{domains/arrange/domain/ast/ast-helpers.helper.mjs → arrange/domain/ast/helpers.mjs} +26 -9
  11. package/dist/{domains/arrange/domain/ast/targets.model.mjs → arrange/domain/ast/targets.mjs} +19 -10
  12. package/dist/{domains/arrange/domain/constants.domain.mjs → arrange/domain/constants.mjs} +63 -18
  13. package/dist/{domains/arrange/domain/arrange-grouping.domain-service.mjs → arrange/domain/grouping-service.mjs} +31 -10
  14. package/dist/{domains/arrange/domain/grouping.domain.mjs → arrange/domain/grouping.mjs} +39 -18
  15. package/dist/{domains/arrange/domain/imports.domain.mjs → arrange/domain/imports.mjs} +7 -3
  16. package/dist/{domains/arrange/domain/source-text-formatters.formatter.mjs → arrange/domain/source-text-formatters.mjs} +22 -5
  17. package/dist/{domains/arrange/domain/tailwind-token.value-object.mjs → arrange/domain/tailwind-token.mjs} +12 -3
  18. package/dist/{domains/arrange/domain/tailwind-token-classifier.domain-service.mjs → arrange/domain/token-classifier.mjs} +40 -15
  19. package/dist/arrange/output.mjs +79 -0
  20. package/dist/arrange/process-file.mjs +42 -0
  21. package/dist/arrange/resolve-target.mjs +24 -0
  22. package/dist/arrange/scan-target.mjs +20 -0
  23. package/dist/arrange/source-parse.mjs +18 -0
  24. package/dist/arrange/suggest.mjs +15 -0
  25. package/dist/arrange/sync.mjs +51 -0
  26. package/dist/arrange/typescript-ast-translator.mjs +354 -0
  27. package/dist/arrange/workspace.mjs +31 -0
  28. package/dist/bin.mjs +1 -1
  29. package/dist/{program.mjs → cli.mjs} +14 -20
  30. package/dist/core/cli/format-error.mjs +15 -0
  31. package/dist/core/cli/global-options.mjs +10 -0
  32. package/dist/core/cli/positional.mjs +11 -0
  33. package/dist/core/cli/result-handle.mjs +51 -0
  34. package/dist/core/config/loader.mjs +79 -0
  35. package/dist/{domains/config/domain/codefast-config.schema.mjs → core/config/schema.mjs} +16 -2
  36. package/dist/core/config/warnings.mjs +12 -0
  37. package/dist/core/config.mjs +19 -0
  38. package/dist/{shell/domain/caught-unknown-message.value-object.mjs → core/errors.mjs} +20 -4
  39. package/dist/core/exit-codes.mjs +17 -0
  40. package/dist/core/filesystem/node.mjs +32 -0
  41. package/dist/core/logger.mjs +15 -0
  42. package/dist/{shell/domain/result.model.mjs → core/result.mjs} +7 -3
  43. package/dist/core/schema-parse.mjs +18 -0
  44. package/dist/{shell/domain/source-text-edit.support.mjs → core/source-text-edit.mjs} +14 -13
  45. package/dist/core/verbose-diagnostics.mjs +11 -0
  46. package/dist/core/workspace/resolver.mjs +177 -0
  47. package/dist/core/workspace/typescript-walk.mjs +36 -0
  48. package/dist/{domains/mirror/application/mirror-sync-cli-result.mjs → mirror/cli-result.mjs} +8 -2
  49. package/dist/{domains/mirror/presentation/presenters/mirror-cli.schema.mjs → mirror/cli-schema.mjs} +4 -1
  50. package/dist/mirror/command.mjs +57 -0
  51. package/dist/mirror/dist-filesystem-impl.mjs +42 -0
  52. package/dist/{domains/mirror/domain/constants.domain.mjs → mirror/domain/constants.mjs} +16 -1
  53. package/dist/{domains/mirror/infrastructure/guards/dirent-list.guard.mjs → mirror/domain/dirent-guard.mjs} +5 -2
  54. package/dist/{domains/mirror/domain/errors.domain.mjs → mirror/domain/errors.mjs} +7 -1
  55. package/dist/{domains/mirror/domain/generate-mirror-exports.domain-service.mjs → mirror/domain/exports.mjs} +17 -10
  56. package/dist/{domains/mirror/domain/package-display-name.policy.mjs → mirror/domain/package-display-name.mjs} +5 -2
  57. package/dist/{domains/mirror/domain/path-normalizer.value-object.mjs → mirror/domain/path-normalizer.mjs} +4 -1
  58. package/dist/mirror/output.mjs +45 -0
  59. package/dist/mirror/package-path.mjs +32 -0
  60. package/dist/mirror/prepare.mjs +33 -0
  61. package/dist/mirror/sync-reporter.mjs +104 -0
  62. package/dist/mirror/sync-workspace-package.mjs +103 -0
  63. package/dist/mirror/sync.mjs +87 -0
  64. package/dist/{domains/mirror/infrastructure/package-json-exports.repository.mjs → mirror/write-exports.mjs} +11 -7
  65. package/dist/tag/cli-result.mjs +11 -0
  66. package/dist/{domains/tag/presentation/presenters/tag-cli.schema.mjs → tag/cli-schema.mjs} +4 -1
  67. package/dist/tag/command.mjs +56 -0
  68. package/dist/tag/output.mjs +87 -0
  69. package/dist/tag/prepare.mjs +29 -0
  70. package/dist/tag/resolve-target-path.mjs +12 -0
  71. package/dist/tag/since-writer.mjs +130 -0
  72. package/dist/tag/sync.mjs +141 -0
  73. package/dist/tag/target-candidates.mjs +68 -0
  74. package/dist/tag/target-runner.mjs +26 -0
  75. package/dist/tag/version-resolver.mjs +25 -0
  76. package/package.json +4 -7
  77. package/dist/bootstrap/cli-application.module.mjs +0 -18
  78. package/dist/bootstrap/composition-root.mjs +0 -14
  79. package/dist/bootstrap/register-cli-command-trees.mjs +0 -7
  80. package/dist/domains/arrange/application/ports/outbound/arrange-target-scanner.port.mjs +0 -1
  81. package/dist/domains/arrange/application/ports/outbound/domain-source-parser.port.mjs +0 -1
  82. package/dist/domains/arrange/application/ports/outbound/file-walker.port.mjs +0 -1
  83. package/dist/domains/arrange/application/ports/presenting/present-analyze-report.presenter.mjs +0 -1
  84. package/dist/domains/arrange/application/ports/presenting/present-arrange-sync-result.presenter.mjs +0 -1
  85. package/dist/domains/arrange/application/ports/presenting/present-group-file-preview.presenter.mjs +0 -1
  86. package/dist/domains/arrange/application/requests/analyze-directory.request.mjs +0 -1
  87. package/dist/domains/arrange/application/requests/arrange-sync.request.mjs +0 -1
  88. package/dist/domains/arrange/application/requests/suggest-groups.request.mjs +0 -1
  89. package/dist/domains/arrange/application/use-cases/analyze-directory.use-case.mjs +0 -255
  90. package/dist/domains/arrange/application/use-cases/prepare-arrange-workspace.use-case.mjs +0 -264
  91. package/dist/domains/arrange/application/use-cases/run-arrange-sync.use-case.mjs +0 -274
  92. package/dist/domains/arrange/application/use-cases/suggest-cn-groups.use-case.mjs +0 -237
  93. package/dist/domains/arrange/arrange.module.mjs +0 -38
  94. package/dist/domains/arrange/composition/tokens.mjs +0 -17
  95. package/dist/domains/arrange/contracts/models.mjs +0 -1
  96. package/dist/domains/arrange/domain/tailwind-grouping.domain-service.mjs +0 -231
  97. package/dist/domains/arrange/domain/types.domain.mjs +0 -1
  98. package/dist/domains/arrange/infrastructure/adapters/arrange-file-processor.adapter.mjs +0 -267
  99. package/dist/domains/arrange/infrastructure/adapters/arrange-target-path-resolver.adapter.mjs +0 -247
  100. package/dist/domains/arrange/infrastructure/adapters/arrange-target-scanner.adapter.mjs +0 -243
  101. package/dist/domains/arrange/infrastructure/adapters/domain-source-parser.adapter.mjs +0 -241
  102. package/dist/domains/arrange/infrastructure/adapters/file-walker.adapter.mjs +0 -240
  103. package/dist/domains/arrange/infrastructure/typescript-ast-translator.mjs +0 -580
  104. package/dist/domains/arrange/presentation/cli/arrange.command.mjs +0 -465
  105. package/dist/domains/arrange/presentation/presenters/arrange-analyze.presenter.mjs +0 -252
  106. package/dist/domains/arrange/presentation/presenters/arrange-sync.presenter.mjs +0 -236
  107. package/dist/domains/arrange/presentation/presenters/group-file-preview.presenter.mjs +0 -271
  108. package/dist/domains/config/application/ports/outbound/codefast-config-schema.port.mjs +0 -1
  109. package/dist/domains/config/application/ports/outbound/config-loader.port.mjs +0 -1
  110. package/dist/domains/config/application/ports/outbound/config-warning-reporter.port.mjs +0 -1
  111. package/dist/domains/config/composition/tokens.mjs +0 -7
  112. package/dist/domains/config/domain/schema.domain.mjs +0 -1
  113. package/dist/domains/config/infrastructure/adapters/config-loader.adapter.mjs +0 -305
  114. package/dist/domains/config/infrastructure/adapters/config-warning-reporter.adapter.mjs +0 -234
  115. package/dist/domains/config/infrastructure/adapters/zod-codefast-config-schema.adapter.mjs +0 -236
  116. package/dist/domains/mirror/application/ports/inbound/prepare-mirror-sync.port.mjs +0 -1
  117. package/dist/domains/mirror/application/ports/inbound/run-mirror-sync.port.mjs +0 -1
  118. package/dist/domains/mirror/application/ports/outbound/file-system-service.port.mjs +0 -1
  119. package/dist/domains/mirror/application/ports/outbound/mirror-package-path.port.mjs +0 -1
  120. package/dist/domains/mirror/application/ports/outbound/mirror-sync-reporter.port.mjs +0 -1
  121. package/dist/domains/mirror/application/ports/outbound/package-repository.port.mjs +0 -1
  122. package/dist/domains/mirror/application/ports/outbound/sync-workspace-package.port.mjs +0 -1
  123. package/dist/domains/mirror/application/ports/presenting/present-mirror-sync-progress.presenter.mjs +0 -1
  124. package/dist/domains/mirror/application/requests/mirror-sync-execution-input.mjs +0 -1
  125. package/dist/domains/mirror/application/requests/mirror-sync.request.mjs +0 -1
  126. package/dist/domains/mirror/application/use-cases/prepare-mirror-sync.use-case.mjs +0 -263
  127. package/dist/domains/mirror/application/use-cases/run-mirror-sync.use-case.mjs +0 -317
  128. package/dist/domains/mirror/composition/tokens.mjs +0 -12
  129. package/dist/domains/mirror/contracts/models.mjs +0 -1
  130. package/dist/domains/mirror/domain/types.domain.mjs +0 -1
  131. package/dist/domains/mirror/infrastructure/adapters/file-system-service.adapter.mjs +0 -261
  132. package/dist/domains/mirror/infrastructure/adapters/mirror-package-path-resolver.adapter.mjs +0 -252
  133. package/dist/domains/mirror/infrastructure/adapters/mirror-sync-reporter.adapter.mjs +0 -322
  134. package/dist/domains/mirror/infrastructure/adapters/package-repository.adapter.mjs +0 -241
  135. package/dist/domains/mirror/infrastructure/adapters/sync-workspace-package.adapter.mjs +0 -328
  136. package/dist/domains/mirror/mirror.module.mjs +0 -26
  137. package/dist/domains/mirror/presentation/cli/mirror.command.mjs +0 -328
  138. package/dist/domains/mirror/presentation/presenters/present-mirror-sync-progress.presenter.mjs +0 -265
  139. package/dist/domains/tag/application/ports/inbound/prepare-tag-sync.port.mjs +0 -1
  140. package/dist/domains/tag/application/ports/inbound/run-tag-sync.port.mjs +0 -1
  141. package/dist/domains/tag/application/ports/outbound/tag-eligible-workspace-paths.port.mjs +0 -1
  142. package/dist/domains/tag/application/ports/outbound/tag-since-writer.port.mjs +0 -1
  143. package/dist/domains/tag/application/ports/outbound/tag-target-path-resolver.port.mjs +0 -1
  144. package/dist/domains/tag/application/ports/outbound/tag-target-runner.port.mjs +0 -1
  145. package/dist/domains/tag/application/ports/outbound/tag-version-resolver.port.mjs +0 -1
  146. package/dist/domains/tag/application/ports/presenting/present-tag-sync-progress.presenter.mjs +0 -1
  147. package/dist/domains/tag/application/ports/presenting/present-tag-sync-result.presenter.mjs +0 -1
  148. package/dist/domains/tag/application/requests/tag-sync-execution-input.mjs +0 -1
  149. package/dist/domains/tag/application/requests/tag-sync.request.mjs +0 -1
  150. package/dist/domains/tag/application/tag-sync-cli-result.mjs +0 -11
  151. package/dist/domains/tag/application/use-cases/prepare-tag-sync.use-case.mjs +0 -260
  152. package/dist/domains/tag/application/use-cases/run-tag-sync.use-case.mjs +0 -375
  153. package/dist/domains/tag/composition/tokens.mjs +0 -13
  154. package/dist/domains/tag/contracts/models.mjs +0 -1
  155. package/dist/domains/tag/domain/types.domain.mjs +0 -1
  156. package/dist/domains/tag/infrastructure/adapters/tag-since-writer.adapter.mjs +0 -348
  157. package/dist/domains/tag/infrastructure/adapters/tag-target-path-resolver.adapter.mjs +0 -235
  158. package/dist/domains/tag/infrastructure/adapters/tag-target-resolver.adapter.mjs +0 -302
  159. package/dist/domains/tag/infrastructure/adapters/tag-target-runner.adapter.mjs +0 -259
  160. package/dist/domains/tag/infrastructure/adapters/tag-version-resolver.adapter.mjs +0 -249
  161. package/dist/domains/tag/presentation/cli/tag.command.mjs +0 -325
  162. package/dist/domains/tag/presentation/presenters/present-tag-sync-progress.presenter.mjs +0 -248
  163. package/dist/domains/tag/presentation/presenters/present-tag-sync-result.presenter.mjs +0 -290
  164. package/dist/domains/tag/tag.module.mjs +0 -28
  165. package/dist/shell/application/cli-runtime.tokens.mjs +0 -18
  166. package/dist/shell/application/coordination/cli-executor.coordination.mjs +0 -1
  167. package/dist/shell/application/coordination/cli-schema-parsing.coordination.mjs +0 -1
  168. package/dist/shell/application/global-cli-options.model.mjs +0 -5
  169. package/dist/shell/application/ports/inbound/load-codefast-config.port.mjs +0 -1
  170. package/dist/shell/application/ports/outbound/cli-fs.port.mjs +0 -1
  171. package/dist/shell/application/ports/outbound/cli-logger.port.mjs +0 -1
  172. package/dist/shell/application/ports/outbound/cli-path.port.mjs +0 -1
  173. package/dist/shell/application/ports/outbound/cli-runtime.port.mjs +0 -1
  174. package/dist/shell/application/ports/outbound/cli-telemetry.port.mjs +0 -1
  175. package/dist/shell/application/ports/outbound/cli-verbose-diagnostics.port.mjs +0 -1
  176. package/dist/shell/application/ports/outbound/format-app-error.port.mjs +0 -1
  177. package/dist/shell/application/ports/outbound/global-cli-options-parse.port.mjs +0 -1
  178. package/dist/shell/application/ports/outbound/repo-root-resolver.port.mjs +0 -1
  179. package/dist/shell/application/ports/outbound/typescript-source-file-walker.port.mjs +0 -1
  180. package/dist/shell/application/ports/outbound/workspace-package-layout.port.mjs +0 -1
  181. package/dist/shell/application/ports/primary/command.port.mjs +0 -1
  182. package/dist/shell/application/services/cli-executor.service.mjs +0 -267
  183. package/dist/shell/application/services/schema-validator.service.mjs +0 -236
  184. package/dist/shell/application/use-cases/load-codefast-config.use-case.mjs +0 -243
  185. package/dist/shell/composition/tokens.mjs +0 -5
  186. package/dist/shell/contracts/cli-command-slots.mjs +0 -11
  187. package/dist/shell/domain/cli-exit-codes.domain.mjs +0 -11
  188. package/dist/shell/domain/cli-positional-arg.value-object.mjs +0 -6
  189. package/dist/shell/domain/errors.domain.mjs +0 -17
  190. package/dist/shell/infrastructure/adapters/cli-verbose-diagnostics.adapter.mjs +0 -228
  191. package/dist/shell/infrastructure/adapters/format-app-error.adapter.mjs +0 -236
  192. package/dist/shell/infrastructure/adapters/global-cli-options-parser.adapter.mjs +0 -233
  193. package/dist/shell/infrastructure/adapters/repo-root-resolver.adapter.mjs +0 -244
  194. package/dist/shell/infrastructure/adapters/typescript-source-file-walker.adapter.mjs +0 -259
  195. package/dist/shell/infrastructure/commander/commander-cli-host.adapter.mjs +0 -69
  196. package/dist/shell/infrastructure/node/node-cli-fs.adapter.mjs +0 -249
  197. package/dist/shell/infrastructure/node/node-cli-logger.adapter.mjs +0 -231
  198. package/dist/shell/infrastructure/node/node-cli-path.adapter.mjs +0 -246
  199. package/dist/shell/infrastructure/node/node-cli-runtime.adapter.mjs +0 -234
  200. package/dist/shell/infrastructure/telemetry/cli-telemetry.adapter.mjs +0 -280
  201. package/dist/shell/infrastructure/workspace/node-pnpm-workspace-package-layout.adapter.mjs +0 -385
  202. package/dist/shell/shell.module.mjs +0 -43
  203. package/dist/shell/wiring/optional-cli-port-telemetry-activation.mjs +0 -13
  204. /package/dist/{domains/arrange/application/ports/inbound/analyze-directory.port.mjs → arrange/domain/types.mjs} +0 -0
  205. /package/dist/{domains/arrange/application/ports/inbound/prepare-arrange-workspace.port.mjs → core/filesystem/port.mjs} +0 -0
  206. /package/dist/{domains/arrange/application/ports/inbound/run-arrange-sync.port.mjs → mirror/domain/dist-filesystem.mjs} +0 -0
  207. /package/dist/{domains/arrange/application/ports/inbound/suggest-cn-groups.port.mjs → mirror/domain/types.mjs} +0 -0
  208. /package/dist/{domains/arrange/application/ports/outbound/arrange-file-processor.port.mjs → mirror/sync-types.mjs} +0 -0
  209. /package/dist/{domains/arrange/application/ports/outbound/arrange-target-path-resolver.port.mjs → tag/domain/types.mjs} +0 -0
package/README.md CHANGED
@@ -339,7 +339,7 @@ Contract:
339
339
 
340
340
  Adjacent buckets may be merged into a single string literal when declared _compatible_ (e.g. Layout + Sizing), which keeps `cn()` calls readable without flattening unrelated concerns.
341
341
 
342
- To change placement, extend `classifyBareUtility` in `src/domains/arrange/domain/tailwind-token-classifier.domain-service.ts` (and cover the new rule with arrange tests if you introduce a new bucket).
342
+ To change placement, extend `classifyBareUtility` in `packages/cli/src/arrange/domain/token-classifier.ts` (and cover the new rule with arrange tests if you introduce a new bucket).
343
343
 
344
344
  ---
345
345
 
@@ -0,0 +1,24 @@
1
+ import { AppError, messageFrom } from "../core/errors.mjs";
2
+ import { err, ok } from "../core/result.mjs";
3
+ import { accumulateAnalyzeReportForSourceFile, createEmptyAnalyzeReport } from "./domain/analyze-service.mjs";
4
+ import { scanArrangeTargets } from "./scan-target.mjs";
5
+ import { parseDomainSourceFile } from "./source-parse.mjs";
6
+ //#region src/arrange/analyze.ts
7
+ /**
8
+ * @since 0.3.16-canary.0
9
+ */
10
+ function analyzeDirectory(fs, analyzeRootPath) {
11
+ const report = createEmptyAnalyzeReport();
12
+ try {
13
+ const files = scanArrangeTargets(fs, analyzeRootPath);
14
+ for (const filePath of files) {
15
+ const sourceText = fs.readFileSync(filePath, "utf8");
16
+ accumulateAnalyzeReportForSourceFile(report, parseDomainSourceFile(filePath, sourceText), sourceText, filePath);
17
+ }
18
+ return ok(report);
19
+ } catch (caughtError) {
20
+ return err(new AppError("INFRA_FAILURE", messageFrom(caughtError), caughtError));
21
+ }
22
+ }
23
+ //#endregion
24
+ export { analyzeDirectory };
@@ -1,6 +1,12 @@
1
1
  import { z } from "zod";
2
- //#region src/domains/arrange/presentation/presenters/arrange-cli.schema.ts
2
+ //#region src/arrange/cli-schema.ts
3
+ /**
4
+ * @since 0.3.16-canary.0
5
+ */
3
6
  const arrangeAnalyzeDirectoryRequestSchema = z.object({ analyzeRootPath: z.string().min(1, "analyzeRootPath is required") });
7
+ /**
8
+ * @since 0.3.16-canary.0
9
+ */
4
10
  const arrangeSyncRunRequestSchema = z.object({
5
11
  rootDir: z.string().min(1),
6
12
  targetPath: z.string().min(1),
@@ -9,6 +15,9 @@ const arrangeSyncRunRequestSchema = z.object({
9
15
  cnImport: z.string().optional(),
10
16
  config: z.unknown().optional()
11
17
  });
18
+ /**
19
+ * @since 0.3.16-canary.0
20
+ */
12
21
  const arrangeSuggestGroupsRequestSchema = z.object({
13
22
  inlineClasses: z.string().min(1, "Pass a class string. Example: codefast arrange group \"flex gap-2 text-sm rounded-md\""),
14
23
  emitTvStyleArray: z.boolean(),
@@ -0,0 +1,106 @@
1
+ import { parseWithSchema } from "../core/schema-parse.mjs";
2
+ import "../core/exit-codes.mjs";
3
+ import { logger } from "../core/logger.mjs";
4
+ import { consumeCliAppError, runCliResultAsync } from "../core/cli/result-handle.mjs";
5
+ import { nodeFilesystem } from "../core/filesystem/node.mjs";
6
+ import { arrangeAnalyzeDirectoryRequestSchema, arrangeSuggestGroupsRequestSchema, arrangeSyncRunRequestSchema } from "./cli-schema.mjs";
7
+ import { prepareArrangeWorkspace } from "./workspace.mjs";
8
+ import { analyzeDirectory } from "./analyze.mjs";
9
+ import { runArrangeSync } from "./sync.mjs";
10
+ import { suggestCnGroupsFromCli } from "./suggest.mjs";
11
+ import { printAnalyzeReport, printGroupFilePreviewFromWork, printSyncResult } from "./output.mjs";
12
+ import { readOptionalPositionalArg } from "../core/cli/positional.mjs";
13
+ import process from "node:process";
14
+ import { Command } from "commander";
15
+ //#region src/arrange/command.ts
16
+ /**
17
+ * @since 0.3.16-canary.0
18
+ */
19
+ function createArrangeCommand() {
20
+ const cmd = new Command("arrange").description("Analyze and regroup Tailwind classes in cn() / tv() calls (Tailwind v4)");
21
+ cmd.command("analyze").description("Report long strings, nested cn in tv(), and related findings").argument("[target]", "Directory or file (default: nearest package directory from cwd)").option("--json", "Print one JSON object on stdout instead of a human report", false).action(async (target, opts) => {
22
+ const prelude = await prepareArrangeWorkspace(nodeFilesystem, {
23
+ currentWorkingDirectory: process.cwd(),
24
+ rawTarget: readOptionalPositionalArg(target)
25
+ });
26
+ if (!consumeCliAppError(prelude)) return;
27
+ const { resolvedTarget } = prelude.value;
28
+ const parsed = parseWithSchema(arrangeAnalyzeDirectoryRequestSchema, { analyzeRootPath: resolvedTarget });
29
+ if (!consumeCliAppError(parsed)) return;
30
+ const outcome = analyzeDirectory(nodeFilesystem, parsed.value.analyzeRootPath);
31
+ if (!consumeCliAppError(outcome)) return;
32
+ if (opts.json) logger.out(formatArrangeAnalyzeJsonOutput(resolvedTarget, outcome.value));
33
+ else printAnalyzeReport(resolvedTarget, outcome.value);
34
+ });
35
+ const previewOrApply = (write) => async (target, opts) => {
36
+ const prelude = await prepareArrangeWorkspace(nodeFilesystem, {
37
+ currentWorkingDirectory: process.cwd(),
38
+ rawTarget: readOptionalPositionalArg(target)
39
+ });
40
+ if (!consumeCliAppError(prelude)) return;
41
+ const { resolvedTarget, rootDir, config } = prelude.value;
42
+ const parsed = parseWithSchema(arrangeSyncRunRequestSchema, {
43
+ rootDir,
44
+ targetPath: resolvedTarget,
45
+ write,
46
+ withClassName: opts.withClassName,
47
+ cnImport: opts.cnImport,
48
+ config: config.arrange ?? {}
49
+ });
50
+ if (!consumeCliAppError(parsed)) return;
51
+ await runCliResultAsync(runArrangeSync(nodeFilesystem, parsed.value), (value) => {
52
+ if (!write) for (const plan of value.previewPlans) printGroupFilePreviewFromWork(plan);
53
+ if (opts.json) {
54
+ logger.out(formatArrangeSyncJsonOutput(value, write));
55
+ return exitCodeForArrangeSyncResult(value);
56
+ }
57
+ printSyncResult(value, write);
58
+ return exitCodeForArrangeSyncResult(value);
59
+ });
60
+ };
61
+ cmd.command("preview").description("Dry-run: print suggested replacements without writing files").argument("[target]", "Directory or file (default: nearest package directory from cwd)").option("--with-classname, --with-class-name", "Append className as final cn() argument", false).option("--cn-import <spec>", "Override module specifier when adding cn import").option("--json", "Print one JSON object on stdout (suppresses human progress)", false).action(previewOrApply(false));
62
+ cmd.command("apply").description("Apply grouping and cn-in-tv unwrap edits to files").argument("[target]", "Directory or file (default: nearest package directory from cwd)").option("--with-classname, --with-class-name", "Append className as final cn() argument", false).option("--cn-import <spec>", "Override module specifier when adding cn import").option("--json", "Print one JSON object on stdout (suppresses human progress)", false).action(previewOrApply(true));
63
+ cmd.command("group").description("Try grouping on a pasted class string (stdout: cn(...) or tv array with --tv)").argument("<tokens...>", "Class tokens (quote a single string if it contains spaces)").option("--tv", "Emit tv()-style array instead of cn() call", false).option("--with-classname, --with-class-name", "Append className as final cn() argument", false).option("--json", "Print one JSON object on stdout instead of plain lines", false).action(async (classTokenSeries, opts) => {
64
+ const parsed = parseWithSchema(arrangeSuggestGroupsRequestSchema, {
65
+ inlineClasses: classTokenSeries.join(" ").trim(),
66
+ emitTvStyleArray: !!opts.tv,
67
+ trailingClassName: !!opts.withClassName
68
+ });
69
+ if (!consumeCliAppError(parsed)) return;
70
+ const output = suggestCnGroupsFromCli(parsed.value);
71
+ if (opts.json) logger.out(formatArrangeGroupJsonOutput(output));
72
+ else {
73
+ logger.out(output.primaryLine);
74
+ logger.out(output.bucketsCommentLine);
75
+ }
76
+ });
77
+ return cmd;
78
+ }
79
+ function formatArrangeAnalyzeJsonOutput(analyzeRootPath, report) {
80
+ return JSON.stringify({
81
+ schemaVersion: 1,
82
+ analyzeRootPath,
83
+ report
84
+ });
85
+ }
86
+ function formatArrangeSyncJsonOutput(result, write) {
87
+ const { previewPlans: _plans, ...serializableResult } = result;
88
+ return JSON.stringify({
89
+ schemaVersion: 1,
90
+ ok: result.hookError === null,
91
+ write,
92
+ result: serializableResult
93
+ });
94
+ }
95
+ function formatArrangeGroupJsonOutput(output) {
96
+ return JSON.stringify({
97
+ schemaVersion: 1,
98
+ primaryLine: output.primaryLine,
99
+ bucketsCommentLine: output.bucketsCommentLine
100
+ });
101
+ }
102
+ function exitCodeForArrangeSyncResult(result) {
103
+ return result.hookError !== null ? 1 : 0;
104
+ }
105
+ //#endregion
106
+ export { createArrangeCommand };
@@ -1,18 +1,22 @@
1
- import "./constants.domain.mjs";
2
- import { forEachDomainChild, isDomainCallExpression, isDomainJsxAttribute, isDomainObjectLiteralExpression } from "./ast/ast-node.model.mjs";
3
- import { buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf } from "./ast/ast-helpers.helper.mjs";
4
- import { forEachStringLiteralInClassExpression } from "./ast/collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "./tailwind-token.value-object.mjs";
6
- import { collectCnCallsInsideTv, traverseTvObject } from "./ast/collectors-tv.collector.mjs";
7
- import { jsxClassNameStaticLiteral } from "./ast/collectors-jsx.collector.mjs";
8
- //#region src/domains/arrange/domain/arrange-analyze.domain-service.ts
1
+ import "./constants.mjs";
2
+ import { tokenizeClassString } from "./tailwind-token.mjs";
3
+ import { forEachDomainChild, isDomainCallExpression, isDomainJsxAttribute, isDomainObjectLiteralExpression } from "./ast/ast-node.mjs";
4
+ import { forEachStringLiteralInClassExpression } from "./ast/collectors-cn.mjs";
5
+ import { jsxClassNameStaticLiteral } from "./ast/collectors-jsx.mjs";
6
+ import { buildKnownCnTvBindings, isCnOrTvIdentifier, lineOf } from "./ast/helpers.mjs";
7
+ import { collectCnCallsInsideTv, traverseTvObject } from "./ast/collectors-tv.mjs";
8
+ //#region src/arrange/domain/analyze-service.ts
9
9
  /**
10
10
  * Rich domain: Tailwind/cn/tv analysis rules (counts, long literals, nested cn in tv).
11
11
  * Pure orchestration of domain collectors and invariants — no I/O.
12
- */ const PREVIEW_MAX_LENGTH = 72;
12
+ */
13
+ const PREVIEW_MAX_LENGTH = 72;
13
14
  function previewText(text) {
14
15
  return text.length > PREVIEW_MAX_LENGTH ? `${text.slice(0, PREVIEW_MAX_LENGTH)}…` : text;
15
16
  }
17
+ /**
18
+ * @since 0.3.16-canary.0
19
+ */
16
20
  function createEmptyAnalyzeReport() {
17
21
  return {
18
22
  files: 0,
@@ -81,7 +85,10 @@ function visitJsxAttributeForArrangeAnalyze(jsxClassAttribute, domainSf, filePat
81
85
  }
82
86
  /**
83
87
  * Accumulates findings for one parsed source file into `report` (mutates report).
84
- */ function accumulateAnalyzeReportForSourceFile(report, domainSf, sourceText, filePath) {
88
+ *
89
+ * @since 0.3.16-canary.0
90
+ */
91
+ function accumulateAnalyzeReportForSourceFile(report, domainSf, sourceText, filePath) {
85
92
  report.files++;
86
93
  const knownBindings = buildKnownCnTvBindings(domainSf);
87
94
  const visitTypeScriptSubtree = (tsNode) => {
@@ -1,8 +1,11 @@
1
- //#region src/domains/arrange/domain/ast/ast-node.model.ts
1
+ //#region src/arrange/domain/ast/ast-node.ts
2
2
  /**
3
3
  * Pure-domain AST shapes for arrange analysis. No TypeScript compiler types.
4
4
  * Positions mirror `getStart(sourceFile)` / `getEnd()` semantics from translation.
5
- */ var DomainSyntaxKind = /* @__PURE__ */ function(DomainSyntaxKind) {
5
+ *
6
+ * @since 0.3.16-canary.0
7
+ */
8
+ let DomainSyntaxKind = /* @__PURE__ */ function(DomainSyntaxKind) {
6
9
  DomainSyntaxKind[DomainSyntaxKind["Unknown"] = 1] = "Unknown";
7
10
  DomainSyntaxKind[DomainSyntaxKind["Identifier"] = 2] = "Identifier";
8
11
  DomainSyntaxKind[DomainSyntaxKind["StringLiteral"] = 3] = "StringLiteral";
@@ -29,56 +32,104 @@
29
32
  DomainSyntaxKind[DomainSyntaxKind["JsxExpression"] = 24] = "JsxExpression";
30
33
  return DomainSyntaxKind;
31
34
  }({});
32
- var DomainBinaryOperator = /* @__PURE__ */ function(DomainBinaryOperator) {
35
+ /**
36
+ * @since 0.3.16-canary.0
37
+ */
38
+ let DomainBinaryOperator = /* @__PURE__ */ function(DomainBinaryOperator) {
33
39
  DomainBinaryOperator[DomainBinaryOperator["Plus"] = 0] = "Plus";
34
40
  DomainBinaryOperator[DomainBinaryOperator["Other"] = 1] = "Other";
35
41
  return DomainBinaryOperator;
36
42
  }({});
43
+ /**
44
+ * @since 0.3.16-canary.0
45
+ */
37
46
  function isDomainIdentifier(node) {
38
47
  return node.kind === 2;
39
48
  }
49
+ /**
50
+ * @since 0.3.16-canary.0
51
+ */
40
52
  function isDomainStringLiteral(node) {
41
53
  return node.kind === 3;
42
54
  }
43
55
  function isDomainNoSubstitutionTemplateLiteral(node) {
44
56
  return node.kind === 4;
45
57
  }
58
+ /**
59
+ * @since 0.3.16-canary.0
60
+ */
46
61
  function isDomainTailwindClassLiteral(node) {
47
62
  return isDomainStringLiteral(node) || isDomainNoSubstitutionTemplateLiteral(node);
48
63
  }
64
+ /**
65
+ * @since 0.3.16-canary.0
66
+ */
49
67
  function isDomainImportDeclaration(node) {
50
68
  return node.kind === 5;
51
69
  }
70
+ /**
71
+ * @since 0.3.16-canary.0
72
+ */
52
73
  function isDomainNamedImports(node) {
53
74
  return node.kind === 7;
54
75
  }
76
+ /**
77
+ * @since 0.3.16-canary.0
78
+ */
55
79
  function isDomainNamespaceImport(node) {
56
80
  return node.kind === 8;
57
81
  }
82
+ /**
83
+ * @since 0.3.16-canary.0
84
+ */
58
85
  function isDomainCallExpression(node) {
59
86
  return node.kind === 10;
60
87
  }
88
+ /**
89
+ * @since 0.3.16-canary.0
90
+ */
61
91
  function isDomainObjectLiteralExpression(node) {
62
92
  return node.kind === 12;
63
93
  }
94
+ /**
95
+ * @since 0.3.16-canary.0
96
+ */
64
97
  function isDomainPropertyAssignment(node) {
65
98
  return node.kind === 13;
66
99
  }
100
+ /**
101
+ * @since 0.3.16-canary.0
102
+ */
67
103
  function isDomainArrayLiteralExpression(node) {
68
104
  return node.kind === 14;
69
105
  }
106
+ /**
107
+ * @since 0.3.16-canary.0
108
+ */
70
109
  function isDomainSpreadElement(node) {
71
110
  return node.kind === 15;
72
111
  }
112
+ /**
113
+ * @since 0.3.16-canary.0
114
+ */
73
115
  function isDomainPropertyAccessExpression(node) {
74
116
  return node.kind === 11;
75
117
  }
118
+ /**
119
+ * @since 0.3.16-canary.0
120
+ */
76
121
  function isDomainJsxAttribute(node) {
77
122
  return node.kind === 23;
78
123
  }
124
+ /**
125
+ * @since 0.3.16-canary.0
126
+ */
79
127
  function isDomainJsxExpression(node) {
80
128
  return node.kind === 24;
81
129
  }
130
+ /**
131
+ * @since 0.3.16-canary.0
132
+ */
82
133
  function forEachDomainChild(node, visit) {
83
134
  switch (node.kind) {
84
135
  case 1:
@@ -151,6 +202,9 @@ function forEachDomainChild(node, visit) {
151
202
  default: return;
152
203
  }
153
204
  }
205
+ /**
206
+ * @since 0.3.16-canary.0
207
+ */
154
208
  function lineOfSourcePosition(sourceText, pos) {
155
209
  const boundedPos = Math.max(0, Math.min(pos, sourceText.length));
156
210
  let line = 1;
@@ -1,44 +1,56 @@
1
- import "../constants.domain.mjs";
2
- import { DomainBinaryOperator, DomainSyntaxKind, isDomainArrayLiteralExpression, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
3
- //#region src/domains/arrange/domain/ast/collectors-cn.collector.ts
1
+ import "../constants.mjs";
2
+ import { isDomainArrayLiteralExpression, isDomainTailwindClassLiteral } from "./ast-node.mjs";
3
+ //#region src/arrange/domain/ast/collectors-cn.ts
4
+ /**
5
+ * @since 0.3.16-canary.0
6
+ */
4
7
  function forEachStringLiteralInClassExpression(expr, sink, depth = 0, options) {
5
8
  if (depth > 12) return;
6
9
  if (isDomainTailwindClassLiteral(expr)) {
7
10
  sink(expr);
8
11
  return;
9
12
  }
10
- if (expr.kind === DomainSyntaxKind.ParenthesizedExpression) {
13
+ if (expr.kind === 16) {
11
14
  forEachStringLiteralInClassExpression(expr.expression, sink, depth + 1, options);
12
15
  return;
13
16
  }
14
- if (expr.kind === DomainSyntaxKind.AsExpression || expr.kind === DomainSyntaxKind.SatisfiesExpression) {
17
+ if (expr.kind === 17 || expr.kind === 18) {
15
18
  forEachStringLiteralInClassExpression(expr.expression, sink, depth + 1, options);
16
19
  return;
17
20
  }
18
- if (expr.kind === DomainSyntaxKind.NonNullExpression) {
21
+ if (expr.kind === 19) {
19
22
  forEachStringLiteralInClassExpression(expr.expression, sink, depth + 1, options);
20
23
  return;
21
24
  }
22
- if (expr.kind === DomainSyntaxKind.ConditionalExpression) {
25
+ if (expr.kind === 20) {
23
26
  if (options?.descendIntoConditional === false) return;
24
27
  forEachStringLiteralInClassExpression(expr.whenTrue, sink, depth + 1, options);
25
28
  forEachStringLiteralInClassExpression(expr.whenFalse, sink, depth + 1, options);
26
29
  return;
27
30
  }
28
- if (expr.kind === DomainSyntaxKind.BinaryExpression && expr.operator === DomainBinaryOperator.Plus) {
31
+ if (expr.kind === 21 && expr.operator === 0) {
29
32
  forEachStringLiteralInClassExpression(expr.left, sink, depth + 1, options);
30
33
  forEachStringLiteralInClassExpression(expr.right, sink, depth + 1, options);
31
34
  return;
32
35
  }
33
36
  if (isDomainArrayLiteralExpression(expr)) for (const arrayElement of expr.elements) {
34
- if (arrayElement.kind === DomainSyntaxKind.SpreadElement) continue;
37
+ if (arrayElement.kind === 15) continue;
35
38
  forEachStringLiteralInClassExpression(arrayElement, sink, depth + 1, options);
36
39
  }
37
40
  }
41
+ /**
42
+ * @since 0.3.16-canary.0
43
+ */
38
44
  function isUnsafeLiteralForCnStyleApplySplit(classLiteral) {
39
45
  return classLiteral.parent !== null && isDomainArrayLiteralExpression(classLiteral.parent);
40
46
  }
47
+ /**
48
+ * @since 0.3.16-canary.0
49
+ */
41
50
  const CN_APPLY_LITERAL_WALK_OPTS = { descendIntoConditional: false };
51
+ /**
52
+ * @since 0.3.16-canary.0
53
+ */
42
54
  function collectUnconditionalTailwindLiteralsFromCnArguments(args) {
43
55
  const staticLits = [];
44
56
  for (const arg of args) if (isDomainTailwindClassLiteral(arg)) {
@@ -1,5 +1,8 @@
1
- import { isDomainIdentifier, isDomainJsxExpression, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
2
- //#region src/domains/arrange/domain/ast/collectors-jsx.collector.ts
1
+ import { isDomainIdentifier, isDomainJsxExpression, isDomainTailwindClassLiteral } from "./ast-node.mjs";
2
+ //#region src/arrange/domain/ast/collectors-jsx.ts
3
+ /**
4
+ * @since 0.3.16-canary.0
5
+ */
3
6
  function jsxClassNameStaticLiteral(jsxClassNameAttribute) {
4
7
  if (!isDomainIdentifier(jsxClassNameAttribute.name) || jsxClassNameAttribute.name.text !== "className") return;
5
8
  const init = jsxClassNameAttribute.initializer;
@@ -1,9 +1,12 @@
1
- import "../constants.domain.mjs";
2
- import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainObjectLiteralExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
3
- import { buildKnownCnTvBindings, isCnOrTvIdentifier, propertyAssignmentNameText } from "./ast-helpers.helper.mjs";
4
- import { CN_APPLY_LITERAL_WALK_OPTS, collectUnconditionalTailwindLiteralsFromCnArguments, forEachStringLiteralInClassExpression, isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "../tailwind-token.value-object.mjs";
6
- //#region src/domains/arrange/domain/ast/collectors-tv.collector.ts
1
+ import "../constants.mjs";
2
+ import { tokenizeClassString } from "../tailwind-token.mjs";
3
+ import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainCallExpression, isDomainObjectLiteralExpression, isDomainPropertyAssignment, isDomainSpreadElement, isDomainTailwindClassLiteral } from "./ast-node.mjs";
4
+ import { CN_APPLY_LITERAL_WALK_OPTS, collectUnconditionalTailwindLiteralsFromCnArguments, forEachStringLiteralInClassExpression, isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.mjs";
5
+ import { buildKnownCnTvBindings, isCnOrTvIdentifier, propertyAssignmentNameText } from "./helpers.mjs";
6
+ //#region src/arrange/domain/ast/collectors-tv.ts
7
+ /**
8
+ * @since 0.3.16-canary.0
9
+ */
7
10
  function traverseTvObject(sourceFile, obj, visitor, depth = 0, knownBindings) {
8
11
  if (depth > 12) return;
9
12
  for (const prop of obj.properties) {
@@ -37,6 +40,9 @@ function traverseTvObject(sourceFile, obj, visitor, depth = 0, knownBindings) {
37
40
  });
38
41
  }
39
42
  }
43
+ /**
44
+ * @since 0.3.16-canary.0
45
+ */
40
46
  function collectCnCallsInsideTv(sourceFile, obj, knownBindings, depth = 0) {
41
47
  if (depth > 12) return [];
42
48
  const calls = [];
@@ -59,6 +65,9 @@ function collectCnCallsInsideTv(sourceFile, obj, knownBindings, depth = 0) {
59
65
  }
60
66
  return calls;
61
67
  }
68
+ /**
69
+ * @since 0.3.16-canary.0
70
+ */
62
71
  function listAllCnCallsInsideTvInSourceFile(sourceFile, knownBindings) {
63
72
  const calls = [];
64
73
  const visitSubtree = (tsNode) => {
@@ -84,6 +93,9 @@ function makeStringNode(nodes, sourceFile, isTvContext, cnCall) {
84
93
  }
85
94
  };
86
95
  }
96
+ /**
97
+ * @since 0.3.16-canary.0
98
+ */
87
99
  function slotClassString(stringNode) {
88
100
  return stringNode.nodes.map((literal) => literal.text).join(" ");
89
101
  }
@@ -144,6 +156,9 @@ function collectTvSlots(sourceFile, obj, knownBindings, results, seenNodePos, de
144
156
  }
145
157
  }
146
158
  }
159
+ /**
160
+ * @since 0.3.16-canary.0
161
+ */
147
162
  function collectGroupableStringNodes(sourceFile) {
148
163
  const results = [];
149
164
  const seenNodePos = /* @__PURE__ */ new Set();
@@ -1,10 +1,11 @@
1
- import { EMPTY_CN_TV_BINDINGS } from "../constants.domain.mjs";
2
- import { applyEditsDescending, indentOfLineContaining } from "../../../../shell/domain/source-text-edit.support.mjs";
3
- import { isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, isDomainNamespaceImport, isDomainPropertyAccessExpression, isDomainStringLiteral, lineOfSourcePosition } from "./ast-node.model.mjs";
4
- //#region src/domains/arrange/domain/ast/ast-helpers.helper.ts
1
+ import { EMPTY_CN_TV_BINDINGS } from "../constants.mjs";
2
+ import { isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, isDomainNamespaceImport, isDomainPropertyAccessExpression, isDomainStringLiteral, lineOfSourcePosition } from "./ast-node.mjs";
3
+ import { applyEditsDescending, indentOfLineContaining } from "../../../core/source-text-edit.mjs";
4
+ //#region src/arrange/domain/ast/helpers.ts
5
5
  /**
6
6
  * Known module specifiers that export `cn` / `tv`.
7
- */ const KNOWN_CN_TV_MODULES = new Set([
7
+ */
8
+ const KNOWN_CN_TV_MODULES = new Set([
8
9
  "@codefast/tailwind-variants",
9
10
  "clsx",
10
11
  "class-variance-authority",
@@ -16,7 +17,8 @@ import { isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, is
16
17
  /**
17
18
  * True for typical shadcn-style re-exports: `./utils`, `@/lib/utils`, `…/utils/…`,
18
19
  * or a dedicated `cn.ts` / `cn.tsx` module.
19
- */ function moduleLooksLikeCnTvReexport(moduleSpecifier) {
20
+ */
21
+ function moduleLooksLikeCnTvReexport(moduleSpecifier) {
20
22
  const norm = moduleSpecifier.replace(/\\/g, "/");
21
23
  if (/(?:^|[./])utils(?:\/|$)/.test(norm)) return true;
22
24
  if (/\/utils\//.test(norm) || /\/utils$/.test(norm)) return true;
@@ -26,7 +28,10 @@ import { isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, is
26
28
  /**
27
29
  * Build a set of local binding names that are imported from a known cn/tv
28
30
  * module in `sourceFile`.
29
- */ function buildKnownCnTvBindings(sourceFile) {
31
+ *
32
+ * @since 0.3.16-canary.0
33
+ */
34
+ function buildKnownCnTvBindings(sourceFile) {
30
35
  const bindings = /* @__PURE__ */ new Set();
31
36
  for (const stmt of sourceFile.statements) {
32
37
  if (!isDomainImportDeclaration(stmt) || !stmt.importClause) continue;
@@ -50,23 +55,35 @@ import { isDomainIdentifier, isDomainImportDeclaration, isDomainNamedImports, is
50
55
  /**
51
56
  * Returns true when `expr` is an identifier whose name matches `name` AND
52
57
  * that name is listed in `knownBindings` from a recognized import.
53
- */ function isCnOrTvIdentifier(expr, name, knownBindings = EMPTY_CN_TV_BINDINGS) {
58
+ *
59
+ * @since 0.3.16-canary.0
60
+ */
61
+ function isCnOrTvIdentifier(expr, name, knownBindings = EMPTY_CN_TV_BINDINGS) {
54
62
  if (knownBindings.size === 0) return false;
55
63
  if (isDomainIdentifier(expr) && expr.text === name) return knownBindings.has(expr.text);
56
64
  if (isDomainPropertyAccessExpression(expr) && expr.name.text === name) return isDomainIdentifier(expr.expression) && knownBindings.has(expr.expression.text);
57
65
  return false;
58
66
  }
67
+ /**
68
+ * @since 0.3.16-canary.0
69
+ */
59
70
  function propertyAssignmentNameText(prop) {
60
71
  if (isDomainIdentifier(prop.name)) return prop.name.text;
61
72
  if (isDomainStringLiteral(prop.name)) return prop.name.text;
62
73
  }
74
+ /**
75
+ * @since 0.3.16-canary.0
76
+ */
63
77
  function lineOf(sourceFile, node) {
64
78
  return lineOfSourcePosition(sourceFile.text, node.pos);
65
79
  }
66
80
  /**
67
81
  * Replace `cn(...)` nested in `tv({...})` with a plain string (one arg) or a string
68
82
  * array (multiple args). Returns undefined when there are zero arguments.
69
- */ function unwrapCnInsideTvCallReplacement(call, sourceText) {
83
+ *
84
+ * @since 0.3.16-canary.0
85
+ */
86
+ function unwrapCnInsideTvCallReplacement(call, sourceText) {
70
87
  const args = call.arguments;
71
88
  if (args.length === 0) return;
72
89
  const baseIndent = indentOfLineContaining(sourceText, call.pos);
@@ -1,13 +1,16 @@
1
- import "../constants.domain.mjs";
2
- import { endAfterOptionalCommaFollowingInSource, indentOfLineContaining, textPrefixFromLineStartToPosition } from "../../../../shell/domain/source-text-edit.support.mjs";
3
- import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainJsxAttribute, isDomainTailwindClassLiteral } from "./ast-node.model.mjs";
4
- import { isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.collector.mjs";
5
- import { tokenizeClassString } from "../tailwind-token.value-object.mjs";
6
- import { collectGroupableStringNodes, slotClassString } from "./collectors-tv.collector.mjs";
7
- import { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels } from "../grouping.domain.mjs";
8
- import { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatJsxCnAttributeValue } from "../source-text-formatters.formatter.mjs";
9
- import { jsxClassNameStaticLiteral } from "./collectors-jsx.collector.mjs";
10
- //#region src/domains/arrange/domain/ast/targets.model.ts
1
+ import "../constants.mjs";
2
+ import { tokenizeClassString } from "../tailwind-token.mjs";
3
+ import { forEachDomainChild, isDomainArrayLiteralExpression, isDomainJsxAttribute, isDomainTailwindClassLiteral } from "./ast-node.mjs";
4
+ import { isUnsafeLiteralForCnStyleApplySplit } from "./collectors-cn.mjs";
5
+ import { jsxClassNameStaticLiteral } from "./collectors-jsx.mjs";
6
+ import { endAfterOptionalCommaFollowingInSource, indentOfLineContaining, textPrefixFromLineStartToPosition } from "../../../core/source-text-edit.mjs";
7
+ import { collectGroupableStringNodes, slotClassString } from "./collectors-tv.mjs";
8
+ import { areCnTailwindPartitionsEquivalent, suggestCnGroups, summarizeGroupBucketLabels } from "../grouping.mjs";
9
+ import { escapeTsStringLiteralContent, formatArray, formatArrayElementsAsSiblingLines, formatJsxCnAttributeValue } from "../source-text-formatters.mjs";
10
+ //#region src/arrange/domain/ast/targets.ts
11
+ /**
12
+ * @since 0.3.16-canary.0
13
+ */
11
14
  function targetReplaceStart(target) {
12
15
  if (target.kind === "cnArg") return target.item.cnCall ? target.item.cnCall.pos : target.item.primaryClassLiteral.pos;
13
16
  return target.valueNode.pos;
@@ -29,6 +32,9 @@ function collectLongJsxClassNameTargets(sourceFile) {
29
32
  for (const stmt of sourceFile.statements) visitTypeScriptSubtree(stmt);
30
33
  return results;
31
34
  }
35
+ /**
36
+ * @since 0.3.16-canary.0
37
+ */
32
38
  function collectGroupTargets(sourceFile, filePath) {
33
39
  const cnPart = collectGroupableStringNodes(sourceFile).map((stringNode) => ({
34
40
  kind: "cnArg",
@@ -58,6 +64,9 @@ function formatCnCallReplacement(stringNode, sourceText, withClassName) {
58
64
  const commaAfterLastArg = allArgs.length > 1;
59
65
  return `cn(\n${allArgs.map((argLine, lineIndex) => lineIndex < allArgs.length - 1 || commaAfterLastArg ? `${argLine},` : `${argLine}`).join("\n")}\n${baseIndent})`;
60
66
  }
67
+ /**
68
+ * @since 0.3.16-canary.0
69
+ */
61
70
  function planGroupEditForTarget(target, textAfterUnwrap, withClassName) {
62
71
  if (target.kind === "jsxClassName") {
63
72
  const groups = suggestCnGroups(target.lit.text);