politty 0.1.1 → 0.2.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 (59) hide show
  1. package/dist/{arg-registry-D4NsqcNZ.d.ts → arg-registry-i6SA4l-E.d.cts} +1 -2
  2. package/dist/arg-registry-i6SA4l-E.d.cts.map +1 -0
  3. package/dist/{arg-registry-ClI2WGgH.d.cts → arg-registry-w5mMKJkZ.d.ts} +1 -2
  4. package/dist/arg-registry-w5mMKJkZ.d.ts.map +1 -0
  5. package/dist/augment.d.cts +1 -2
  6. package/dist/augment.d.cts.map +1 -1
  7. package/dist/augment.d.ts +1 -2
  8. package/dist/augment.d.ts.map +1 -1
  9. package/dist/{command-CvKyk4ag.js → command-DCpFEZFM.js} +1 -1
  10. package/dist/{command-CvKyk4ag.js.map → command-DCpFEZFM.js.map} +1 -1
  11. package/dist/completion/index.cjs +1 -1
  12. package/dist/completion/index.cjs.map +1 -1
  13. package/dist/completion/index.d.cts +1 -3
  14. package/dist/completion/index.d.cts.map +1 -1
  15. package/dist/completion/index.d.ts +1 -3
  16. package/dist/completion/index.d.ts.map +1 -1
  17. package/dist/completion/index.js +3 -3
  18. package/dist/completion/index.js.map +1 -1
  19. package/dist/docs/index.cjs +252 -26
  20. package/dist/docs/index.cjs.map +1 -1
  21. package/dist/docs/index.d.cts +95 -13
  22. package/dist/docs/index.d.cts.map +1 -1
  23. package/dist/docs/index.d.ts +95 -13
  24. package/dist/docs/index.d.ts.map +1 -1
  25. package/dist/docs/index.js +269 -45
  26. package/dist/docs/index.js.map +1 -1
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.cts +2 -2
  29. package/dist/index.d.cts.map +1 -1
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +3 -3
  33. package/dist/runner-BkhekqT9.cjs +4 -0
  34. package/dist/{runner-DceWXOwD.js → runner-CyxuNkT1.js} +18 -18
  35. package/dist/runner-CyxuNkT1.js.map +1 -0
  36. package/dist/runner-DzzbIwEy.js +4 -0
  37. package/dist/{runner-BZuYiRhi.cjs → runner-ttyvfYGi.cjs} +16 -16
  38. package/dist/runner-ttyvfYGi.cjs.map +1 -0
  39. package/dist/schema-extractor-B9D3Rf22.cjs.map +1 -1
  40. package/dist/{schema-extractor-kkajLb9E.d.ts → schema-extractor-CXeUTW_Z.d.cts} +1 -2
  41. package/dist/schema-extractor-CXeUTW_Z.d.cts.map +1 -0
  42. package/dist/{schema-extractor-D-Eo7I77.d.cts → schema-extractor-Cl_D04BX.d.ts} +1 -2
  43. package/dist/schema-extractor-Cl_D04BX.d.ts.map +1 -0
  44. package/dist/{schema-extractor-Dk5Z0Iei.js → schema-extractor-D0q5Fj2R.js} +1 -1
  45. package/dist/schema-extractor-D0q5Fj2R.js.map +1 -0
  46. package/dist/{subcommand-router-BiSvDXHg.js → subcommand-router-D9QSLX56.js} +1 -1
  47. package/dist/subcommand-router-D9QSLX56.js.map +1 -0
  48. package/dist/subcommand-router-Vf-0w9P4.cjs.map +1 -1
  49. package/package.json +13 -13
  50. package/dist/arg-registry-ClI2WGgH.d.cts.map +0 -1
  51. package/dist/arg-registry-D4NsqcNZ.d.ts.map +0 -1
  52. package/dist/runner-BZuYiRhi.cjs.map +0 -1
  53. package/dist/runner-D2BXiWtg.cjs +0 -4
  54. package/dist/runner-DceWXOwD.js.map +0 -1
  55. package/dist/runner-KCql2UKz.js +0 -4
  56. package/dist/schema-extractor-D-Eo7I77.d.cts.map +0 -1
  57. package/dist/schema-extractor-Dk5Z0Iei.js.map +0 -1
  58. package/dist/schema-extractor-kkajLb9E.d.ts.map +0 -1
  59. package/dist/subcommand-router-BiSvDXHg.js.map +0 -1
@@ -1,5 +1,6 @@
1
- import { n as getExtractedFields } from "../schema-extractor-Dk5Z0Iei.js";
2
- import { i as createLogCollector, n as resolveLazyCommand } from "../subcommand-router-BiSvDXHg.js";
1
+ import { n as getExtractedFields, t as extractFields } from "../schema-extractor-D0q5Fj2R.js";
2
+ import { i as createLogCollector, n as resolveLazyCommand } from "../subcommand-router-D9QSLX56.js";
3
+ import { z } from "zod";
3
4
  import * as fs from "node:fs";
4
5
  import * as path from "node:path";
5
6
 
@@ -7,13 +8,13 @@ import * as path from "node:path";
7
8
  /**
8
9
  * Escape markdown special characters in table cells
9
10
  */
10
- function escapeTableCell(str) {
11
+ function escapeTableCell$2(str) {
11
12
  return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
12
13
  }
13
14
  /**
14
15
  * Format default value for display
15
16
  */
16
- function formatDefaultValue(value) {
17
+ function formatDefaultValue$1(value) {
17
18
  if (value === void 0) return "-";
18
19
  return `\`${JSON.stringify(value)}\``;
19
20
  }
@@ -37,7 +38,7 @@ function renderArgumentsTable(info) {
37
38
  lines.push("| Argument | Description | Required |");
38
39
  lines.push("|----------|-------------|----------|");
39
40
  for (const arg of info.positionalArgs) {
40
- const desc = escapeTableCell(arg.description ?? "");
41
+ const desc = escapeTableCell$2(arg.description ?? "");
41
42
  const required = arg.required ? "Yes" : "No";
42
43
  lines.push(`| \`${arg.name}\` | ${desc} | ${required} |`);
43
44
  }
@@ -103,8 +104,8 @@ function renderOptionsTable(info) {
103
104
  const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
104
105
  const optionName = opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
105
106
  const alias = opt.alias ? `\`-${opt.alias}\`` : "-";
106
- const desc = escapeTableCell(opt.description ?? "");
107
- const defaultVal = formatDefaultValue(opt.defaultValue);
107
+ const desc = escapeTableCell$2(opt.description ?? "");
108
+ const defaultVal = formatDefaultValue$1(opt.defaultValue);
108
109
  if (hasEnv) {
109
110
  const envNames = opt.env ? Array.isArray(opt.env) ? opt.env.map((e) => `\`${e}\``).join(", ") : `\`${opt.env}\`` : "-";
110
111
  lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} | ${envNames} |`);
@@ -138,7 +139,7 @@ function renderOptionsList(info) {
138
139
  /**
139
140
  * Generate anchor from command path
140
141
  */
141
- function generateAnchor(commandPath) {
142
+ function generateAnchor$1(commandPath) {
142
143
  return commandPath.join("-").toLowerCase();
143
144
  }
144
145
  /**
@@ -164,10 +165,10 @@ function renderSubcommandsTable(info, generateAnchors = true) {
164
165
  const fileMap = info.fileMap;
165
166
  for (const sub of info.subCommands) {
166
167
  const fullName = sub.fullPath.join(" ");
167
- const desc = escapeTableCell(sub.description ?? "");
168
+ const desc = escapeTableCell$2(sub.description ?? "");
168
169
  const subCommandPath = sub.fullPath.join(" ");
169
170
  if (generateAnchors) {
170
- const anchor = generateAnchor(sub.fullPath);
171
+ const anchor = generateAnchor$1(sub.fullPath);
171
172
  const subFile = fileMap?.[subCommandPath];
172
173
  if (currentFile && subFile && currentFile !== subFile) {
173
174
  const relativePath = getRelativePath(currentFile, subFile);
@@ -195,8 +196,8 @@ function renderOptionsTableFromArray(options) {
195
196
  const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
196
197
  const optionName = opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
197
198
  const alias = opt.alias ? `\`-${opt.alias}\`` : "-";
198
- const desc = escapeTableCell(opt.description ?? "");
199
- const defaultVal = formatDefaultValue(opt.defaultValue);
199
+ const desc = escapeTableCell$2(opt.description ?? "");
200
+ const defaultVal = formatDefaultValue$1(opt.defaultValue);
200
201
  if (hasEnv) {
201
202
  const envNames = opt.env ? Array.isArray(opt.env) ? opt.env.map((e) => `\`${e}\``).join(", ") : `\`${opt.env}\`` : "-";
202
203
  lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} | ${envNames} |`);
@@ -228,7 +229,7 @@ function renderArgumentsTableFromArray(args) {
228
229
  lines.push("| Argument | Description | Required |");
229
230
  lines.push("|----------|-------------|----------|");
230
231
  for (const arg of args) {
231
- const desc = escapeTableCell(arg.description ?? "");
232
+ const desc = escapeTableCell$2(arg.description ?? "");
232
233
  const required = arg.required ? "Yes" : "No";
233
234
  lines.push(`| \`${arg.name}\` | ${desc} | ${required} |`);
234
235
  }
@@ -259,10 +260,10 @@ function renderSubcommandsTableFromArray(subcommands, info, generateAnchors = tr
259
260
  const fileMap = info.fileMap;
260
261
  for (const sub of subcommands) {
261
262
  const fullName = sub.fullPath.join(" ");
262
- const desc = escapeTableCell(sub.description ?? "");
263
+ const desc = escapeTableCell$2(sub.description ?? "");
263
264
  const subCommandPath = sub.fullPath.join(" ");
264
265
  if (generateAnchors) {
265
- const anchor = generateAnchor(sub.fullPath);
266
+ const anchor = generateAnchor$1(sub.fullPath);
266
267
  const subFile = fileMap?.[subCommandPath];
267
268
  if (currentFile && subFile && currentFile !== subFile) {
268
269
  const relativePath = getRelativePath(currentFile, subFile);
@@ -290,6 +291,7 @@ function renderSubcommandsTableFromArray(subcommands, info, generateAnchors = tr
290
291
  function renderExamplesDefault(examples, results, opts) {
291
292
  if (examples.length === 0) return "";
292
293
  const showOutput = opts?.showOutput ?? true;
294
+ const prefix = opts?.commandPrefix ? `${opts.commandPrefix} ` : "";
293
295
  const lines = [];
294
296
  for (let i = 0; i < examples.length; i++) {
295
297
  const example = examples[i];
@@ -298,7 +300,7 @@ function renderExamplesDefault(examples, results, opts) {
298
300
  lines.push(`**${example.desc}**`);
299
301
  lines.push("");
300
302
  lines.push("```bash");
301
- lines.push(`$ ${example.cmd}`);
303
+ lines.push(`$ ${prefix}${example.cmd}`);
302
304
  if (showOutput) {
303
305
  if (result) {
304
306
  if (result.stdout) lines.push(result.stdout);
@@ -351,8 +353,8 @@ function createCommandRenderer(options = {}) {
351
353
  const renderArgs = (args, opts) => {
352
354
  const style = opts?.style ?? optionStyle;
353
355
  const withHeading = opts?.withHeading ?? true;
354
- const content$1 = style === "table" ? renderArgumentsTableFromArray(args) : renderArgumentsListFromArray(args);
355
- return withHeading ? `**Arguments**\n\n${content$1}` : content$1;
356
+ const content = style === "table" ? renderArgumentsTableFromArray(args) : renderArgumentsListFromArray(args);
357
+ return withHeading ? `**Arguments**\n\n${content}` : content;
356
358
  };
357
359
  const context = {
358
360
  args: info.positionalArgs,
@@ -367,11 +369,11 @@ function createCommandRenderer(options = {}) {
367
369
  }
368
370
  }
369
371
  if (info.options.length > 0) {
370
- const renderOpts = (opts, renderOpts$1) => {
371
- const style = renderOpts$1?.style ?? optionStyle;
372
- const withHeading = renderOpts$1?.withHeading ?? true;
373
- const content$1 = style === "table" ? renderOptionsTableFromArray(opts) : renderOptionsListFromArray(opts);
374
- return withHeading ? `**Options**\n\n${content$1}` : content$1;
372
+ const renderOpts = (opts, renderOpts) => {
373
+ const style = renderOpts?.style ?? optionStyle;
374
+ const withHeading = renderOpts?.withHeading ?? true;
375
+ const content = style === "table" ? renderOptionsTableFromArray(opts) : renderOptionsListFromArray(opts);
376
+ return withHeading ? `**Options**\n\n${content}` : content;
375
377
  };
376
378
  const context = {
377
379
  options: info.options,
@@ -390,8 +392,8 @@ function createCommandRenderer(options = {}) {
390
392
  const renderSubs = (subs, opts) => {
391
393
  const anchors = opts?.generateAnchors ?? effectiveAnchors;
392
394
  const withHeading = opts?.withHeading ?? true;
393
- const content$1 = renderSubcommandsTableFromArray(subs, info, anchors);
394
- return withHeading ? `**Commands**\n\n${content$1}` : content$1;
395
+ const content = renderSubcommandsTableFromArray(subs, info, anchors);
396
+ return withHeading ? `**Commands**\n\n${content}` : content;
395
397
  };
396
398
  const context = {
397
399
  subcommands: info.subCommands,
@@ -408,8 +410,11 @@ function createCommandRenderer(options = {}) {
408
410
  if (info.examples && info.examples.length > 0) {
409
411
  const renderEx = (examples, results, opts) => {
410
412
  const withHeading = opts?.withHeading ?? true;
411
- const content$1 = renderExamplesDefault(examples, results, opts);
412
- return withHeading ? `**Examples**\n\n${content$1}` : content$1;
413
+ const content = renderExamplesDefault(examples, results, {
414
+ commandPrefix: info.fullCommandPath,
415
+ ...opts
416
+ });
417
+ return withHeading ? `**Examples**\n\n${content}` : content;
413
418
  };
414
419
  const context = {
415
420
  examples: info.examples,
@@ -598,11 +603,11 @@ async function buildCommandInfo(command, rootName, commandPath = []) {
598
603
  async function collectAllCommands(command, rootName) {
599
604
  const root = rootName ?? command.name ?? "command";
600
605
  const result = /* @__PURE__ */ new Map();
601
- async function traverse(cmd, path$1) {
602
- const info = await buildCommandInfo(cmd, root, path$1);
603
- const pathKey = path$1.join(" ");
606
+ async function traverse(cmd, path) {
607
+ const info = await buildCommandInfo(cmd, root, path);
608
+ const pathKey = path.join(" ");
604
609
  result.set(pathKey, info);
605
- if (cmd.subCommands) for (const [name, subCmd] of Object.entries(cmd.subCommands)) await traverse(await resolveLazyCommand(subCmd), [...path$1, name]);
610
+ if (cmd.subCommands) for (const [name, subCmd] of Object.entries(cmd.subCommands)) await traverse(await resolveLazyCommand(subCmd), [...path, name]);
606
611
  }
607
612
  await traverse(command, []);
608
613
  return result;
@@ -642,7 +647,7 @@ async function executeSingleExample(example, rootCommand, commandPath) {
642
647
  collector.start();
643
648
  let success = true;
644
649
  try {
645
- const { runCommand } = await import("../runner-KCql2UKz.js");
650
+ const { runCommand } = await import("../runner-DzzbIwEy.js");
646
651
  const result = await runCommand(rootCommand, argv);
647
652
  success = result.success;
648
653
  if (!result.success && result.error) console.error(result.error.message);
@@ -770,8 +775,8 @@ function containsWildcard(pattern) {
770
775
  * matchesWildcard("config get", "config *") // true
771
776
  * matchesWildcard("greet", "*") // true
772
777
  */
773
- function matchesWildcard(path$1, pattern) {
774
- const pathSegments = path$1 === "" ? [] : path$1.split(" ");
778
+ function matchesWildcard(path, pattern) {
779
+ const pathSegments = path === "" ? [] : path.split(" ");
775
780
  const patternSegments = pattern === "" ? [] : pattern.split(" ");
776
781
  if (pathSegments.length !== patternSegments.length) return false;
777
782
  for (let i = 0; i < patternSegments.length; i++) {
@@ -793,15 +798,15 @@ function expandWildcardPattern(pattern, allCommands) {
793
798
  * Check if a path matches any ignore pattern (with wildcard support)
794
799
  * For wildcard patterns, also ignores subcommands of matched commands
795
800
  */
796
- function matchesIgnorePattern(path$1, ignorePattern) {
801
+ function matchesIgnorePattern(path, ignorePattern) {
797
802
  if (containsWildcard(ignorePattern)) {
798
- if (matchesWildcard(path$1, ignorePattern)) return true;
799
- const pathSegments = path$1 === "" ? [] : path$1.split(" ");
803
+ if (matchesWildcard(path, ignorePattern)) return true;
804
+ const pathSegments = path === "" ? [] : path.split(" ");
800
805
  const patternSegments = ignorePattern === "" ? [] : ignorePattern.split(" ");
801
806
  if (pathSegments.length > patternSegments.length) return matchesWildcard(pathSegments.slice(0, patternSegments.length).join(" "), ignorePattern);
802
807
  return false;
803
808
  }
804
- return isSubcommandOf(path$1, ignorePattern);
809
+ return isSubcommandOf(path, ignorePattern);
805
810
  }
806
811
  /**
807
812
  * Expand command paths to include all subcommands (with wildcard support)
@@ -812,11 +817,11 @@ function expandCommandPaths(commandPaths, allCommands) {
812
817
  const matches = expandWildcardPattern(cmdPath, allCommands);
813
818
  for (const match of matches) {
814
819
  expanded.add(match);
815
- for (const path$1 of allCommands.keys()) if (isSubcommandOf(path$1, match)) expanded.add(path$1);
820
+ for (const path of allCommands.keys()) if (isSubcommandOf(path, match)) expanded.add(path);
816
821
  }
817
822
  } else {
818
823
  if (allCommands.has(cmdPath)) expanded.add(cmdPath);
819
- for (const path$1 of allCommands.keys()) if (isSubcommandOf(path$1, cmdPath)) expanded.add(path$1);
824
+ for (const path of allCommands.keys()) if (isSubcommandOf(path, cmdPath)) expanded.add(path);
820
825
  }
821
826
  return Array.from(expanded);
822
827
  }
@@ -824,8 +829,8 @@ function expandCommandPaths(commandPaths, allCommands) {
824
829
  * Filter out ignored commands (with wildcard support)
825
830
  */
826
831
  function filterIgnoredCommands(commandPaths, ignores) {
827
- return commandPaths.filter((path$1) => {
828
- return !ignores.some((ignorePattern) => matchesIgnorePattern(path$1, ignorePattern));
832
+ return commandPaths.filter((path) => {
833
+ return !ignores.some((ignorePattern) => matchesIgnorePattern(path, ignorePattern));
829
834
  });
830
835
  }
831
836
  /**
@@ -858,7 +863,7 @@ function validateIgnoresExist(ignores, allCommands) {
858
863
  function sortDepthFirst(commandPaths, specifiedOrder) {
859
864
  const pathSet = new Set(commandPaths);
860
865
  const topLevelPaths = specifiedOrder.filter((cmd) => pathSet.has(cmd));
861
- for (const path$1 of commandPaths) if ((path$1 === "" ? 0 : path$1.split(" ").length) === 1 && !topLevelPaths.includes(path$1)) topLevelPaths.push(path$1);
866
+ for (const path of commandPaths) if ((path === "" ? 0 : path.split(" ").length) === 1 && !topLevelPaths.includes(path)) topLevelPaths.push(path);
862
867
  const result = [];
863
868
  const visited = /* @__PURE__ */ new Set();
864
869
  function addWithChildren(cmdPath) {
@@ -873,7 +878,7 @@ function sortDepthFirst(commandPaths, specifiedOrder) {
873
878
  for (const child of children) addWithChildren(child);
874
879
  }
875
880
  for (const topLevel of topLevelPaths) addWithChildren(topLevel);
876
- for (const path$1 of commandPaths) if (!visited.has(path$1)) result.push(path$1);
881
+ for (const path of commandPaths) if (!visited.has(path)) result.push(path);
877
882
  return result;
878
883
  }
879
884
  /**
@@ -1178,5 +1183,224 @@ function initDocFile(config, fileSystem) {
1178
1183
  }
1179
1184
 
1180
1185
  //#endregion
1181
- export { COMMAND_MARKER_PREFIX, UPDATE_GOLDEN_ENV, assertDocMatch, buildCommandInfo, collectAllCommands, commandEndMarker, commandStartMarker, compareWithExisting, createCommandRenderer, defaultRenderers, executeExamples, formatDiff, generateDoc, initDocFile, renderArgumentsList, renderArgumentsListFromArray, renderArgumentsTable, renderArgumentsTableFromArray, renderExamplesDefault, renderOptionsList, renderOptionsListFromArray, renderOptionsTable, renderOptionsTableFromArray, renderSubcommandsTable, renderSubcommandsTableFromArray, renderUsage, resolveLazyCommand, writeFile };
1186
+ //#region src/docs/render-args.ts
1187
+ /**
1188
+ * Extract ResolvedFieldMeta array from ArgsShape
1189
+ *
1190
+ * This converts a raw args shape (like `commonArgs`) into the
1191
+ * ResolvedFieldMeta format used by politty's rendering functions.
1192
+ */
1193
+ function extractArgsFields(args) {
1194
+ return extractFields(z.object(args)).fields;
1195
+ }
1196
+ /**
1197
+ * Render args definition as a markdown options table
1198
+ *
1199
+ * This function takes raw args definitions (like `commonArgs`) and
1200
+ * renders them as a markdown table suitable for documentation.
1201
+ *
1202
+ * @example
1203
+ * import { renderArgsTable } from "politty/docs";
1204
+ * import { commonArgs, workspaceArgs } from "./args";
1205
+ *
1206
+ * const table = renderArgsTable({
1207
+ * ...commonArgs,
1208
+ * ...workspaceArgs,
1209
+ * });
1210
+ * // | Option | Alias | Description | Default |
1211
+ * // |--------|-------|-------------|---------|
1212
+ * // | `--env-file <ENV_FILE>` | `-e` | Path to environment file | - |
1213
+ * // ...
1214
+ *
1215
+ * @param args - Args shape (Record of string keys to Zod schemas with arg() metadata)
1216
+ * @param options - Rendering options
1217
+ * @returns Rendered markdown table string
1218
+ */
1219
+ function renderArgsTable(args, options) {
1220
+ const optionFields = extractArgsFields(args).filter((f) => !f.positional);
1221
+ if (optionFields.length === 0) return "";
1222
+ if (options?.columns) return renderFilteredTable(optionFields, options.columns);
1223
+ return renderOptionsTableFromArray(optionFields);
1224
+ }
1225
+ /**
1226
+ * Escape markdown special characters in table cells
1227
+ */
1228
+ function escapeTableCell$1(str) {
1229
+ return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
1230
+ }
1231
+ /**
1232
+ * Format default value for display
1233
+ */
1234
+ function formatDefaultValue(value) {
1235
+ if (value === void 0) return "-";
1236
+ return `\`${JSON.stringify(value)}\``;
1237
+ }
1238
+ /**
1239
+ * Render table with filtered columns
1240
+ */
1241
+ function renderFilteredTable(options, columns) {
1242
+ const lines = [];
1243
+ const headerCells = [];
1244
+ const separatorCells = [];
1245
+ for (const col of columns) switch (col) {
1246
+ case "option":
1247
+ headerCells.push("Option");
1248
+ separatorCells.push("------");
1249
+ break;
1250
+ case "alias":
1251
+ headerCells.push("Alias");
1252
+ separatorCells.push("-----");
1253
+ break;
1254
+ case "description":
1255
+ headerCells.push("Description");
1256
+ separatorCells.push("-----------");
1257
+ break;
1258
+ case "default":
1259
+ headerCells.push("Default");
1260
+ separatorCells.push("-------");
1261
+ break;
1262
+ case "env":
1263
+ headerCells.push("Env");
1264
+ separatorCells.push("---");
1265
+ break;
1266
+ }
1267
+ lines.push(`| ${headerCells.join(" | ")} |`);
1268
+ lines.push(`| ${separatorCells.join(" | ")} |`);
1269
+ for (const opt of options) {
1270
+ const cells = [];
1271
+ for (const col of columns) switch (col) {
1272
+ case "option": {
1273
+ const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, "_");
1274
+ const optionName = opt.type === "boolean" ? `\`--${opt.cliName}\`` : `\`--${opt.cliName} <${placeholder}>\``;
1275
+ cells.push(optionName);
1276
+ break;
1277
+ }
1278
+ case "alias":
1279
+ cells.push(opt.alias ? `\`-${opt.alias}\`` : "-");
1280
+ break;
1281
+ case "description":
1282
+ cells.push(escapeTableCell$1(opt.description ?? ""));
1283
+ break;
1284
+ case "default":
1285
+ cells.push(formatDefaultValue(opt.defaultValue));
1286
+ break;
1287
+ case "env": {
1288
+ const envNames = opt.env ? Array.isArray(opt.env) ? opt.env.map((e) => `\`${e}\``).join(", ") : `\`${opt.env}\`` : "-";
1289
+ cells.push(envNames);
1290
+ break;
1291
+ }
1292
+ }
1293
+ lines.push(`| ${cells.join(" | ")} |`);
1294
+ }
1295
+ return lines.join("\n");
1296
+ }
1297
+
1298
+ //#endregion
1299
+ //#region src/docs/render-index.ts
1300
+ /**
1301
+ * Escape markdown special characters in table cells
1302
+ */
1303
+ function escapeTableCell(str) {
1304
+ return str.replace(/\|/g, "\\|").replace(/\n/g, " ");
1305
+ }
1306
+ /**
1307
+ * Generate anchor from command path
1308
+ */
1309
+ function generateAnchor(commandPath) {
1310
+ return commandPath.replace(/\s+/g, "-").toLowerCase();
1311
+ }
1312
+ /**
1313
+ * Check if a command is a leaf (has no subcommands)
1314
+ */
1315
+ function isLeafCommand(info) {
1316
+ return info.subCommands.length === 0;
1317
+ }
1318
+ /**
1319
+ * Expand commands to include their subcommands
1320
+ * If a command has subcommands, recursively find all commands under it
1321
+ *
1322
+ * @param commandPaths - Command paths to expand
1323
+ * @param allCommands - Map of all available commands
1324
+ * @param leafOnly - If true, only include leaf commands; if false, include all commands
1325
+ */
1326
+ function expandCommands(commandPaths, allCommands, leafOnly) {
1327
+ const result = [];
1328
+ for (const cmdPath of commandPaths) {
1329
+ const info = allCommands.get(cmdPath);
1330
+ if (!info) continue;
1331
+ if (isLeafCommand(info)) result.push(cmdPath);
1332
+ else for (const [path, pathInfo] of allCommands) if (cmdPath === "" ? path.length > 0 : path.startsWith(cmdPath + " ") || path === cmdPath) {
1333
+ if (isLeafCommand(pathInfo) || !leafOnly) result.push(path);
1334
+ }
1335
+ }
1336
+ return result;
1337
+ }
1338
+ /**
1339
+ * Render a single category section
1340
+ */
1341
+ function renderCategory(category, allCommands, headingLevel, leafOnly) {
1342
+ const h = "#".repeat(headingLevel);
1343
+ const lines = [];
1344
+ lines.push(`${h} [${category.title}](${category.docPath})`);
1345
+ lines.push("");
1346
+ lines.push(category.description);
1347
+ lines.push("");
1348
+ const commandPaths = expandCommands(category.commands, allCommands, leafOnly);
1349
+ lines.push("| Command | Description |");
1350
+ lines.push("|---------|-------------|");
1351
+ for (const cmdPath of commandPaths) {
1352
+ const info = allCommands.get(cmdPath);
1353
+ if (!info) continue;
1354
+ if (leafOnly && !isLeafCommand(info)) continue;
1355
+ const displayName = cmdPath || info.name;
1356
+ const anchor = generateAnchor(displayName);
1357
+ const desc = escapeTableCell(info.description ?? "");
1358
+ lines.push(`| [${displayName}](${category.docPath}#${anchor}) | ${desc} |`);
1359
+ }
1360
+ return lines.join("\n");
1361
+ }
1362
+ /**
1363
+ * Render command index from categories
1364
+ *
1365
+ * Generates a category-based index of commands with links to documentation.
1366
+ *
1367
+ * @example
1368
+ * const categories: CommandCategory[] = [
1369
+ * {
1370
+ * title: "Application Commands",
1371
+ * description: "Commands for managing applications.",
1372
+ * commands: ["init", "generate", "apply"],
1373
+ * docPath: "./cli/application.md",
1374
+ * },
1375
+ * ];
1376
+ *
1377
+ * const index = await renderCommandIndex(mainCommand, categories);
1378
+ * // ### [Application Commands](./cli/application.md)
1379
+ * //
1380
+ * // Commands for managing applications.
1381
+ * //
1382
+ * // | Command | Description |
1383
+ * // |---------|-------------|
1384
+ * // | [init](./cli/application.md#init) | Initialize a project |
1385
+ * // ...
1386
+ *
1387
+ * @param command - Root command to extract command information from
1388
+ * @param categories - Category definitions for grouping commands
1389
+ * @param options - Rendering options
1390
+ * @returns Rendered markdown string
1391
+ */
1392
+ async function renderCommandIndex(command, categories, options) {
1393
+ const headingLevel = options?.headingLevel ?? 3;
1394
+ const leafOnly = options?.leafOnly ?? true;
1395
+ const allCommands = await collectAllCommands(command);
1396
+ const sections = [];
1397
+ for (const category of categories) {
1398
+ const section = renderCategory(category, allCommands, headingLevel, leafOnly);
1399
+ sections.push(section);
1400
+ }
1401
+ return sections.join("\n\n");
1402
+ }
1403
+
1404
+ //#endregion
1405
+ export { COMMAND_MARKER_PREFIX, UPDATE_GOLDEN_ENV, assertDocMatch, buildCommandInfo, collectAllCommands, commandEndMarker, commandStartMarker, compareWithExisting, createCommandRenderer, defaultRenderers, executeExamples, formatDiff, generateDoc, initDocFile, renderArgsTable, renderArgumentsList, renderArgumentsListFromArray, renderArgumentsTable, renderArgumentsTableFromArray, renderCommandIndex, renderExamplesDefault, renderOptionsList, renderOptionsListFromArray, renderOptionsTable, renderOptionsTableFromArray, renderSubcommandsTable, renderSubcommandsTableFromArray, renderUsage, resolveLazyCommand, writeFile };
1182
1406
  //# sourceMappingURL=index.js.map