politty 0.2.0 → 0.2.2

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 (32) hide show
  1. package/dist/{command-DCpFEZFM.js → command-D-P2Pc3J.js} +1 -1
  2. package/dist/{command-DCpFEZFM.js.map → command-D-P2Pc3J.js.map} +1 -1
  3. package/dist/completion/index.cjs +1 -0
  4. package/dist/completion/index.cjs.map +1 -1
  5. package/dist/completion/index.js +2 -2
  6. package/dist/docs/index.cjs +47 -21
  7. package/dist/docs/index.cjs.map +1 -1
  8. package/dist/docs/index.d.cts +6 -6
  9. package/dist/docs/index.d.cts.map +1 -1
  10. package/dist/docs/index.d.ts +6 -6
  11. package/dist/docs/index.d.ts.map +1 -1
  12. package/dist/docs/index.js +33 -22
  13. package/dist/docs/index.js.map +1 -1
  14. package/dist/index.cjs +4 -1
  15. package/dist/index.d.cts +30 -1
  16. package/dist/index.d.cts.map +1 -1
  17. package/dist/index.d.ts +30 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +4 -4
  20. package/dist/{runner-ttyvfYGi.cjs → runner-B38UBqhv.cjs} +336 -8
  21. package/dist/runner-B38UBqhv.cjs.map +1 -0
  22. package/dist/{runner-CyxuNkT1.js → runner-CUN50BqK.js} +338 -11
  23. package/dist/runner-CUN50BqK.js.map +1 -0
  24. package/dist/{schema-extractor-D0q5Fj2R.js → schema-extractor-1YXqFSDT.js} +1 -1
  25. package/dist/{schema-extractor-D0q5Fj2R.js.map → schema-extractor-1YXqFSDT.js.map} +1 -1
  26. package/dist/{subcommand-router-D9QSLX56.js → subcommand-router-DtCeT_O9.js} +1 -1
  27. package/dist/{subcommand-router-D9QSLX56.js.map → subcommand-router-DtCeT_O9.js.map} +1 -1
  28. package/package.json +22 -25
  29. package/dist/runner-BkhekqT9.cjs +0 -4
  30. package/dist/runner-CyxuNkT1.js.map +0 -1
  31. package/dist/runner-DzzbIwEy.js +0 -4
  32. package/dist/runner-ttyvfYGi.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["escapeTableCell","formatDefaultValue","generateAnchor","path","fs","getExtractedFields","resolveLazyCommand","createLogCollector","extractFields","z","escapeTableCell"],"sources":["../../src/docs/default-renderers.ts","../../src/docs/doc-comparator.ts","../../src/docs/doc-generator.ts","../../src/docs/example-executor.ts","../../src/docs/types.ts","../../src/docs/golden-test.ts","../../src/docs/render-args.ts","../../src/docs/render-index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { Example } from \"../types.js\";\nimport type {\n ArgumentsRenderContext,\n CommandInfo,\n DefaultRendererOptions,\n ExampleExecutionResult,\n ExamplesRenderContext,\n ExamplesRenderOptions,\n OptionsRenderContext,\n RenderContentOptions,\n RenderFunction,\n SimpleRenderContext,\n SubCommandInfo,\n SubcommandsRenderContext,\n SubcommandsRenderOptions,\n} from \"./types.js\";\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Format default value for display\n */\nfunction formatDefaultValue(value: unknown): string {\n if (value === undefined) {\n return \"-\";\n }\n return `\\`${JSON.stringify(value)}\\``;\n}\n\n/**\n * Render usage line\n */\nexport function renderUsage(info: CommandInfo): string {\n const parts: string[] = [info.fullCommandPath];\n\n if (info.options.length > 0) {\n parts.push(\"[options]\");\n }\n\n if (info.subCommands.length > 0) {\n parts.push(\"[command]\");\n }\n\n for (const arg of info.positionalArgs) {\n if (arg.required) {\n parts.push(`<${arg.name}>`);\n } else {\n parts.push(`[${arg.name}]`);\n }\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Render arguments as table\n */\nexport function renderArgumentsTable(info: CommandInfo): string {\n if (info.positionalArgs.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Argument | Description | Required |\");\n lines.push(\"|----------|-------------|----------|\");\n\n for (const arg of info.positionalArgs) {\n const desc = escapeTableCell(arg.description ?? \"\");\n const required = arg.required ? \"Yes\" : \"No\";\n lines.push(`| \\`${arg.name}\\` | ${desc} | ${required} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments as list\n */\nexport function renderArgumentsList(info: CommandInfo): string {\n if (info.positionalArgs.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const arg of info.positionalArgs) {\n const required = arg.required ? \"(required)\" : \"(optional)\";\n const desc = arg.description ? ` - ${arg.description}` : \"\";\n lines.push(`- \\`${arg.name}\\`${desc} ${required}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format environment variable info for display\n */\nfunction formatEnvInfo(env: string | string[] | undefined): string {\n if (!env) return \"\";\n const envNames = Array.isArray(env) ? env : [env];\n return ` [env: ${envNames.join(\", \")}]`;\n}\n\n/**\n * Format option flags (uses kebab-case cliName)\n */\nfunction formatOptionFlags(opt: ResolvedFieldMeta): string {\n const parts: string[] = [];\n\n // Use cliName (kebab-case) for CLI display\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const longFlag =\n opt.type === \"boolean\" ? `--${opt.cliName}` : `--${opt.cliName} <${placeholder}>`;\n\n if (opt.alias) {\n parts.push(`\\`-${opt.alias}\\`, \\`${longFlag}\\``);\n } else {\n parts.push(`\\`${longFlag}\\``);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Render options as markdown table\n *\n * Features:\n * - Uses kebab-case (cliName) for option names (e.g., `--dry-run` instead of `--dryRun`)\n * - Automatically adds Env column when any option has env configured\n * - Displays multiple env vars as comma-separated list\n *\n * @example\n * | Option | Alias | Description | Default | Env |\n * |--------|-------|-------------|---------|-----|\n * | `--dry-run` | `-d` | Dry run mode | `false` | - |\n * | `--port <PORT>` | - | Server port | - | `PORT`, `SERVER_PORT` |\n */\nexport function renderOptionsTable(info: CommandInfo): string {\n if (info.options.length === 0) {\n return \"\";\n }\n\n // Check if any option has env configured\n const hasEnv = info.options.some((opt) => opt.env);\n\n const lines: string[] = [];\n if (hasEnv) {\n lines.push(\"| Option | Alias | Description | Default | Env |\");\n lines.push(\"|--------|-------|-------------|---------|-----|\");\n } else {\n lines.push(\"| Option | Alias | Description | Default |\");\n lines.push(\"|--------|-------|-------------|---------|\");\n }\n\n for (const opt of info.options) {\n // Use cliName (kebab-case) for CLI display\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\" ? `\\`--${opt.cliName}\\`` : `\\`--${opt.cliName} <${placeholder}>\\``;\n const alias = opt.alias ? `\\`-${opt.alias}\\`` : \"-\";\n const desc = escapeTableCell(opt.description ?? \"\");\n const defaultVal = formatDefaultValue(opt.defaultValue);\n\n if (hasEnv) {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} | ${envNames} |`);\n } else {\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options as markdown list\n *\n * Features:\n * - Uses kebab-case (cliName) for option names (e.g., `--dry-run` instead of `--dryRun`)\n * - Appends env info at the end of each option (e.g., `[env: PORT, SERVER_PORT]`)\n *\n * @example\n * - `-d`, `--dry-run` - Dry run mode (default: false)\n * - `--port <PORT>` - Server port [env: PORT, SERVER_PORT]\n */\nexport function renderOptionsList(info: CommandInfo): string {\n if (info.options.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const opt of info.options) {\n const flags = formatOptionFlags(opt);\n const desc = opt.description ? ` - ${opt.description}` : \"\";\n const defaultVal =\n opt.defaultValue !== undefined ? ` (default: ${JSON.stringify(opt.defaultValue)})` : \"\";\n const envInfo = formatEnvInfo(opt.env);\n lines.push(`- ${flags}${desc}${defaultVal}${envInfo}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate anchor from command path\n */\nfunction generateAnchor(commandPath: string[]): string {\n return commandPath.join(\"-\").toLowerCase();\n}\n\n/**\n * Generate relative path from one file to another\n */\nfunction getRelativePath(from: string, to: string): string {\n const fromParts = from.split(\"/\").slice(0, -1); // directory of 'from'\n const toParts = to.split(\"/\");\n\n // Find common prefix\n let commonLength = 0;\n while (\n commonLength < fromParts.length &&\n commonLength < toParts.length - 1 &&\n fromParts[commonLength] === toParts[commonLength]\n ) {\n commonLength++;\n }\n\n // Build relative path\n const upCount = fromParts.length - commonLength;\n const relativeParts = [...Array(upCount).fill(\"..\"), ...toParts.slice(commonLength)];\n\n return relativeParts.join(\"/\") || (toParts[toParts.length - 1] ?? \"\");\n}\n\n/**\n * Render subcommands as table\n */\nexport function renderSubcommandsTable(info: CommandInfo, generateAnchors = true): string {\n if (info.subCommands.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n const currentFile = info.filePath;\n const fileMap = info.fileMap;\n\n for (const sub of info.subCommands) {\n const fullName = sub.fullPath.join(\" \");\n const desc = escapeTableCell(sub.description ?? \"\");\n const subCommandPath = sub.fullPath.join(\" \");\n\n if (generateAnchors) {\n const anchor = generateAnchor(sub.fullPath);\n const subFile = fileMap?.[subCommandPath];\n\n if (currentFile && subFile && currentFile !== subFile) {\n // Cross-file link\n const relativePath = getRelativePath(currentFile, subFile);\n lines.push(`| [\\`${fullName}\\`](${relativePath}#${anchor}) | ${desc} |`);\n } else {\n // Same-file anchor\n lines.push(`| [\\`${fullName}\\`](#${anchor}) | ${desc} |`);\n }\n } else {\n lines.push(`| \\`${fullName}\\` | ${desc} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options from array as table\n */\nexport function renderOptionsTableFromArray(options: ResolvedFieldMeta[]): string {\n if (options.length === 0) {\n return \"\";\n }\n\n // Check if any option has env configured\n const hasEnv = options.some((opt) => opt.env);\n\n const lines: string[] = [];\n if (hasEnv) {\n lines.push(\"| Option | Alias | Description | Default | Env |\");\n lines.push(\"|--------|-------|-------------|---------|-----|\");\n } else {\n lines.push(\"| Option | Alias | Description | Default |\");\n lines.push(\"|--------|-------|-------------|---------|\");\n }\n\n for (const opt of options) {\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\" ? `\\`--${opt.cliName}\\`` : `\\`--${opt.cliName} <${placeholder}>\\``;\n const alias = opt.alias ? `\\`-${opt.alias}\\`` : \"-\";\n const desc = escapeTableCell(opt.description ?? \"\");\n const defaultVal = formatDefaultValue(opt.defaultValue);\n\n if (hasEnv) {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} | ${envNames} |`);\n } else {\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${defaultVal} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options from array as list\n */\nexport function renderOptionsListFromArray(options: ResolvedFieldMeta[]): string {\n if (options.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const opt of options) {\n const flags = formatOptionFlags(opt);\n const desc = opt.description ? ` - ${opt.description}` : \"\";\n const defaultVal =\n opt.defaultValue !== undefined ? ` (default: ${JSON.stringify(opt.defaultValue)})` : \"\";\n const envInfo = formatEnvInfo(opt.env);\n lines.push(`- ${flags}${desc}${defaultVal}${envInfo}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments from array as table\n */\nexport function renderArgumentsTableFromArray(args: ResolvedFieldMeta[]): string {\n if (args.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Argument | Description | Required |\");\n lines.push(\"|----------|-------------|----------|\");\n\n for (const arg of args) {\n const desc = escapeTableCell(arg.description ?? \"\");\n const required = arg.required ? \"Yes\" : \"No\";\n lines.push(`| \\`${arg.name}\\` | ${desc} | ${required} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments from array as list\n */\nexport function renderArgumentsListFromArray(args: ResolvedFieldMeta[]): string {\n if (args.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const arg of args) {\n const required = arg.required ? \"(required)\" : \"(optional)\";\n const desc = arg.description ? ` - ${arg.description}` : \"\";\n lines.push(`- \\`${arg.name}\\`${desc} ${required}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render subcommands from array as table\n */\nexport function renderSubcommandsTableFromArray(\n subcommands: SubCommandInfo[],\n info: CommandInfo,\n generateAnchors = true,\n): string {\n if (subcommands.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n const currentFile = info.filePath;\n const fileMap = info.fileMap;\n\n for (const sub of subcommands) {\n const fullName = sub.fullPath.join(\" \");\n const desc = escapeTableCell(sub.description ?? \"\");\n const subCommandPath = sub.fullPath.join(\" \");\n\n if (generateAnchors) {\n const anchor = generateAnchor(sub.fullPath);\n const subFile = fileMap?.[subCommandPath];\n\n if (currentFile && subFile && currentFile !== subFile) {\n // Cross-file link\n const relativePath = getRelativePath(currentFile, subFile);\n lines.push(`| [\\`${fullName}\\`](${relativePath}#${anchor}) | ${desc} |`);\n } else {\n // Same-file anchor\n lines.push(`| [\\`${fullName}\\`](#${anchor}) | ${desc} |`);\n }\n } else {\n lines.push(`| \\`${fullName}\\` | ${desc} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render examples as markdown\n *\n * @example\n * **Basic usage**\n *\n * ```bash\n * $ greet World\n * ```\n *\n * Output:\n * ```\n * Hello, World!\n * ```\n */\nexport function renderExamplesDefault(\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n): string {\n if (examples.length === 0) {\n return \"\";\n }\n\n const showOutput = opts?.showOutput ?? true;\n const prefix = opts?.commandPrefix ? `${opts.commandPrefix} ` : \"\";\n const lines: string[] = [];\n\n for (let i = 0; i < examples.length; i++) {\n const example = examples[i];\n if (!example) continue;\n\n const result = results?.[i];\n\n // Description as bold text\n lines.push(`**${example.desc}**`);\n lines.push(\"\");\n\n // Command and output in a single code block\n lines.push(\"```bash\");\n lines.push(`$ ${prefix}${example.cmd}`);\n\n // Output\n if (showOutput) {\n if (result) {\n // Use captured output from execution\n if (result.stdout) {\n lines.push(result.stdout);\n }\n if (result.stderr) {\n lines.push(`[stderr] ${result.stderr}`);\n }\n } else if (example.output) {\n // Use expected output from definition\n lines.push(example.output);\n }\n }\n\n lines.push(\"```\");\n lines.push(\"\");\n }\n\n // Remove trailing empty lines\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Create command renderer with options\n */\nexport function createCommandRenderer(options: DefaultRendererOptions = {}): RenderFunction {\n const {\n headingLevel = 1,\n optionStyle = \"table\",\n generateAnchors = true,\n includeSubcommandDetails = true,\n renderDescription: customRenderDescription,\n renderUsage: customRenderUsage,\n renderArguments: customRenderArguments,\n renderOptions: customRenderOptions,\n renderSubcommands: customRenderSubcommands,\n renderNotes: customRenderNotes,\n renderFooter: customRenderFooter,\n renderExamples: customRenderExamples,\n } = options;\n\n return (info: CommandInfo): string => {\n const lines: string[] = [];\n // Calculate effective heading level based on command depth\n // depth=1 → headingLevel, depth=2 → headingLevel+1, etc.\n const effectiveLevel = Math.min(headingLevel + (info.depth - 1), 6);\n const h = \"#\".repeat(effectiveLevel);\n\n // Title - use commandPath for subcommands, name for root\n const title = info.commandPath || info.name;\n lines.push(`${h} ${title}`);\n lines.push(\"\");\n\n // Description\n if (info.description) {\n const context: SimpleRenderContext = {\n content: info.description,\n heading: \"\",\n info,\n };\n const content = customRenderDescription ? customRenderDescription(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Usage\n {\n const defaultUsage = `**Usage**\\n\\n\\`\\`\\`\\n${renderUsage(info)}\\n\\`\\`\\``;\n const context: SimpleRenderContext = {\n content: defaultUsage,\n heading: \"**Usage**\",\n info,\n };\n const content = customRenderUsage ? customRenderUsage(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Arguments\n if (info.positionalArgs.length > 0) {\n const renderArgs = (args: ResolvedFieldMeta[], opts?: RenderContentOptions): string => {\n const style = opts?.style ?? optionStyle;\n const withHeading = opts?.withHeading ?? true;\n const content =\n style === \"table\"\n ? renderArgumentsTableFromArray(args)\n : renderArgumentsListFromArray(args);\n return withHeading ? `**Arguments**\\n\\n${content}` : content;\n };\n\n const context: ArgumentsRenderContext = {\n args: info.positionalArgs,\n render: renderArgs,\n heading: \"**Arguments**\",\n info,\n };\n\n const content = customRenderArguments\n ? customRenderArguments(context)\n : renderArgs(context.args);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Options\n if (info.options.length > 0) {\n const renderOpts = (opts: ResolvedFieldMeta[], renderOpts?: RenderContentOptions): string => {\n const style = renderOpts?.style ?? optionStyle;\n const withHeading = renderOpts?.withHeading ?? true;\n const content =\n style === \"table\" ? renderOptionsTableFromArray(opts) : renderOptionsListFromArray(opts);\n return withHeading ? `**Options**\\n\\n${content}` : content;\n };\n\n const context: OptionsRenderContext = {\n options: info.options,\n render: renderOpts,\n heading: \"**Options**\",\n info,\n };\n\n const content = customRenderOptions\n ? customRenderOptions(context)\n : renderOpts(context.options);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Subcommands\n if (info.subCommands.length > 0) {\n const effectiveAnchors = generateAnchors && includeSubcommandDetails;\n\n const renderSubs = (subs: SubCommandInfo[], opts?: SubcommandsRenderOptions): string => {\n const anchors = opts?.generateAnchors ?? effectiveAnchors;\n const withHeading = opts?.withHeading ?? true;\n const content = renderSubcommandsTableFromArray(subs, info, anchors);\n return withHeading ? `**Commands**\\n\\n${content}` : content;\n };\n\n const context: SubcommandsRenderContext = {\n subcommands: info.subCommands,\n render: renderSubs,\n heading: \"**Commands**\",\n info,\n };\n\n const content = customRenderSubcommands\n ? customRenderSubcommands(context)\n : renderSubs(context.subcommands);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Examples\n if (info.examples && info.examples.length > 0) {\n const renderEx = (\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n ): string => {\n const withHeading = opts?.withHeading ?? true;\n const mergedOpts: ExamplesRenderOptions = {\n commandPrefix: info.fullCommandPath,\n ...opts,\n };\n const content = renderExamplesDefault(examples, results, mergedOpts);\n return withHeading ? `**Examples**\\n\\n${content}` : content;\n };\n\n const context: ExamplesRenderContext = {\n examples: info.examples,\n results: info.exampleResults,\n render: renderEx,\n heading: \"**Examples**\",\n info,\n };\n\n const content = customRenderExamples\n ? customRenderExamples(context)\n : renderEx(context.examples, context.results);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Notes\n if (info.notes) {\n const context: SimpleRenderContext = {\n content: `**Notes**\\n\\n${info.notes}`,\n heading: \"**Notes**\",\n info,\n };\n const content = customRenderNotes ? customRenderNotes(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Footer (default is empty)\n {\n const context: SimpleRenderContext = {\n content: \"\",\n heading: \"\",\n info,\n };\n const content = customRenderFooter ? customRenderFooter(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Remove trailing empty lines and ensure single newline at end\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n };\n}\n\n/**\n * Default renderers presets\n */\nexport const defaultRenderers = {\n /** Standard command documentation */\n command: (options?: DefaultRendererOptions) => createCommandRenderer(options),\n /** Table style options (default) */\n tableStyle: createCommandRenderer({ optionStyle: \"table\" }),\n /** List style options */\n listStyle: createCommandRenderer({ optionStyle: \"list\" }),\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Comparison result\n */\nexport interface CompareResult {\n /** Whether the content matches */\n match: boolean;\n /** Diff content (only when match is false) */\n diff?: string;\n /** Whether the file exists */\n fileExists: boolean;\n}\n\n/**\n * Compare generated content with existing file\n */\nexport function compareWithExisting(generatedContent: string, filePath: string): CompareResult {\n const absolutePath = path.resolve(filePath);\n\n if (!fs.existsSync(absolutePath)) {\n return {\n match: false,\n fileExists: false,\n };\n }\n\n const existingContent = fs.readFileSync(absolutePath, \"utf-8\");\n\n if (generatedContent === existingContent) {\n return {\n match: true,\n fileExists: true,\n };\n }\n\n return {\n match: false,\n diff: formatDiff(existingContent, generatedContent),\n fileExists: true,\n };\n}\n\n/**\n * Format diff between two strings in unified diff format\n */\nexport function formatDiff(expected: string, actual: string): string {\n const expectedLines = expected.split(\"\\n\");\n const actualLines = actual.split(\"\\n\");\n\n const result: string[] = [];\n result.push(\"--- existing\");\n result.push(\"+++ generated\");\n result.push(\"\");\n\n // Simple line-by-line diff\n const maxLines = Math.max(expectedLines.length, actualLines.length);\n let inChunk = false;\n let chunkStart = 0;\n const chunk: string[] = [];\n\n const flushChunk = (): void => {\n if (chunk.length > 0) {\n result.push(`@@ -${chunkStart + 1},${chunk.length} @@`);\n result.push(...chunk);\n chunk.length = 0;\n }\n inChunk = false;\n };\n\n for (let i = 0; i < maxLines; i++) {\n const expectedLine = expectedLines[i];\n const actualLine = actualLines[i];\n\n if (expectedLine === actualLine) {\n if (inChunk) {\n // Add context line\n chunk.push(` ${expectedLine ?? \"\"}`);\n // If we have more than 3 context lines after a change, flush the chunk\n const lastChangeIndex = chunk.findIndex(\n (line, idx) =>\n (line.startsWith(\"-\") || line.startsWith(\"+\")) &&\n chunk.slice(idx + 1).every((l) => l.startsWith(\" \")),\n );\n if (lastChangeIndex !== -1 && chunk.length - lastChangeIndex > 3) {\n flushChunk();\n }\n }\n } else {\n if (!inChunk) {\n inChunk = true;\n chunkStart = i;\n // Add up to 3 lines of context before\n const contextStart = Math.max(0, i - 3);\n for (let j = contextStart; j < i; j++) {\n chunk.push(` ${expectedLines[j] ?? \"\"}`);\n }\n }\n\n if (expectedLine !== undefined && (actualLine === undefined || expectedLine !== actualLine)) {\n chunk.push(`-${expectedLine}`);\n }\n if (actualLine !== undefined && (expectedLine === undefined || expectedLine !== actualLine)) {\n chunk.push(`+${actualLine}`);\n }\n }\n }\n\n flushChunk();\n\n return result.join(\"\\n\");\n}\n\n/**\n * Write content to file, creating directories if needed\n */\nexport function writeFile(filePath: string, content: string): void {\n const absolutePath = path.resolve(filePath);\n const dir = path.dirname(absolutePath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n fs.writeFileSync(absolutePath, content, \"utf-8\");\n}\n\n/**\n * Read file content if it exists\n * Returns null if file does not exist\n */\nexport function readFile(filePath: string): string | null {\n const absolutePath = path.resolve(filePath);\n\n if (!fs.existsSync(absolutePath)) {\n return null;\n }\n\n return fs.readFileSync(absolutePath, \"utf-8\");\n}\n\n/**\n * Minimal fs interface for deleteFile\n */\nexport interface DeleteFileFs {\n existsSync: typeof fs.existsSync;\n unlinkSync: typeof fs.unlinkSync;\n}\n\n/**\n * Delete file if it exists\n * @param filePath - Path to the file to delete\n * @param fileSystem - Optional fs implementation (useful when fs is mocked)\n */\nexport function deleteFile(filePath: string, fileSystem: DeleteFileFs = fs): void {\n const absolutePath = path.resolve(filePath);\n\n if (fileSystem.existsSync(absolutePath)) {\n fileSystem.unlinkSync(absolutePath);\n }\n}\n","import { getExtractedFields } from \"../core/schema-extractor.js\";\nimport { resolveLazyCommand } from \"../executor/subcommand-router.js\";\nimport type { AnyCommand } from \"../types.js\";\nimport type { CommandInfo, SubCommandInfo } from \"./types.js\";\n\n/**\n * Build CommandInfo from a command\n */\nexport async function buildCommandInfo(\n command: AnyCommand,\n rootName: string,\n commandPath: string[] = [],\n): Promise<CommandInfo> {\n const extracted = getExtractedFields(command);\n\n const positionalArgs = extracted?.fields.filter((f) => f.positional) ?? [];\n const options = extracted?.fields.filter((f) => !f.positional) ?? [];\n\n const subCommands: SubCommandInfo[] = [];\n if (command.subCommands) {\n for (const [name, subCmd] of Object.entries(command.subCommands)) {\n const resolved = await resolveLazyCommand(subCmd);\n const fullPath = [...commandPath, name];\n subCommands.push({\n name,\n description: resolved.description,\n fullPath,\n });\n }\n }\n\n return {\n name: command.name ?? \"\",\n description: command.description,\n fullCommandPath: commandPath.length > 0 ? `${rootName} ${commandPath.join(\" \")}` : rootName,\n commandPath: commandPath.join(\" \"),\n depth: commandPath.length + 1,\n positionalArgs,\n options,\n subCommands,\n extracted,\n command,\n notes: command.notes,\n examples: command.examples,\n };\n}\n\n/**\n * Collect all commands with their paths\n * Returns a map of command path -> CommandInfo\n */\nexport async function collectAllCommands(\n command: AnyCommand,\n rootName?: string,\n): Promise<Map<string, CommandInfo>> {\n const root = rootName ?? command.name ?? \"command\";\n const result = new Map<string, CommandInfo>();\n\n async function traverse(cmd: AnyCommand, path: string[]): Promise<void> {\n const info = await buildCommandInfo(cmd, root, path);\n const pathKey = path.join(\" \");\n result.set(pathKey, info);\n\n if (cmd.subCommands) {\n for (const [name, subCmd] of Object.entries(cmd.subCommands)) {\n const resolved = await resolveLazyCommand(subCmd);\n await traverse(resolved, [...path, name]);\n }\n }\n }\n\n await traverse(command, []);\n return result;\n}\n","import { createLogCollector } from \"../executor/log-collector.js\";\nimport type { AnyCommand, Example } from \"../types.js\";\nimport type { ExampleCommandConfig, ExampleExecutionResult } from \"./types.js\";\n\n/**\n * Execute examples for a command and capture output\n *\n * @param examples - Examples to execute\n * @param config - Execution configuration (mock setup/cleanup)\n * @param rootCommand - Root command to execute against\n * @param commandPath - Command path for subcommands (e.g., [\"config\", \"get\"])\n * @returns Array of execution results with captured stdout/stderr\n */\nexport async function executeExamples(\n examples: Example[],\n config: ExampleCommandConfig,\n rootCommand: AnyCommand,\n commandPath: string[] = [],\n): Promise<ExampleExecutionResult[]> {\n const results: ExampleExecutionResult[] = [];\n\n // Setup mock if provided\n if (config.mock) {\n await config.mock();\n }\n\n try {\n for (const example of examples) {\n const result = await executeSingleExample(example, rootCommand, commandPath);\n results.push(result);\n }\n } finally {\n // Cleanup mock if provided\n if (config.cleanup) {\n await config.cleanup();\n }\n }\n\n return results;\n}\n\n/**\n * Execute a single example and capture output\n */\nasync function executeSingleExample(\n example: Example,\n rootCommand: AnyCommand,\n commandPath: string[],\n): Promise<ExampleExecutionResult> {\n // Parse command string into argv\n const exampleArgs = parseExampleCmd(example.cmd);\n\n // Build full argv: command path + example args\n const argv = [...commandPath, ...exampleArgs];\n\n // Use unified log collector (don't passthrough to console)\n const collector = createLogCollector({ passthrough: false });\n collector.start();\n\n let success = true;\n try {\n // Import runCommand dynamically to avoid circular dependency\n const { runCommand } = await import(\"../core/runner.js\");\n const result = await runCommand(rootCommand, argv);\n success = result.success;\n\n // Also capture any errors from the result\n if (!result.success && result.error) {\n console.error(result.error.message);\n }\n } catch (error) {\n success = false;\n console.error(error instanceof Error ? error.message : String(error));\n } finally {\n collector.stop();\n }\n\n // Convert entries to stdout/stderr strings\n const logs = collector.getLogs();\n const stdout = logs.entries\n .filter((e) => e.stream === \"stdout\")\n .map((e) => e.message)\n .join(\"\\n\");\n const stderr = logs.entries\n .filter((e) => e.stream === \"stderr\")\n .map((e) => e.message)\n .join(\"\\n\");\n\n return {\n cmd: example.cmd,\n desc: example.desc,\n expectedOutput: example.output,\n stdout,\n stderr,\n success,\n };\n}\n\n/**\n * Parse example command string into argv array\n * Handles quoted strings (single and double quotes)\n *\n * @example\n * parseExampleCmd('World') // ['World']\n * parseExampleCmd('--name \"John Doe\"') // ['--name', 'John Doe']\n * parseExampleCmd(\"--greeting 'Hello World'\") // ['--greeting', 'Hello World']\n */\nfunction parseExampleCmd(cmd: string): string[] {\n const args: string[] = [];\n let current = \"\";\n let inQuote = false;\n let quoteChar = \"\";\n\n for (let i = 0; i < cmd.length; i++) {\n const char = cmd[i]!;\n\n if ((char === '\"' || char === \"'\") && !inQuote) {\n inQuote = true;\n quoteChar = char;\n } else if (char === quoteChar && inQuote) {\n inQuote = false;\n quoteChar = \"\";\n } else if (char === \" \" && !inQuote) {\n if (current) {\n args.push(current);\n current = \"\";\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n args.push(current);\n }\n\n return args;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { AnyCommand, Example } from \"../types.js\";\n\n/**\n * Command information for rendering\n */\nexport interface CommandInfo {\n /** Command name */\n name: string;\n /** Command description */\n description?: string | undefined;\n /** Full command path (e.g., \"my-cli config get\") */\n fullCommandPath: string;\n /** Command path relative to root (e.g., \"\" for root, \"config\" for subcommand) */\n commandPath: string;\n /** Command depth (1 for root commands, 2 for subcommands, etc.) */\n depth: number;\n /** Positional arguments */\n positionalArgs: ResolvedFieldMeta[];\n /** Options (non-positional arguments) */\n options: ResolvedFieldMeta[];\n /** Subcommand information */\n subCommands: SubCommandInfo[];\n /** Extracted field information from schema */\n extracted: ExtractedFields | null;\n /** Original command object */\n command: AnyCommand;\n /** Additional notes */\n notes?: string | undefined;\n /** File path where this command is rendered (for cross-file links) */\n filePath?: string | undefined;\n /** Map of command path to file path (for cross-file links) */\n fileMap?: Record<string, string> | undefined;\n /** Example definitions from command */\n examples?: Example[] | undefined;\n /** Example execution results (populated when examples are executed) */\n exampleResults?: ExampleExecutionResult[] | undefined;\n}\n\n/**\n * Subcommand information\n */\nexport interface SubCommandInfo {\n /** Subcommand name */\n name: string;\n /** Subcommand description */\n description?: string | undefined;\n /** Full command path */\n fullPath: string[];\n}\n\n/**\n * Example execution result\n */\nexport interface ExampleExecutionResult {\n /** Command arguments that were executed */\n cmd: string;\n /** Description of the example */\n desc: string;\n /** Expected output (if defined in example) */\n expectedOutput?: string | undefined;\n /** Captured stdout */\n stdout: string;\n /** Captured stderr */\n stderr: string;\n /** Whether execution was successful */\n success: boolean;\n}\n\n/**\n * Example execution config for a specific command path\n * If a command path is specified in ExampleConfig, its examples will be executed\n */\nexport interface ExampleCommandConfig {\n /** Mock setup before running examples */\n mock?: () => void | Promise<void>;\n /** Mock cleanup after running examples */\n cleanup?: () => void | Promise<void>;\n}\n\n/**\n * Example execution configuration\n * Key is command path (e.g., \"\", \"config\", \"config get\")\n * All specified command paths will have their examples executed\n *\n * @example\n * // With mock setup\n * { \"\": { mock: () => mockFs(), cleanup: () => restoreFs() } }\n *\n * // Without mock (just execute)\n * { \"user\": true }\n */\nexport type ExampleConfig = Record<string, ExampleCommandConfig | true>;\n\n/**\n * Render function type for custom markdown generation\n */\nexport type RenderFunction = (info: CommandInfo) => string;\n\n/**\n * Section render function type (legacy)\n * @param defaultContent - The default rendered content for this section\n * @param info - Command information\n * @returns The final content to render (return empty string to hide section)\n * @deprecated Use context-based render functions instead\n */\nexport type SectionRenderFunction = (defaultContent: string, info: CommandInfo) => string;\n\n/**\n * Render options for options/arguments\n */\nexport interface RenderContentOptions {\n /** Style for rendering */\n style?: \"table\" | \"list\";\n /** Include heading (default: true) */\n withHeading?: boolean;\n}\n\n/**\n * Options render context\n */\nexport interface OptionsRenderContext {\n /** Options to render */\n options: ResolvedFieldMeta[];\n /** Render function that accepts options and optional rendering options */\n render: (options: ResolvedFieldMeta[], opts?: RenderContentOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type OptionsRenderFunction = (context: OptionsRenderContext) => string;\n\n/**\n * Arguments render context\n */\nexport interface ArgumentsRenderContext {\n /** Arguments to render */\n args: ResolvedFieldMeta[];\n /** Render function that accepts arguments and optional rendering options */\n render: (args: ResolvedFieldMeta[], opts?: RenderContentOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type ArgumentsRenderFunction = (context: ArgumentsRenderContext) => string;\n\n/**\n * Subcommands render options\n */\nexport interface SubcommandsRenderOptions {\n /** Generate anchor links */\n generateAnchors?: boolean;\n /** Include heading (default: true) */\n withHeading?: boolean;\n}\n\n/**\n * Subcommands render context\n */\nexport interface SubcommandsRenderContext {\n /** Subcommands to render */\n subcommands: SubCommandInfo[];\n /** Render function that accepts subcommands and optional rendering options */\n render: (subcommands: SubCommandInfo[], opts?: SubcommandsRenderOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type SubcommandsRenderFunction = (context: SubcommandsRenderContext) => string;\n\n/**\n * Examples render options\n */\nexport interface ExamplesRenderOptions {\n /** Include heading (default: true) */\n withHeading?: boolean;\n /** Show execution output (default: true when results available) */\n showOutput?: boolean;\n /** Command prefix to prepend to example commands (e.g., \"my-cli config get\") */\n commandPrefix?: string;\n}\n\n/**\n * Examples render context\n */\nexport interface ExamplesRenderContext {\n /** Examples to render */\n examples: Example[];\n /** Execution results (if examples were executed) */\n results?: ExampleExecutionResult[] | undefined;\n /** Render function that accepts examples, results, and optional rendering options */\n render: (\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n ) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type ExamplesRenderFunction = (context: ExamplesRenderContext) => string;\n\n/**\n * Simple section render context (for description, usage, notes, footer)\n */\nexport interface SimpleRenderContext {\n /** Default content */\n content: string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type SimpleRenderFunction = (context: SimpleRenderContext) => string;\n\n/**\n * Default renderer customization options\n */\nexport interface DefaultRendererOptions {\n /** Heading level (default: 1) */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Option display style */\n optionStyle?: \"table\" | \"list\";\n /** Generate anchor links to subcommands */\n generateAnchors?: boolean;\n /** Include subcommand details */\n includeSubcommandDetails?: boolean;\n /** Custom renderer for description section */\n renderDescription?: SimpleRenderFunction;\n /** Custom renderer for usage section */\n renderUsage?: SimpleRenderFunction;\n /** Custom renderer for arguments section */\n renderArguments?: ArgumentsRenderFunction;\n /** Custom renderer for options section */\n renderOptions?: OptionsRenderFunction;\n /** Custom renderer for subcommands section */\n renderSubcommands?: SubcommandsRenderFunction;\n /** Custom renderer for notes section */\n renderNotes?: SimpleRenderFunction;\n /** Custom renderer for footer (default content is empty) */\n renderFooter?: SimpleRenderFunction;\n /** Custom renderer for examples section */\n renderExamples?: ExamplesRenderFunction;\n}\n\n/**\n * Per-file configuration with custom renderer\n */\nexport interface FileConfig {\n /** Command paths to include in this file (e.g., [\"\", \"user\", \"config get\"]) */\n commands: string[];\n /** Custom renderer for this file (optional) */\n render?: RenderFunction;\n /** File title (prepended to the file content) */\n title?: string;\n /** File description (added after title) */\n description?: string;\n}\n\n/**\n * File mapping configuration\n * Key: output file path (e.g., \"docs/cli.md\")\n * Value: command paths array or FileConfig object\n *\n * @example\n * // Simple: single file with multiple commands\n * { \"docs/cli.md\": [\"\", \"user\", \"config\"] }\n *\n * // With custom renderer\n * { \"docs/cli.md\": { commands: [\"\"], render: customRenderer } }\n */\nexport type FileMapping = Record<string, string[] | FileConfig>;\n\n/**\n * generateDoc configuration\n */\nexport interface GenerateDocConfig {\n /** Command to generate documentation for */\n command: AnyCommand;\n /** File output configuration (command path -> file mapping) */\n files: FileMapping;\n /** Command paths to ignore (including their subcommands) */\n ignores?: string[];\n /** Default renderer options (used when render is not specified per file) */\n format?: DefaultRendererOptions;\n /** Formatter function to apply to generated content before comparison */\n formatter?: FormatterFunction;\n /** Example execution configuration (per command path) */\n examples?: ExampleConfig;\n /**\n * Target command paths to validate (e.g., [\"read\", \"config get\"])\n * When specified, only these commands' sections are validated.\n * The full document structure is used to maintain cross-file links.\n */\n targetCommands?: string[];\n}\n\n/**\n * generateDoc result\n */\nexport interface GenerateDocResult {\n /** Whether all files matched or were updated successfully */\n success: boolean;\n /** File processing results */\n files: Array<{\n /** File path */\n path: string;\n /** Status of this file */\n status: \"match\" | \"created\" | \"updated\" | \"diff\";\n /** Diff content (only when status is \"diff\") */\n diff?: string | undefined;\n }>;\n /** Error message (when success is false) */\n error?: string | undefined;\n}\n\n/**\n * Formatter function type\n * Formats generated content before comparison\n */\nexport type FormatterFunction = (content: string) => string | Promise<string>;\n\n/**\n * Environment variable name for update mode\n */\nexport const UPDATE_GOLDEN_ENV = \"POLITTY_DOCS_UPDATE\";\n\n/**\n * Marker prefix for command sections in generated documentation\n * Format: <!-- politty:command:<path>:start --> ... <!-- politty:command:<path>:end -->\n */\nexport const COMMAND_MARKER_PREFIX = \"politty:command\";\n\n/**\n * Generate start marker for a command section\n */\nexport function commandStartMarker(commandPath: string): string {\n return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:start -->`;\n}\n\n/**\n * Generate end marker for a command section\n */\nexport function commandEndMarker(commandPath: string): string {\n return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:end -->`;\n}\n","import { createCommandRenderer } from \"./default-renderers.js\";\nimport {\n compareWithExisting,\n deleteFile,\n formatDiff,\n readFile,\n writeFile,\n type DeleteFileFs,\n} from \"./doc-comparator.js\";\nimport { collectAllCommands } from \"./doc-generator.js\";\nimport { executeExamples } from \"./example-executor.js\";\nimport type {\n CommandInfo,\n ExampleConfig,\n FileConfig,\n FormatterFunction,\n GenerateDocConfig,\n GenerateDocResult,\n RenderFunction,\n} from \"./types.js\";\nimport { commandEndMarker, commandStartMarker, UPDATE_GOLDEN_ENV } from \"./types.js\";\n\n/**\n * Apply formatter to content if provided\n * Supports both sync and async formatters\n */\nasync function applyFormatter(\n content: string,\n formatter: FormatterFunction | undefined,\n): Promise<string> {\n if (!formatter) {\n return content;\n }\n return await formatter(content);\n}\n\n/**\n * Check if update mode is enabled via environment variable\n */\nfunction isUpdateMode(): boolean {\n const value = process.env[UPDATE_GOLDEN_ENV];\n return value === \"true\" || value === \"1\";\n}\n\n/**\n * Normalize file mapping entry to FileConfig\n */\nfunction normalizeFileConfig(config: string[] | FileConfig): FileConfig {\n if (Array.isArray(config)) {\n return { commands: config };\n }\n return config;\n}\n\n/**\n * Check if a command path is a subcommand of another\n */\nfunction isSubcommandOf(childPath: string, parentPath: string): boolean {\n if (parentPath === \"\") return true; // Root is parent of everything\n if (childPath === parentPath) return true;\n return childPath.startsWith(parentPath + \" \");\n}\n\n/**\n * Check if a pattern contains wildcards\n */\nfunction containsWildcard(pattern: string): boolean {\n return pattern.includes(\"*\");\n}\n\n/**\n * Check if a command path matches a wildcard pattern\n * - `*` matches any single command segment\n * - Pattern segments are space-separated\n *\n * @example\n * matchesWildcard(\"config get\", \"* *\") // true\n * matchesWildcard(\"config\", \"* *\") // false\n * matchesWildcard(\"config get\", \"config *\") // true\n * matchesWildcard(\"greet\", \"*\") // true\n */\nfunction matchesWildcard(path: string, pattern: string): boolean {\n const pathSegments = path === \"\" ? [] : path.split(\" \");\n const patternSegments = pattern === \"\" ? [] : pattern.split(\" \");\n\n if (pathSegments.length !== patternSegments.length) {\n return false;\n }\n\n for (let i = 0; i < patternSegments.length; i++) {\n const patternSeg = patternSegments[i]!;\n const pathSeg = pathSegments[i]!;\n\n if (patternSeg !== \"*\" && patternSeg !== pathSeg) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Expand a wildcard pattern to matching command paths\n */\nfunction expandWildcardPattern(pattern: string, allCommands: Map<string, CommandInfo>): string[] {\n const matches: string[] = [];\n\n for (const cmdPath of allCommands.keys()) {\n if (matchesWildcard(cmdPath, pattern)) {\n matches.push(cmdPath);\n }\n }\n\n return matches;\n}\n\n/**\n * Check if a path matches any ignore pattern (with wildcard support)\n * For wildcard patterns, also ignores subcommands of matched commands\n */\nfunction matchesIgnorePattern(path: string, ignorePattern: string): boolean {\n if (containsWildcard(ignorePattern)) {\n // Check if path matches the wildcard pattern exactly\n if (matchesWildcard(path, ignorePattern)) {\n return true;\n }\n // Check if path is a subcommand of any command matching the pattern\n // e.g., \"config get\" is a subcommand of \"config\" which matches \"*\"\n const pathSegments = path === \"\" ? [] : path.split(\" \");\n const patternSegments = ignorePattern === \"\" ? [] : ignorePattern.split(\" \");\n\n // If path is deeper than pattern, check if prefix matches\n if (pathSegments.length > patternSegments.length) {\n const prefixPath = pathSegments.slice(0, patternSegments.length).join(\" \");\n return matchesWildcard(prefixPath, ignorePattern);\n }\n return false;\n }\n // For non-wildcards, use original subcommand logic\n return isSubcommandOf(path, ignorePattern);\n}\n\n/**\n * Expand command paths to include all subcommands (with wildcard support)\n */\nfunction expandCommandPaths(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n): string[] {\n const expanded = new Set<string>();\n\n for (const cmdPath of commandPaths) {\n if (containsWildcard(cmdPath)) {\n // Expand wildcard pattern to matching commands\n const matches = expandWildcardPattern(cmdPath, allCommands);\n for (const match of matches) {\n expanded.add(match);\n // Also add subcommands of matched commands\n for (const path of allCommands.keys()) {\n if (isSubcommandOf(path, match)) {\n expanded.add(path);\n }\n }\n }\n } else {\n // Add the command itself\n if (allCommands.has(cmdPath)) {\n expanded.add(cmdPath);\n }\n // Add all subcommands\n for (const path of allCommands.keys()) {\n if (isSubcommandOf(path, cmdPath)) {\n expanded.add(path);\n }\n }\n }\n }\n\n return Array.from(expanded);\n}\n\n/**\n * Filter out ignored commands (with wildcard support)\n */\nfunction filterIgnoredCommands(commandPaths: string[], ignores: string[]): string[] {\n return commandPaths.filter((path) => {\n return !ignores.some((ignorePattern) => matchesIgnorePattern(path, ignorePattern));\n });\n}\n\n/**\n * Validate that there are no conflicts between files and ignores (with wildcard support)\n */\nfunction validateNoConflicts(\n filesCommands: string[],\n ignores: string[],\n allCommands: Map<string, CommandInfo>,\n): void {\n const conflicts: string[] = [];\n\n for (const filePattern of filesCommands) {\n // Expand file pattern if it's a wildcard\n const filePaths = containsWildcard(filePattern)\n ? expandWildcardPattern(filePattern, allCommands)\n : [filePattern];\n\n for (const filePath of filePaths) {\n for (const ignorePattern of ignores) {\n if (containsWildcard(ignorePattern)) {\n // For wildcard ignores, check if file path matches the pattern\n if (matchesWildcard(filePath, ignorePattern)) {\n conflicts.push(`\"${filePath}\" is both in files and ignored by \"${ignorePattern}\"`);\n }\n } else {\n // For non-wildcard ignores, use original logic\n if (filePath === ignorePattern || isSubcommandOf(filePath, ignorePattern)) {\n conflicts.push(`\"${filePath}\" is both in files and ignored by \"${ignorePattern}\"`);\n }\n }\n }\n }\n }\n\n if (conflicts.length > 0) {\n throw new Error(`Conflict between files and ignores:\\n - ${conflicts.join(\"\\n - \")}`);\n }\n}\n\n/**\n * Validate that all ignored paths exist in the command tree (with wildcard support)\n */\nfunction validateIgnoresExist(ignores: string[], allCommands: Map<string, CommandInfo>): void {\n const nonExistent: string[] = [];\n\n for (const ignorePattern of ignores) {\n if (containsWildcard(ignorePattern)) {\n // For wildcard patterns, check if at least one command matches\n const matches = expandWildcardPattern(ignorePattern, allCommands);\n if (matches.length === 0) {\n nonExistent.push(`\"${ignorePattern}\"`);\n }\n } else {\n // For non-wildcard paths, check exact existence\n if (!allCommands.has(ignorePattern)) {\n nonExistent.push(`\"${ignorePattern}\"`);\n }\n }\n }\n\n if (nonExistent.length > 0) {\n throw new Error(`Ignored command paths do not exist: ${nonExistent.join(\", \")}`);\n }\n}\n\n/**\n * Sort command paths in depth-first order while preserving the specified command order\n * Parent commands are immediately followed by their subcommands\n */\nfunction sortDepthFirst(commandPaths: string[], specifiedOrder: string[]): string[] {\n // Build a set of all paths for quick lookup\n const pathSet = new Set(commandPaths);\n\n // Find top-level commands (those that match specified order or have no parent in the set)\n const topLevelPaths = specifiedOrder.filter((cmd) => pathSet.has(cmd));\n\n // Also include any commands not in specifiedOrder (for safety)\n for (const path of commandPaths) {\n const depth = path === \"\" ? 0 : path.split(\" \").length;\n if (depth === 1 && !topLevelPaths.includes(path)) {\n topLevelPaths.push(path);\n }\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n\n function addWithChildren(cmdPath: string): void {\n if (visited.has(cmdPath) || !pathSet.has(cmdPath)) return;\n visited.add(cmdPath);\n result.push(cmdPath);\n\n // Find and add direct children in alphabetical order\n const children = commandPaths\n .filter((p) => {\n if (p === cmdPath || visited.has(p)) return false;\n // Check if p is a direct child of cmdPath\n if (cmdPath === \"\") {\n return p.split(\" \").length === 1;\n }\n return p.startsWith(cmdPath + \" \") && p.split(\" \").length === cmdPath.split(\" \").length + 1;\n })\n .sort((a, b) => a.localeCompare(b));\n\n for (const child of children) {\n addWithChildren(child);\n }\n }\n\n // Start with top-level commands in specified order\n for (const topLevel of topLevelPaths) {\n addWithChildren(topLevel);\n }\n\n // Add any remaining paths (shouldn't happen normally)\n for (const path of commandPaths) {\n if (!visited.has(path)) {\n result.push(path);\n }\n }\n\n return result;\n}\n\n/**\n * Generate file header from FileConfig\n */\nfunction generateFileHeader(fileConfig: FileConfig): string | null {\n if (!fileConfig.title && !fileConfig.description) {\n return null;\n }\n\n const parts: string[] = [];\n if (fileConfig.title) {\n parts.push(`# ${fileConfig.title}`);\n }\n if (fileConfig.description) {\n parts.push(\"\");\n parts.push(fileConfig.description);\n }\n parts.push(\"\");\n\n return parts.join(\"\\n\");\n}\n\n/**\n * Extract a command section from content using markers\n * Returns the content between start and end markers (including markers)\n */\nfunction extractCommandSection(content: string, commandPath: string): string | null {\n const startMarker = commandStartMarker(commandPath);\n const endMarker = commandEndMarker(commandPath);\n\n const startIndex = content.indexOf(startMarker);\n if (startIndex === -1) {\n return null;\n }\n\n const endIndex = content.indexOf(endMarker, startIndex);\n if (endIndex === -1) {\n return null;\n }\n\n return content.slice(startIndex, endIndex + endMarker.length);\n}\n\n/**\n * Replace a command section in content using markers\n * Returns the updated content with the new section\n */\nfunction replaceCommandSection(\n content: string,\n commandPath: string,\n newSection: string,\n): string | null {\n const startMarker = commandStartMarker(commandPath);\n const endMarker = commandEndMarker(commandPath);\n\n const startIndex = content.indexOf(startMarker);\n if (startIndex === -1) {\n return null;\n }\n\n const endIndex = content.indexOf(endMarker, startIndex);\n if (endIndex === -1) {\n return null;\n }\n\n return content.slice(0, startIndex) + newSection + content.slice(endIndex + endMarker.length);\n}\n\n/**\n * Insert a command section at the correct position based on specified order\n * Returns the updated content with the section inserted at the right position\n */\nfunction insertCommandSection(\n content: string,\n commandPath: string,\n newSection: string,\n specifiedOrder: string[],\n): string {\n // Find the index of the target command in the specified order\n const targetIndex = specifiedOrder.indexOf(commandPath);\n if (targetIndex === -1) {\n // If not in order, append to end\n return content.trimEnd() + \"\\n\\n\" + newSection + \"\\n\";\n }\n\n // Find the next command in the order that exists in the content\n for (let i = targetIndex + 1; i < specifiedOrder.length; i++) {\n const nextCmd = specifiedOrder[i];\n if (nextCmd === undefined) continue;\n const nextMarker = commandStartMarker(nextCmd);\n const nextIndex = content.indexOf(nextMarker);\n if (nextIndex !== -1) {\n // Insert before the next section\n // Find the start of the line (after previous section's newlines)\n let insertPos = nextIndex;\n // Go back to find proper insertion point (skip leading newlines)\n while (insertPos > 0 && content[insertPos - 1] === \"\\n\") {\n insertPos--;\n }\n // Keep one newline as separator\n if (insertPos < nextIndex) {\n insertPos++;\n }\n return content.slice(0, insertPos) + newSection + \"\\n\" + content.slice(nextIndex);\n }\n }\n\n // Find the previous command in the order that exists in the content\n for (let i = targetIndex - 1; i >= 0; i--) {\n const prevCmd = specifiedOrder[i];\n if (prevCmd === undefined) continue;\n const prevEndMarker = commandEndMarker(prevCmd);\n const prevEndIndex = content.indexOf(prevEndMarker);\n if (prevEndIndex !== -1) {\n // Insert after the previous section\n const insertPos = prevEndIndex + prevEndMarker.length;\n return content.slice(0, insertPos) + \"\\n\" + newSection + content.slice(insertPos);\n }\n }\n\n // No reference point found, append to end\n return content.trimEnd() + \"\\n\" + newSection + \"\\n\";\n}\n\n/**\n * Find which file contains a specific command\n */\nfunction findFileForCommand(\n commandPath: string,\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): string | null {\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n if (commandPaths.includes(commandPath)) {\n return filePath;\n }\n }\n return null;\n}\n\n/**\n * Find which target commands are contained in a file\n * Also expands each target command to include subcommands that are NOT explicitly in specifiedCommands\n */\nfunction findTargetCommandsInFile(\n targetCommands: string[],\n filePath: string,\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): string[] {\n const fileConfigRaw = files[filePath];\n if (!fileConfigRaw) return [];\n\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n // Expand targetCommands to include their subcommands,\n // but exclude subcommands that are explicitly in specifiedCommands\n const expandedTargets = new Set<string>();\n for (const targetCmd of targetCommands) {\n if (!commandPaths.includes(targetCmd)) continue;\n\n // Add the target command itself\n expandedTargets.add(targetCmd);\n\n // Add subcommands that are NOT explicitly specified\n for (const cmdPath of commandPaths) {\n if (isSubcommandOf(cmdPath, targetCmd) && !specifiedCommands.includes(cmdPath)) {\n expandedTargets.add(cmdPath);\n }\n }\n }\n\n return Array.from(expandedTargets);\n}\n\n/**\n * Generate a single command section with markers\n */\nfunction generateCommandSection(\n cmdPath: string,\n allCommands: Map<string, CommandInfo>,\n render: RenderFunction,\n filePath?: string,\n fileMap?: Record<string, string>,\n): string | null {\n const info = allCommands.get(cmdPath);\n if (!info) return null;\n\n // Add file context to CommandInfo for cross-file link generation\n const infoWithFileContext: CommandInfo = {\n ...info,\n filePath,\n fileMap,\n };\n\n const renderedSection = render(infoWithFileContext);\n\n // Wrap section with markers for partial validation\n return [commandStartMarker(cmdPath), renderedSection, commandEndMarker(cmdPath)].join(\"\\n\");\n}\n\n/**\n * Generate markdown for a file containing multiple commands\n * Each command section is wrapped with markers for partial validation\n */\nfunction generateFileMarkdown(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n render: RenderFunction,\n filePath?: string,\n fileMap?: Record<string, string>,\n specifiedOrder?: string[],\n fileConfig?: FileConfig,\n): string {\n const sections: string[] = [];\n\n // Add file header if title or description is provided\n const header = fileConfig ? generateFileHeader(fileConfig) : null;\n if (header) {\n sections.push(header);\n }\n\n // Sort commands depth-first while preserving specified order\n const sortedPaths = sortDepthFirst(commandPaths, specifiedOrder ?? []);\n\n for (const cmdPath of sortedPaths) {\n const section = generateCommandSection(cmdPath, allCommands, render, filePath, fileMap);\n if (section) {\n sections.push(section);\n }\n }\n\n return sections.join(\"\\n\");\n}\n\n/**\n * Build a map of command path to file path\n */\nfunction buildFileMap(\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): Record<string, string> {\n const fileMap: Record<string, string> = {};\n\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n for (const cmdPath of commandPaths) {\n fileMap[cmdPath] = filePath;\n }\n }\n\n return fileMap;\n}\n\n/**\n * Execute examples for commands based on configuration\n */\nasync function executeConfiguredExamples(\n allCommands: Map<string, CommandInfo>,\n examplesConfig: ExampleConfig,\n rootCommand: import(\"../types.js\").AnyCommand,\n): Promise<void> {\n for (const [cmdPath, cmdConfig] of Object.entries(examplesConfig)) {\n const commandInfo = allCommands.get(cmdPath);\n if (!commandInfo?.examples?.length) {\n continue;\n }\n\n // Normalize config: true means no mock setup\n const config = cmdConfig === true ? {} : cmdConfig;\n\n // Parse command path into array\n const commandPath = cmdPath ? cmdPath.split(\" \") : [];\n\n // Execute examples and store results\n const results = await executeExamples(commandInfo.examples, config, rootCommand, commandPath);\n\n // Update CommandInfo with execution results\n commandInfo.exampleResults = results;\n }\n}\n\n/**\n * Generate documentation from command definition\n */\nexport async function generateDoc(config: GenerateDocConfig): Promise<GenerateDocResult> {\n const {\n command,\n files,\n ignores = [],\n format = {},\n formatter,\n examples: examplesConfig,\n targetCommands,\n } = config;\n const updateMode = isUpdateMode();\n\n // Collect all commands\n const allCommands = await collectAllCommands(command);\n\n // Execute examples for all commands specified in examplesConfig\n if (examplesConfig) {\n await executeConfiguredExamples(allCommands, examplesConfig, command);\n }\n\n // Collect all explicitly specified commands from files\n const allFilesCommands: string[] = [];\n for (const fileConfigRaw of Object.values(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n allFilesCommands.push(...fileConfig.commands);\n }\n\n // Validate ignores refer to existing commands\n validateIgnoresExist(ignores, allCommands);\n\n // Validate no conflicts between files and ignores\n validateNoConflicts(allFilesCommands, ignores, allCommands);\n\n // Build file map for cross-file links\n const fileMap = buildFileMap(files, allCommands, ignores);\n\n const results: GenerateDocResult[\"files\"] = [];\n let hasError = false;\n\n // Validate all targetCommands exist in files\n if (targetCommands && targetCommands.length > 0) {\n for (const targetCommand of targetCommands) {\n const targetFilePath = findFileForCommand(targetCommand, files, allCommands, ignores);\n if (!targetFilePath) {\n throw new Error(`Target command \"${targetCommand}\" not found in any file configuration`);\n }\n }\n }\n\n // Process each file\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n if (specifiedCommands.length === 0) {\n continue;\n }\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n if (commandPaths.length === 0) {\n continue;\n }\n\n // Calculate minimum depth in this file for relative heading level\n const minDepth = Math.min(...commandPaths.map((p) => allCommands.get(p)?.depth ?? 1));\n\n // Adjust headingLevel so that minimum depth command gets the configured headingLevel\n const adjustedHeadingLevel = Math.max(1, (format?.headingLevel ?? 1) - (minDepth - 1)) as\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6;\n\n // Create file-specific renderer with adjusted headingLevel (if no custom renderer)\n const fileRenderer = createCommandRenderer({\n ...format,\n headingLevel: adjustedHeadingLevel,\n });\n\n // Use custom renderer if provided, otherwise use file-specific renderer\n const render = fileConfig.render ?? fileRenderer;\n\n // Handle partial validation when targetCommands are specified\n if (targetCommands !== undefined && targetCommands.length > 0) {\n // Find which target commands are in this file\n const fileTargetCommands = findTargetCommandsInFile(\n targetCommands,\n filePath,\n files,\n allCommands,\n ignores,\n );\n\n // Skip files that don't contain any target commands\n if (fileTargetCommands.length === 0) {\n continue;\n }\n\n // Read existing content once for all target commands in this file\n let existingContent = readFile(filePath);\n let fileStatus: \"match\" | \"created\" | \"updated\" | \"diff\" = \"match\";\n const diffs: string[] = [];\n\n for (const targetCommand of fileTargetCommands) {\n // Generate only the target command's section\n const rawSection = generateCommandSection(\n targetCommand,\n allCommands,\n render,\n filePath,\n fileMap,\n );\n\n if (!rawSection) {\n throw new Error(`Target command \"${targetCommand}\" not found in commands`);\n }\n\n // For root command, include file header if configured\n const isRootCommand = targetCommand === \"\";\n const header = isRootCommand && fileConfig ? generateFileHeader(fileConfig) : null;\n const rawContent = header ? `${header}\\n${rawSection}` : rawSection;\n\n // Apply formatter to the section\n const generatedSection = await applyFormatter(rawContent, formatter);\n\n if (!existingContent) {\n // File doesn't exist yet, create it with the section only\n if (updateMode) {\n writeFile(filePath, generatedSection);\n existingContent = generatedSection;\n fileStatus = \"created\";\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(\n `File does not exist. Target command \"${targetCommand}\" section cannot be validated.`,\n );\n }\n continue;\n }\n\n // Extract existing section for comparison\n const existingSection = extractCommandSection(existingContent, targetCommand);\n\n // For comparison, extract just the section from generated content (without header)\n const generatedSectionOnly = extractCommandSection(generatedSection, targetCommand);\n\n if (!generatedSectionOnly) {\n throw new Error(\n `Generated content does not contain section for command \"${targetCommand}\"`,\n );\n }\n\n if (!existingSection) {\n // Section doesn't exist in existing file - insert at correct position\n if (updateMode) {\n existingContent = insertCommandSection(\n existingContent,\n targetCommand,\n generatedSectionOnly,\n specifiedCommands,\n );\n writeFile(filePath, existingContent);\n if (fileStatus !== \"created\") {\n fileStatus = \"updated\";\n }\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(`Existing file does not contain section for command \"${targetCommand}\"`);\n }\n continue;\n }\n\n // Compare sections\n if (existingSection !== generatedSectionOnly) {\n if (updateMode) {\n // Replace only the target command section in the existing file\n const updatedContent = replaceCommandSection(\n existingContent,\n targetCommand,\n generatedSectionOnly,\n );\n if (updatedContent) {\n existingContent = updatedContent;\n writeFile(filePath, existingContent);\n if (fileStatus !== \"created\") {\n fileStatus = \"updated\";\n }\n } else {\n throw new Error(`Failed to replace section for command \"${targetCommand}\"`);\n }\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(formatDiff(existingSection, generatedSectionOnly));\n }\n }\n }\n\n results.push({\n path: filePath,\n status: fileStatus,\n diff: diffs.length > 0 ? diffs.join(\"\\n\\n\") : undefined,\n });\n } else {\n // Generate markdown with file context (pass specifiedCommands as order hint)\n const rawMarkdown = generateFileMarkdown(\n commandPaths,\n allCommands,\n render,\n filePath,\n fileMap,\n specifiedCommands,\n fileConfig,\n );\n\n // Apply formatter if provided\n const generatedMarkdown = await applyFormatter(rawMarkdown, formatter);\n // Full file comparison (original behavior)\n const comparison = compareWithExisting(generatedMarkdown, filePath);\n\n if (comparison.match) {\n results.push({\n path: filePath,\n status: \"match\",\n });\n } else if (updateMode) {\n writeFile(filePath, generatedMarkdown);\n results.push({\n path: filePath,\n status: comparison.fileExists ? \"updated\" : \"created\",\n });\n } else {\n hasError = true;\n results.push({\n path: filePath,\n status: \"diff\",\n diff: comparison.diff,\n });\n }\n }\n }\n\n return {\n success: !hasError,\n files: results,\n error: hasError\n ? `Documentation is out of date. Run with ${UPDATE_GOLDEN_ENV}=true to update.`\n : undefined,\n };\n}\n\n/**\n * Assert that documentation matches golden files\n * Throws an error if there are differences and update mode is not enabled\n */\nexport async function assertDocMatch(config: GenerateDocConfig): Promise<void> {\n const result = await generateDoc(config);\n\n if (!result.success) {\n const diffMessages = result.files\n .filter((f) => f.status === \"diff\")\n .map((f) => {\n let msg = `File: ${f.path}\\n`;\n if (f.diff) {\n msg += f.diff;\n }\n return msg;\n })\n .join(\"\\n\\n\");\n\n throw new Error(\n `Documentation does not match golden files.\\n\\n${diffMessages}\\n\\n` +\n `Run with ${UPDATE_GOLDEN_ENV}=true to update the documentation.`,\n );\n }\n}\n\n/**\n * Initialize documentation files by deleting them\n * Only deletes when update mode is enabled (POLITTY_DOCS_UPDATE=true)\n * Use this in beforeAll to ensure skipped tests don't leave stale sections\n * @param config - Config containing files to initialize, or a single file path\n * @param fileSystem - Optional fs implementation (useful when fs is mocked)\n */\nexport function initDocFile(\n config: Pick<GenerateDocConfig, \"files\"> | string,\n fileSystem?: DeleteFileFs,\n): void {\n if (!isUpdateMode()) {\n return;\n }\n\n if (typeof config === \"string\") {\n deleteFile(config, fileSystem);\n } else {\n for (const filePath of Object.keys(config.files)) {\n deleteFile(filePath, fileSystem);\n }\n }\n}\n","import { z } from \"zod\";\nimport { extractFields, type ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { renderOptionsTableFromArray } from \"./default-renderers.js\";\n\n/**\n * Args shape type (Record of string keys to Zod schemas)\n * This matches the typical structure of `commonArgs`, `workspaceArgs`, etc.\n */\nexport type ArgsShape = Record<string, z.ZodType>;\n\n/**\n * Options for rendering args table\n */\nexport type ArgsTableOptions = {\n /** Columns to include in the table (default: all columns) */\n columns?: (\"option\" | \"alias\" | \"description\" | \"default\" | \"env\")[];\n};\n\n/**\n * Extract ResolvedFieldMeta array from ArgsShape\n *\n * This converts a raw args shape (like `commonArgs`) into the\n * ResolvedFieldMeta format used by politty's rendering functions.\n */\nfunction extractArgsFields(args: ArgsShape): ResolvedFieldMeta[] {\n // Wrap in z.object to use extractFields\n const schema = z.object(args);\n const extracted = extractFields(schema);\n return extracted.fields;\n}\n\n/**\n * Render args definition as a markdown options table\n *\n * This function takes raw args definitions (like `commonArgs`) and\n * renders them as a markdown table suitable for documentation.\n *\n * @example\n * import { renderArgsTable } from \"politty/docs\";\n * import { commonArgs, workspaceArgs } from \"./args\";\n *\n * const table = renderArgsTable({\n * ...commonArgs,\n * ...workspaceArgs,\n * });\n * // | Option | Alias | Description | Default |\n * // |--------|-------|-------------|---------|\n * // | `--env-file <ENV_FILE>` | `-e` | Path to environment file | - |\n * // ...\n *\n * @param args - Args shape (Record of string keys to Zod schemas with arg() metadata)\n * @param options - Rendering options\n * @returns Rendered markdown table string\n */\nexport function renderArgsTable(args: ArgsShape, options?: ArgsTableOptions): string {\n const fields = extractArgsFields(args);\n\n // Filter to non-positional args only (options)\n const optionFields = fields.filter((f) => !f.positional);\n\n if (optionFields.length === 0) {\n return \"\";\n }\n\n // Use existing renderOptionsTableFromArray for consistency\n // Note: column filtering is not yet supported by renderOptionsTableFromArray\n // If columns option is needed, we would need to implement custom rendering\n if (options?.columns) {\n return renderFilteredTable(optionFields, options.columns);\n }\n\n return renderOptionsTableFromArray(optionFields);\n}\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Format default value for display\n */\nfunction formatDefaultValue(value: unknown): string {\n if (value === undefined) {\n return \"-\";\n }\n return `\\`${JSON.stringify(value)}\\``;\n}\n\n/**\n * Render table with filtered columns\n */\nfunction renderFilteredTable(\n options: ResolvedFieldMeta[],\n columns: (\"option\" | \"alias\" | \"description\" | \"default\" | \"env\")[],\n): string {\n const lines: string[] = [];\n\n // Build header\n const headerCells: string[] = [];\n const separatorCells: string[] = [];\n\n for (const col of columns) {\n switch (col) {\n case \"option\":\n headerCells.push(\"Option\");\n separatorCells.push(\"------\");\n break;\n case \"alias\":\n headerCells.push(\"Alias\");\n separatorCells.push(\"-----\");\n break;\n case \"description\":\n headerCells.push(\"Description\");\n separatorCells.push(\"-----------\");\n break;\n case \"default\":\n headerCells.push(\"Default\");\n separatorCells.push(\"-------\");\n break;\n case \"env\":\n headerCells.push(\"Env\");\n separatorCells.push(\"---\");\n break;\n }\n }\n\n lines.push(`| ${headerCells.join(\" | \")} |`);\n lines.push(`| ${separatorCells.join(\" | \")} |`);\n\n // Build rows\n for (const opt of options) {\n const cells: string[] = [];\n\n for (const col of columns) {\n switch (col) {\n case \"option\": {\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\"\n ? `\\`--${opt.cliName}\\``\n : `\\`--${opt.cliName} <${placeholder}>\\``;\n cells.push(optionName);\n break;\n }\n case \"alias\":\n cells.push(opt.alias ? `\\`-${opt.alias}\\`` : \"-\");\n break;\n case \"description\":\n cells.push(escapeTableCell(opt.description ?? \"\"));\n break;\n case \"default\":\n cells.push(formatDefaultValue(opt.defaultValue));\n break;\n case \"env\": {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n cells.push(envNames);\n break;\n }\n }\n }\n\n lines.push(`| ${cells.join(\" | \")} |`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { AnyCommand } from \"../types.js\";\nimport { collectAllCommands } from \"./doc-generator.js\";\nimport type { CommandInfo } from \"./types.js\";\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Generate anchor from command path\n */\nfunction generateAnchor(commandPath: string): string {\n return commandPath.replace(/\\s+/g, \"-\").toLowerCase();\n}\n\n/**\n * Configuration for a command category\n */\nexport type CommandCategory = {\n /** Category title (e.g., \"Application Commands\") */\n title: string;\n /** Category description */\n description: string;\n /** Command paths to include (parent commands will auto-expand to leaf commands) */\n commands: string[];\n /** Path to documentation file for links (e.g., \"./cli/application.md\") */\n docPath: string;\n};\n\n/**\n * Options for rendering command index\n */\nexport type CommandIndexOptions = {\n /** Base heading level (default: 3, which renders as ###) */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Only include leaf commands (commands without subcommands). Default: true */\n leafOnly?: boolean;\n};\n\n/**\n * Check if a command is a leaf (has no subcommands)\n */\nfunction isLeafCommand(info: CommandInfo): boolean {\n return info.subCommands.length === 0;\n}\n\n/**\n * Expand commands to include their subcommands\n * If a command has subcommands, recursively find all commands under it\n *\n * @param commandPaths - Command paths to expand\n * @param allCommands - Map of all available commands\n * @param leafOnly - If true, only include leaf commands; if false, include all commands\n */\nfunction expandCommands(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n leafOnly: boolean,\n): string[] {\n const result: string[] = [];\n\n for (const cmdPath of commandPaths) {\n const info = allCommands.get(cmdPath);\n if (!info) continue;\n\n if (isLeafCommand(info)) {\n // Already a leaf command\n result.push(cmdPath);\n } else {\n // Find all commands under this parent\n for (const [path, pathInfo] of allCommands) {\n // Check if this is a subcommand of the current command\n const isSubcommand =\n cmdPath === \"\" ? path.length > 0 : path.startsWith(cmdPath + \" \") || path === cmdPath;\n\n if (isSubcommand) {\n // Include if it's a leaf command, or if we're including all commands\n if (isLeafCommand(pathInfo) || !leafOnly) {\n result.push(path);\n }\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Render a single category section\n */\nfunction renderCategory(\n category: CommandCategory,\n allCommands: Map<string, CommandInfo>,\n headingLevel: number,\n leafOnly: boolean,\n): string {\n const h = \"#\".repeat(headingLevel);\n const lines: string[] = [];\n\n // Category title with link\n lines.push(`${h} [${category.title}](${category.docPath})`);\n lines.push(\"\");\n\n // Category description\n lines.push(category.description);\n lines.push(\"\");\n\n // Determine which commands to include (always expand, leafOnly controls filtering)\n const commandPaths = expandCommands(category.commands, allCommands, leafOnly);\n\n // Build command table\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n for (const cmdPath of commandPaths) {\n const info = allCommands.get(cmdPath);\n if (!info) continue;\n\n // Skip non-leaf commands if leafOnly is true\n if (leafOnly && !isLeafCommand(info)) continue;\n\n const displayName = cmdPath || info.name;\n const anchor = generateAnchor(displayName);\n const desc = escapeTableCell(info.description ?? \"\");\n\n lines.push(`| [${displayName}](${category.docPath}#${anchor}) | ${desc} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render command index from categories\n *\n * Generates a category-based index of commands with links to documentation.\n *\n * @example\n * const categories: CommandCategory[] = [\n * {\n * title: \"Application Commands\",\n * description: \"Commands for managing applications.\",\n * commands: [\"init\", \"generate\", \"apply\"],\n * docPath: \"./cli/application.md\",\n * },\n * ];\n *\n * const index = await renderCommandIndex(mainCommand, categories);\n * // ### [Application Commands](./cli/application.md)\n * //\n * // Commands for managing applications.\n * //\n * // | Command | Description |\n * // |---------|-------------|\n * // | [init](./cli/application.md#init) | Initialize a project |\n * // ...\n *\n * @param command - Root command to extract command information from\n * @param categories - Category definitions for grouping commands\n * @param options - Rendering options\n * @returns Rendered markdown string\n */\nexport async function renderCommandIndex(\n command: AnyCommand,\n categories: CommandCategory[],\n options?: CommandIndexOptions,\n): Promise<string> {\n const headingLevel = options?.headingLevel ?? 3;\n const leafOnly = options?.leafOnly ?? true;\n\n // Collect all commands\n const allCommands = await collectAllCommands(command);\n\n // Render each category\n const sections: string[] = [];\n for (const category of categories) {\n const section = renderCategory(category, allCommands, headingLevel, leafOnly);\n sections.push(section);\n }\n\n return sections.join(\"\\n\\n\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,SAASA,kBAAgB,KAAqB;AAC5C,QAAO,IAAI,QAAQ,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;;;;;AAMtD,SAASC,qBAAmB,OAAwB;AAClD,KAAI,UAAU,OACZ,QAAO;AAET,QAAO,KAAK,KAAK,UAAU,MAAM,CAAC;;;;;AAMpC,SAAgB,YAAY,MAA2B;CACrD,MAAM,QAAkB,CAAC,KAAK,gBAAgB;AAE9C,KAAI,KAAK,QAAQ,SAAS,EACxB,OAAM,KAAK,YAAY;AAGzB,KAAI,KAAK,YAAY,SAAS,EAC5B,OAAM,KAAK,YAAY;AAGzB,MAAK,MAAM,OAAO,KAAK,eACrB,KAAI,IAAI,SACN,OAAM,KAAK,IAAI,IAAI,KAAK,GAAG;KAE3B,OAAM,KAAK,IAAI,IAAI,KAAK,GAAG;AAI/B,QAAO,MAAM,KAAK,IAAI;;;;;AAMxB,SAAgB,qBAAqB,MAA2B;AAC9D,KAAI,KAAK,eAAe,WAAW,EACjC,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,wCAAwC;AACnD,OAAM,KAAK,wCAAwC;AAEnD,MAAK,MAAM,OAAO,KAAK,gBAAgB;EACrC,MAAM,OAAOD,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,WAAW,IAAI,WAAW,QAAQ;AACxC,QAAM,KAAK,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,SAAS,IAAI;;AAG3D,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,oBAAoB,MAA2B;AAC7D,KAAI,KAAK,eAAe,WAAW,EACjC,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,KAAK,gBAAgB;EACrC,MAAM,WAAW,IAAI,WAAW,eAAe;EAC/C,MAAM,OAAO,IAAI,cAAc,MAAM,IAAI,gBAAgB;AACzD,QAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,GAAG,WAAW;;AAGpD,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAS,cAAc,KAA4C;AACjE,KAAI,CAAC,IAAK,QAAO;AAEjB,QAAO,WADU,MAAM,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI,EACvB,KAAK,KAAK,CAAC;;;;;AAMvC,SAAS,kBAAkB,KAAgC;CACzD,MAAM,QAAkB,EAAE;CAG1B,MAAM,cAAc,IAAI,eAAe,IAAI,QAAQ,aAAa,CAAC,QAAQ,MAAM,IAAI;CACnF,MAAM,WACJ,IAAI,SAAS,YAAY,KAAK,IAAI,YAAY,KAAK,IAAI,QAAQ,IAAI,YAAY;AAEjF,KAAI,IAAI,MACN,OAAM,KAAK,MAAM,IAAI,MAAM,QAAQ,SAAS,IAAI;KAEhD,OAAM,KAAK,KAAK,SAAS,IAAI;AAG/B,QAAO,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;AAiBvB,SAAgB,mBAAmB,MAA2B;AAC5D,KAAI,KAAK,QAAQ,WAAW,EAC1B,QAAO;CAIT,MAAM,SAAS,KAAK,QAAQ,MAAM,QAAQ,IAAI,IAAI;CAElD,MAAM,QAAkB,EAAE;AAC1B,KAAI,QAAQ;AACV,QAAM,KAAK,mDAAmD;AAC9D,QAAM,KAAK,mDAAmD;QACzD;AACL,QAAM,KAAK,6CAA6C;AACxD,QAAM,KAAK,6CAA6C;;AAG1D,MAAK,MAAM,OAAO,KAAK,SAAS;EAE9B,MAAM,cAAc,IAAI,eAAe,IAAI,QAAQ,aAAa,CAAC,QAAQ,MAAM,IAAI;EACnF,MAAM,aACJ,IAAI,SAAS,YAAY,OAAO,IAAI,QAAQ,MAAM,OAAO,IAAI,QAAQ,IAAI,YAAY;EACvF,MAAM,QAAQ,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM;EAChD,MAAM,OAAOA,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,aAAaC,qBAAmB,IAAI,aAAa;AAEvD,MAAI,QAAQ;GACV,MAAM,WAAW,IAAI,MACjB,MAAM,QAAQ,IAAI,IAAI,GACpB,IAAI,IAAI,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,GACzC,KAAK,IAAI,IAAI,MACf;AACJ,SAAM,KAAK,KAAK,WAAW,KAAK,MAAM,KAAK,KAAK,KAAK,WAAW,KAAK,SAAS,IAAI;QAElF,OAAM,KAAK,KAAK,WAAW,KAAK,MAAM,KAAK,KAAK,KAAK,WAAW,IAAI;;AAIxE,QAAO,MAAM,KAAK,KAAK;;;;;;;;;;;;;AAczB,SAAgB,kBAAkB,MAA2B;AAC3D,KAAI,KAAK,QAAQ,WAAW,EAC1B,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,KAAK,SAAS;EAC9B,MAAM,QAAQ,kBAAkB,IAAI;EACpC,MAAM,OAAO,IAAI,cAAc,MAAM,IAAI,gBAAgB;EACzD,MAAM,aACJ,IAAI,iBAAiB,SAAY,cAAc,KAAK,UAAU,IAAI,aAAa,CAAC,KAAK;EACvF,MAAM,UAAU,cAAc,IAAI,IAAI;AACtC,QAAM,KAAK,KAAK,QAAQ,OAAO,aAAa,UAAU;;AAGxD,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAASC,iBAAe,aAA+B;AACrD,QAAO,YAAY,KAAK,IAAI,CAAC,aAAa;;;;;AAM5C,SAAS,gBAAgB,MAAc,IAAoB;CACzD,MAAM,YAAY,KAAK,MAAM,IAAI,CAAC,MAAM,GAAG,GAAG;CAC9C,MAAM,UAAU,GAAG,MAAM,IAAI;CAG7B,IAAI,eAAe;AACnB,QACE,eAAe,UAAU,UACzB,eAAe,QAAQ,SAAS,KAChC,UAAU,kBAAkB,QAAQ,cAEpC;CAIF,MAAM,UAAU,UAAU,SAAS;AAGnC,QAFsB,CAAC,GAAG,MAAM,QAAQ,CAAC,KAAK,KAAK,EAAE,GAAG,QAAQ,MAAM,aAAa,CAAC,CAE/D,KAAK,IAAI,KAAK,QAAQ,QAAQ,SAAS,MAAM;;;;;AAMpE,SAAgB,uBAAuB,MAAmB,kBAAkB,MAAc;AACxF,KAAI,KAAK,YAAY,WAAW,EAC9B,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,4BAA4B;AACvC,OAAM,KAAK,4BAA4B;CAEvC,MAAM,cAAc,KAAK;CACzB,MAAM,UAAU,KAAK;AAErB,MAAK,MAAM,OAAO,KAAK,aAAa;EAClC,MAAM,WAAW,IAAI,SAAS,KAAK,IAAI;EACvC,MAAM,OAAOF,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,iBAAiB,IAAI,SAAS,KAAK,IAAI;AAE7C,MAAI,iBAAiB;GACnB,MAAM,SAASE,iBAAe,IAAI,SAAS;GAC3C,MAAM,UAAU,UAAU;AAE1B,OAAI,eAAe,WAAW,gBAAgB,SAAS;IAErD,MAAM,eAAe,gBAAgB,aAAa,QAAQ;AAC1D,UAAM,KAAK,QAAQ,SAAS,MAAM,aAAa,GAAG,OAAO,MAAM,KAAK,IAAI;SAGxE,OAAM,KAAK,QAAQ,SAAS,OAAO,OAAO,MAAM,KAAK,IAAI;QAG3D,OAAM,KAAK,OAAO,SAAS,OAAO,KAAK,IAAI;;AAI/C,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,4BAA4B,SAAsC;AAChF,KAAI,QAAQ,WAAW,EACrB,QAAO;CAIT,MAAM,SAAS,QAAQ,MAAM,QAAQ,IAAI,IAAI;CAE7C,MAAM,QAAkB,EAAE;AAC1B,KAAI,QAAQ;AACV,QAAM,KAAK,mDAAmD;AAC9D,QAAM,KAAK,mDAAmD;QACzD;AACL,QAAM,KAAK,6CAA6C;AACxD,QAAM,KAAK,6CAA6C;;AAG1D,MAAK,MAAM,OAAO,SAAS;EACzB,MAAM,cAAc,IAAI,eAAe,IAAI,QAAQ,aAAa,CAAC,QAAQ,MAAM,IAAI;EACnF,MAAM,aACJ,IAAI,SAAS,YAAY,OAAO,IAAI,QAAQ,MAAM,OAAO,IAAI,QAAQ,IAAI,YAAY;EACvF,MAAM,QAAQ,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM;EAChD,MAAM,OAAOF,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,aAAaC,qBAAmB,IAAI,aAAa;AAEvD,MAAI,QAAQ;GACV,MAAM,WAAW,IAAI,MACjB,MAAM,QAAQ,IAAI,IAAI,GACpB,IAAI,IAAI,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,GACzC,KAAK,IAAI,IAAI,MACf;AACJ,SAAM,KAAK,KAAK,WAAW,KAAK,MAAM,KAAK,KAAK,KAAK,WAAW,KAAK,SAAS,IAAI;QAElF,OAAM,KAAK,KAAK,WAAW,KAAK,MAAM,KAAK,KAAK,KAAK,WAAW,IAAI;;AAIxE,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,2BAA2B,SAAsC;AAC/E,KAAI,QAAQ,WAAW,EACrB,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,SAAS;EACzB,MAAM,QAAQ,kBAAkB,IAAI;EACpC,MAAM,OAAO,IAAI,cAAc,MAAM,IAAI,gBAAgB;EACzD,MAAM,aACJ,IAAI,iBAAiB,SAAY,cAAc,KAAK,UAAU,IAAI,aAAa,CAAC,KAAK;EACvF,MAAM,UAAU,cAAc,IAAI,IAAI;AACtC,QAAM,KAAK,KAAK,QAAQ,OAAO,aAAa,UAAU;;AAGxD,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,8BAA8B,MAAmC;AAC/E,KAAI,KAAK,WAAW,EAClB,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,wCAAwC;AACnD,OAAM,KAAK,wCAAwC;AAEnD,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,OAAOD,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,WAAW,IAAI,WAAW,QAAQ;AACxC,QAAM,KAAK,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK,SAAS,IAAI;;AAG3D,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,6BAA6B,MAAmC;AAC9E,KAAI,KAAK,WAAW,EAClB,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,OAAO,MAAM;EACtB,MAAM,WAAW,IAAI,WAAW,eAAe;EAC/C,MAAM,OAAO,IAAI,cAAc,MAAM,IAAI,gBAAgB;AACzD,QAAM,KAAK,OAAO,IAAI,KAAK,IAAI,KAAK,GAAG,WAAW;;AAGpD,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,gCACd,aACA,MACA,kBAAkB,MACV;AACR,KAAI,YAAY,WAAW,EACzB,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,OAAM,KAAK,4BAA4B;AACvC,OAAM,KAAK,4BAA4B;CAEvC,MAAM,cAAc,KAAK;CACzB,MAAM,UAAU,KAAK;AAErB,MAAK,MAAM,OAAO,aAAa;EAC7B,MAAM,WAAW,IAAI,SAAS,KAAK,IAAI;EACvC,MAAM,OAAOA,kBAAgB,IAAI,eAAe,GAAG;EACnD,MAAM,iBAAiB,IAAI,SAAS,KAAK,IAAI;AAE7C,MAAI,iBAAiB;GACnB,MAAM,SAASE,iBAAe,IAAI,SAAS;GAC3C,MAAM,UAAU,UAAU;AAE1B,OAAI,eAAe,WAAW,gBAAgB,SAAS;IAErD,MAAM,eAAe,gBAAgB,aAAa,QAAQ;AAC1D,UAAM,KAAK,QAAQ,SAAS,MAAM,aAAa,GAAG,OAAO,MAAM,KAAK,IAAI;SAGxE,OAAM,KAAK,QAAQ,SAAS,OAAO,OAAO,MAAM,KAAK,IAAI;QAG3D,OAAM,KAAK,OAAO,SAAS,OAAO,KAAK,IAAI;;AAI/C,QAAO,MAAM,KAAK,KAAK;;;;;;;;;;;;;;;;;AAkBzB,SAAgB,sBACd,UACA,SACA,MACQ;AACR,KAAI,SAAS,WAAW,EACtB,QAAO;CAGT,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,SAAS,MAAM,gBAAgB,GAAG,KAAK,cAAc,KAAK;CAChE,MAAM,QAAkB,EAAE;AAE1B,MAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;EACxC,MAAM,UAAU,SAAS;AACzB,MAAI,CAAC,QAAS;EAEd,MAAM,SAAS,UAAU;AAGzB,QAAM,KAAK,KAAK,QAAQ,KAAK,IAAI;AACjC,QAAM,KAAK,GAAG;AAGd,QAAM,KAAK,UAAU;AACrB,QAAM,KAAK,KAAK,SAAS,QAAQ,MAAM;AAGvC,MAAI,YACF;OAAI,QAAQ;AAEV,QAAI,OAAO,OACT,OAAM,KAAK,OAAO,OAAO;AAE3B,QAAI,OAAO,OACT,OAAM,KAAK,YAAY,OAAO,SAAS;cAEhC,QAAQ,OAEjB,OAAM,KAAK,QAAQ,OAAO;;AAI9B,QAAM,KAAK,MAAM;AACjB,QAAM,KAAK,GAAG;;AAIhB,QAAO,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,OAAO,GACrD,OAAM,KAAK;AAGb,QAAO,MAAM,KAAK,KAAK;;;;;AAMzB,SAAgB,sBAAsB,UAAkC,EAAE,EAAkB;CAC1F,MAAM,EACJ,eAAe,GACf,cAAc,SACd,kBAAkB,MAClB,2BAA2B,MAC3B,mBAAmB,yBACnB,aAAa,mBACb,iBAAiB,uBACjB,eAAe,qBACf,mBAAmB,yBACnB,aAAa,mBACb,cAAc,oBACd,gBAAgB,yBACd;AAEJ,SAAQ,SAA8B;EACpC,MAAM,QAAkB,EAAE;EAG1B,MAAM,iBAAiB,KAAK,IAAI,gBAAgB,KAAK,QAAQ,IAAI,EAAE;EACnE,MAAM,IAAI,IAAI,OAAO,eAAe;EAGpC,MAAM,QAAQ,KAAK,eAAe,KAAK;AACvC,QAAM,KAAK,GAAG,EAAE,GAAG,QAAQ;AAC3B,QAAM,KAAK,GAAG;AAGd,MAAI,KAAK,aAAa;GACpB,MAAM,UAA+B;IACnC,SAAS,KAAK;IACd,SAAS;IACT;IACD;GACD,MAAM,UAAU,0BAA0B,wBAAwB,QAAQ,GAAG,QAAQ;AACrF,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;EAKlB;GAEE,MAAM,UAA+B;IACnC,SAFmB,wBAAwB,YAAY,KAAK,CAAC;IAG7D,SAAS;IACT;IACD;GACD,MAAM,UAAU,oBAAoB,kBAAkB,QAAQ,GAAG,QAAQ;AACzE,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,MAAI,KAAK,eAAe,SAAS,GAAG;GAClC,MAAM,cAAc,MAA2B,SAAwC;IACrF,MAAM,QAAQ,MAAM,SAAS;IAC7B,MAAM,cAAc,MAAM,eAAe;IACzC,MAAM,UACJ,UAAU,UACN,8BAA8B,KAAK,GACnC,6BAA6B,KAAK;AACxC,WAAO,cAAc,oBAAoB,YAAY;;GAGvD,MAAM,UAAkC;IACtC,MAAM,KAAK;IACX,QAAQ;IACR,SAAS;IACT;IACD;GAED,MAAM,UAAU,wBACZ,sBAAsB,QAAQ,GAC9B,WAAW,QAAQ,KAAK;AAC5B,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,MAAI,KAAK,QAAQ,SAAS,GAAG;GAC3B,MAAM,cAAc,MAA2B,eAA8C;IAC3F,MAAM,QAAQ,YAAY,SAAS;IACnC,MAAM,cAAc,YAAY,eAAe;IAC/C,MAAM,UACJ,UAAU,UAAU,4BAA4B,KAAK,GAAG,2BAA2B,KAAK;AAC1F,WAAO,cAAc,kBAAkB,YAAY;;GAGrD,MAAM,UAAgC;IACpC,SAAS,KAAK;IACd,QAAQ;IACR,SAAS;IACT;IACD;GAED,MAAM,UAAU,sBACZ,oBAAoB,QAAQ,GAC5B,WAAW,QAAQ,QAAQ;AAC/B,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,MAAI,KAAK,YAAY,SAAS,GAAG;GAC/B,MAAM,mBAAmB,mBAAmB;GAE5C,MAAM,cAAc,MAAwB,SAA4C;IACtF,MAAM,UAAU,MAAM,mBAAmB;IACzC,MAAM,cAAc,MAAM,eAAe;IACzC,MAAM,UAAU,gCAAgC,MAAM,MAAM,QAAQ;AACpE,WAAO,cAAc,mBAAmB,YAAY;;GAGtD,MAAM,UAAoC;IACxC,aAAa,KAAK;IAClB,QAAQ;IACR,SAAS;IACT;IACD;GAED,MAAM,UAAU,0BACZ,wBAAwB,QAAQ,GAChC,WAAW,QAAQ,YAAY;AACnC,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,MAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;GAC7C,MAAM,YACJ,UACA,SACA,SACW;IACX,MAAM,cAAc,MAAM,eAAe;IAKzC,MAAM,UAAU,sBAAsB,UAAU,SAJN;KACxC,eAAe,KAAK;KACpB,GAAG;KACJ,CACmE;AACpE,WAAO,cAAc,mBAAmB,YAAY;;GAGtD,MAAM,UAAiC;IACrC,UAAU,KAAK;IACf,SAAS,KAAK;IACd,QAAQ;IACR,SAAS;IACT;IACD;GAED,MAAM,UAAU,uBACZ,qBAAqB,QAAQ,GAC7B,SAAS,QAAQ,UAAU,QAAQ,QAAQ;AAC/C,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,MAAI,KAAK,OAAO;GACd,MAAM,UAA+B;IACnC,SAAS,gBAAgB,KAAK;IAC9B,SAAS;IACT;IACD;GACD,MAAM,UAAU,oBAAoB,kBAAkB,QAAQ,GAAG,QAAQ;AACzE,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;EAKlB;GACE,MAAM,UAA+B;IACnC,SAAS;IACT,SAAS;IACT;IACD;GACD,MAAM,UAAU,qBAAqB,mBAAmB,QAAQ,GAAG,QAAQ;AAC3E,OAAI,SAAS;AACX,UAAM,KAAK,QAAQ;AACnB,UAAM,KAAK,GAAG;;;AAKlB,SAAO,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,OAAO,GACrD,OAAM,KAAK;AAEb,QAAM,KAAK,GAAG;AAEd,SAAO,MAAM,KAAK,KAAK;;;;;;AAO3B,MAAa,mBAAmB;CAE9B,UAAU,YAAqC,sBAAsB,QAAQ;CAE7E,YAAY,sBAAsB,EAAE,aAAa,SAAS,CAAC;CAE3D,WAAW,sBAAsB,EAAE,aAAa,QAAQ,CAAC;CAC1D;;;;;;;AChsBD,SAAgB,oBAAoB,kBAA0B,UAAiC;CAC7F,MAAM,eAAeC,UAAK,QAAQ,SAAS;AAE3C,KAAI,CAACC,QAAG,WAAW,aAAa,CAC9B,QAAO;EACL,OAAO;EACP,YAAY;EACb;CAGH,MAAM,kBAAkBA,QAAG,aAAa,cAAc,QAAQ;AAE9D,KAAI,qBAAqB,gBACvB,QAAO;EACL,OAAO;EACP,YAAY;EACb;AAGH,QAAO;EACL,OAAO;EACP,MAAM,WAAW,iBAAiB,iBAAiB;EACnD,YAAY;EACb;;;;;AAMH,SAAgB,WAAW,UAAkB,QAAwB;CACnE,MAAM,gBAAgB,SAAS,MAAM,KAAK;CAC1C,MAAM,cAAc,OAAO,MAAM,KAAK;CAEtC,MAAM,SAAmB,EAAE;AAC3B,QAAO,KAAK,eAAe;AAC3B,QAAO,KAAK,gBAAgB;AAC5B,QAAO,KAAK,GAAG;CAGf,MAAM,WAAW,KAAK,IAAI,cAAc,QAAQ,YAAY,OAAO;CACnE,IAAI,UAAU;CACd,IAAI,aAAa;CACjB,MAAM,QAAkB,EAAE;CAE1B,MAAM,mBAAyB;AAC7B,MAAI,MAAM,SAAS,GAAG;AACpB,UAAO,KAAK,OAAO,aAAa,EAAE,GAAG,MAAM,OAAO,KAAK;AACvD,UAAO,KAAK,GAAG,MAAM;AACrB,SAAM,SAAS;;AAEjB,YAAU;;AAGZ,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,KAAK;EACjC,MAAM,eAAe,cAAc;EACnC,MAAM,aAAa,YAAY;AAE/B,MAAI,iBAAiB,YACnB;OAAI,SAAS;AAEX,UAAM,KAAK,IAAI,gBAAgB,KAAK;IAEpC,MAAM,kBAAkB,MAAM,WAC3B,MAAM,SACJ,KAAK,WAAW,IAAI,IAAI,KAAK,WAAW,IAAI,KAC7C,MAAM,MAAM,MAAM,EAAE,CAAC,OAAO,MAAM,EAAE,WAAW,IAAI,CAAC,CACvD;AACD,QAAI,oBAAoB,MAAM,MAAM,SAAS,kBAAkB,EAC7D,aAAY;;SAGX;AACL,OAAI,CAAC,SAAS;AACZ,cAAU;AACV,iBAAa;IAEb,MAAM,eAAe,KAAK,IAAI,GAAG,IAAI,EAAE;AACvC,SAAK,IAAI,IAAI,cAAc,IAAI,GAAG,IAChC,OAAM,KAAK,IAAI,cAAc,MAAM,KAAK;;AAI5C,OAAI,iBAAiB,WAAc,eAAe,UAAa,iBAAiB,YAC9E,OAAM,KAAK,IAAI,eAAe;AAEhC,OAAI,eAAe,WAAc,iBAAiB,UAAa,iBAAiB,YAC9E,OAAM,KAAK,IAAI,aAAa;;;AAKlC,aAAY;AAEZ,QAAO,OAAO,KAAK,KAAK;;;;;AAM1B,SAAgB,UAAU,UAAkB,SAAuB;CACjE,MAAM,eAAeD,UAAK,QAAQ,SAAS;CAC3C,MAAM,MAAMA,UAAK,QAAQ,aAAa;AAEtC,KAAI,CAACC,QAAG,WAAW,IAAI,CACrB,SAAG,UAAU,KAAK,EAAE,WAAW,MAAM,CAAC;AAGxC,SAAG,cAAc,cAAc,SAAS,QAAQ;;;;;;AAOlD,SAAgB,SAAS,UAAiC;CACxD,MAAM,eAAeD,UAAK,QAAQ,SAAS;AAE3C,KAAI,CAACC,QAAG,WAAW,aAAa,CAC9B,QAAO;AAGT,QAAOA,QAAG,aAAa,cAAc,QAAQ;;;;;;;AAgB/C,SAAgB,WAAW,UAAkB,aAA2BA,SAAU;CAChF,MAAM,eAAeD,UAAK,QAAQ,SAAS;AAE3C,KAAI,WAAW,WAAW,aAAa,CACrC,YAAW,WAAW,aAAa;;;;;;;;ACvJvC,eAAsB,iBACpB,SACA,UACA,cAAwB,EAAE,EACJ;CACtB,MAAM,YAAYE,4CAAmB,QAAQ;CAE7C,MAAM,iBAAiB,WAAW,OAAO,QAAQ,MAAM,EAAE,WAAW,IAAI,EAAE;CAC1E,MAAM,UAAU,WAAW,OAAO,QAAQ,MAAM,CAAC,EAAE,WAAW,IAAI,EAAE;CAEpE,MAAM,cAAgC,EAAE;AACxC,KAAI,QAAQ,YACV,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,QAAQ,YAAY,EAAE;EAChE,MAAM,WAAW,MAAMC,6CAAmB,OAAO;EACjD,MAAM,WAAW,CAAC,GAAG,aAAa,KAAK;AACvC,cAAY,KAAK;GACf;GACA,aAAa,SAAS;GACtB;GACD,CAAC;;AAIN,QAAO;EACL,MAAM,QAAQ,QAAQ;EACtB,aAAa,QAAQ;EACrB,iBAAiB,YAAY,SAAS,IAAI,GAAG,SAAS,GAAG,YAAY,KAAK,IAAI,KAAK;EACnF,aAAa,YAAY,KAAK,IAAI;EAClC,OAAO,YAAY,SAAS;EAC5B;EACA;EACA;EACA;EACA;EACA,OAAO,QAAQ;EACf,UAAU,QAAQ;EACnB;;;;;;AAOH,eAAsB,mBACpB,SACA,UACmC;CACnC,MAAM,OAAO,YAAY,QAAQ,QAAQ;CACzC,MAAM,yBAAS,IAAI,KAA0B;CAE7C,eAAe,SAAS,KAAiB,MAA+B;EACtE,MAAM,OAAO,MAAM,iBAAiB,KAAK,MAAM,KAAK;EACpD,MAAM,UAAU,KAAK,KAAK,IAAI;AAC9B,SAAO,IAAI,SAAS,KAAK;AAEzB,MAAI,IAAI,YACN,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,IAAI,YAAY,CAE1D,OAAM,SADW,MAAMA,6CAAmB,OAAO,EACxB,CAAC,GAAG,MAAM,KAAK,CAAC;;AAK/C,OAAM,SAAS,SAAS,EAAE,CAAC;AAC3B,QAAO;;;;;;;;;;;;;;AC3DT,eAAsB,gBACpB,UACA,QACA,aACA,cAAwB,EAAE,EACS;CACnC,MAAM,UAAoC,EAAE;AAG5C,KAAI,OAAO,KACT,OAAM,OAAO,MAAM;AAGrB,KAAI;AACF,OAAK,MAAM,WAAW,UAAU;GAC9B,MAAM,SAAS,MAAM,qBAAqB,SAAS,aAAa,YAAY;AAC5E,WAAQ,KAAK,OAAO;;WAEd;AAER,MAAI,OAAO,QACT,OAAM,OAAO,SAAS;;AAI1B,QAAO;;;;;AAMT,eAAe,qBACb,SACA,aACA,aACiC;CAEjC,MAAM,cAAc,gBAAgB,QAAQ,IAAI;CAGhD,MAAM,OAAO,CAAC,GAAG,aAAa,GAAG,YAAY;CAG7C,MAAM,YAAYC,6CAAmB,EAAE,aAAa,OAAO,CAAC;AAC5D,WAAU,OAAO;CAEjB,IAAI,UAAU;AACd,KAAI;EAEF,MAAM,EAAE,eAAe,2CAAM;EAC7B,MAAM,SAAS,MAAM,WAAW,aAAa,KAAK;AAClD,YAAU,OAAO;AAGjB,MAAI,CAAC,OAAO,WAAW,OAAO,MAC5B,SAAQ,MAAM,OAAO,MAAM,QAAQ;UAE9B,OAAO;AACd,YAAU;AACV,UAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;WAC7D;AACR,YAAU,MAAM;;CAIlB,MAAM,OAAO,UAAU,SAAS;CAChC,MAAM,SAAS,KAAK,QACjB,QAAQ,MAAM,EAAE,WAAW,SAAS,CACpC,KAAK,MAAM,EAAE,QAAQ,CACrB,KAAK,KAAK;CACb,MAAM,SAAS,KAAK,QACjB,QAAQ,MAAM,EAAE,WAAW,SAAS,CACpC,KAAK,MAAM,EAAE,QAAQ,CACrB,KAAK,KAAK;AAEb,QAAO;EACL,KAAK,QAAQ;EACb,MAAM,QAAQ;EACd,gBAAgB,QAAQ;EACxB;EACA;EACA;EACD;;;;;;;;;;;AAYH,SAAS,gBAAgB,KAAuB;CAC9C,MAAM,OAAiB,EAAE;CACzB,IAAI,UAAU;CACd,IAAI,UAAU;CACd,IAAI,YAAY;AAEhB,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;EACnC,MAAM,OAAO,IAAI;AAEjB,OAAK,SAAS,QAAO,SAAS,QAAQ,CAAC,SAAS;AAC9C,aAAU;AACV,eAAY;aACH,SAAS,aAAa,SAAS;AACxC,aAAU;AACV,eAAY;aACH,SAAS,OAAO,CAAC,SAC1B;OAAI,SAAS;AACX,SAAK,KAAK,QAAQ;AAClB,cAAU;;QAGZ,YAAW;;AAIf,KAAI,QACF,MAAK,KAAK,QAAQ;AAGpB,QAAO;;;;;;;;ACiMT,MAAa,oBAAoB;;;;;AAMjC,MAAa,wBAAwB;;;;AAKrC,SAAgB,mBAAmB,aAA6B;AAC9D,QAAO,QAAQ,sBAAsB,GAAG,YAAY;;;;;AAMtD,SAAgB,iBAAiB,aAA6B;AAC5D,QAAO,QAAQ,sBAAsB,GAAG,YAAY;;;;;;;;;AClUtD,eAAe,eACb,SACA,WACiB;AACjB,KAAI,CAAC,UACH,QAAO;AAET,QAAO,MAAM,UAAU,QAAQ;;;;;AAMjC,SAAS,eAAwB;CAC/B,MAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAO,UAAU,UAAU,UAAU;;;;;AAMvC,SAAS,oBAAoB,QAA2C;AACtE,KAAI,MAAM,QAAQ,OAAO,CACvB,QAAO,EAAE,UAAU,QAAQ;AAE7B,QAAO;;;;;AAMT,SAAS,eAAe,WAAmB,YAA6B;AACtE,KAAI,eAAe,GAAI,QAAO;AAC9B,KAAI,cAAc,WAAY,QAAO;AACrC,QAAO,UAAU,WAAW,aAAa,IAAI;;;;;AAM/C,SAAS,iBAAiB,SAA0B;AAClD,QAAO,QAAQ,SAAS,IAAI;;;;;;;;;;;;;AAc9B,SAAS,gBAAgB,MAAc,SAA0B;CAC/D,MAAM,eAAe,SAAS,KAAK,EAAE,GAAG,KAAK,MAAM,IAAI;CACvD,MAAM,kBAAkB,YAAY,KAAK,EAAE,GAAG,QAAQ,MAAM,IAAI;AAEhE,KAAI,aAAa,WAAW,gBAAgB,OAC1C,QAAO;AAGT,MAAK,IAAI,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;EAC/C,MAAM,aAAa,gBAAgB;EACnC,MAAM,UAAU,aAAa;AAE7B,MAAI,eAAe,OAAO,eAAe,QACvC,QAAO;;AAIX,QAAO;;;;;AAMT,SAAS,sBAAsB,SAAiB,aAAiD;CAC/F,MAAM,UAAoB,EAAE;AAE5B,MAAK,MAAM,WAAW,YAAY,MAAM,CACtC,KAAI,gBAAgB,SAAS,QAAQ,CACnC,SAAQ,KAAK,QAAQ;AAIzB,QAAO;;;;;;AAOT,SAAS,qBAAqB,MAAc,eAAgC;AAC1E,KAAI,iBAAiB,cAAc,EAAE;AAEnC,MAAI,gBAAgB,MAAM,cAAc,CACtC,QAAO;EAIT,MAAM,eAAe,SAAS,KAAK,EAAE,GAAG,KAAK,MAAM,IAAI;EACvD,MAAM,kBAAkB,kBAAkB,KAAK,EAAE,GAAG,cAAc,MAAM,IAAI;AAG5E,MAAI,aAAa,SAAS,gBAAgB,OAExC,QAAO,gBADY,aAAa,MAAM,GAAG,gBAAgB,OAAO,CAAC,KAAK,IAAI,EACvC,cAAc;AAEnD,SAAO;;AAGT,QAAO,eAAe,MAAM,cAAc;;;;;AAM5C,SAAS,mBACP,cACA,aACU;CACV,MAAM,2BAAW,IAAI,KAAa;AAElC,MAAK,MAAM,WAAW,aACpB,KAAI,iBAAiB,QAAQ,EAAE;EAE7B,MAAM,UAAU,sBAAsB,SAAS,YAAY;AAC3D,OAAK,MAAM,SAAS,SAAS;AAC3B,YAAS,IAAI,MAAM;AAEnB,QAAK,MAAM,QAAQ,YAAY,MAAM,CACnC,KAAI,eAAe,MAAM,MAAM,CAC7B,UAAS,IAAI,KAAK;;QAInB;AAEL,MAAI,YAAY,IAAI,QAAQ,CAC1B,UAAS,IAAI,QAAQ;AAGvB,OAAK,MAAM,QAAQ,YAAY,MAAM,CACnC,KAAI,eAAe,MAAM,QAAQ,CAC/B,UAAS,IAAI,KAAK;;AAM1B,QAAO,MAAM,KAAK,SAAS;;;;;AAM7B,SAAS,sBAAsB,cAAwB,SAA6B;AAClF,QAAO,aAAa,QAAQ,SAAS;AACnC,SAAO,CAAC,QAAQ,MAAM,kBAAkB,qBAAqB,MAAM,cAAc,CAAC;GAClF;;;;;AAMJ,SAAS,oBACP,eACA,SACA,aACM;CACN,MAAM,YAAsB,EAAE;AAE9B,MAAK,MAAM,eAAe,eAAe;EAEvC,MAAM,YAAY,iBAAiB,YAAY,GAC3C,sBAAsB,aAAa,YAAY,GAC/C,CAAC,YAAY;AAEjB,OAAK,MAAM,YAAY,UACrB,MAAK,MAAM,iBAAiB,QAC1B,KAAI,iBAAiB,cAAc,EAEjC;OAAI,gBAAgB,UAAU,cAAc,CAC1C,WAAU,KAAK,IAAI,SAAS,qCAAqC,cAAc,GAAG;aAIhF,aAAa,iBAAiB,eAAe,UAAU,cAAc,CACvE,WAAU,KAAK,IAAI,SAAS,qCAAqC,cAAc,GAAG;;AAO5F,KAAI,UAAU,SAAS,EACrB,OAAM,IAAI,MAAM,4CAA4C,UAAU,KAAK,SAAS,GAAG;;;;;AAO3F,SAAS,qBAAqB,SAAmB,aAA6C;CAC5F,MAAM,cAAwB,EAAE;AAEhC,MAAK,MAAM,iBAAiB,QAC1B,KAAI,iBAAiB,cAAc,EAGjC;MADgB,sBAAsB,eAAe,YAAY,CACrD,WAAW,EACrB,aAAY,KAAK,IAAI,cAAc,GAAG;YAIpC,CAAC,YAAY,IAAI,cAAc,CACjC,aAAY,KAAK,IAAI,cAAc,GAAG;AAK5C,KAAI,YAAY,SAAS,EACvB,OAAM,IAAI,MAAM,uCAAuC,YAAY,KAAK,KAAK,GAAG;;;;;;AAQpF,SAAS,eAAe,cAAwB,gBAAoC;CAElF,MAAM,UAAU,IAAI,IAAI,aAAa;CAGrC,MAAM,gBAAgB,eAAe,QAAQ,QAAQ,QAAQ,IAAI,IAAI,CAAC;AAGtE,MAAK,MAAM,QAAQ,aAEjB,MADc,SAAS,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC,YAClC,KAAK,CAAC,cAAc,SAAS,KAAK,CAC9C,eAAc,KAAK,KAAK;CAI5B,MAAM,SAAmB,EAAE;CAC3B,MAAM,0BAAU,IAAI,KAAa;CAEjC,SAAS,gBAAgB,SAAuB;AAC9C,MAAI,QAAQ,IAAI,QAAQ,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAE;AACnD,UAAQ,IAAI,QAAQ;AACpB,SAAO,KAAK,QAAQ;EAGpB,MAAM,WAAW,aACd,QAAQ,MAAM;AACb,OAAI,MAAM,WAAW,QAAQ,IAAI,EAAE,CAAE,QAAO;AAE5C,OAAI,YAAY,GACd,QAAO,EAAE,MAAM,IAAI,CAAC,WAAW;AAEjC,UAAO,EAAE,WAAW,UAAU,IAAI,IAAI,EAAE,MAAM,IAAI,CAAC,WAAW,QAAQ,MAAM,IAAI,CAAC,SAAS;IAC1F,CACD,MAAM,GAAG,MAAM,EAAE,cAAc,EAAE,CAAC;AAErC,OAAK,MAAM,SAAS,SAClB,iBAAgB,MAAM;;AAK1B,MAAK,MAAM,YAAY,cACrB,iBAAgB,SAAS;AAI3B,MAAK,MAAM,QAAQ,aACjB,KAAI,CAAC,QAAQ,IAAI,KAAK,CACpB,QAAO,KAAK,KAAK;AAIrB,QAAO;;;;;AAMT,SAAS,mBAAmB,YAAuC;AACjE,KAAI,CAAC,WAAW,SAAS,CAAC,WAAW,YACnC,QAAO;CAGT,MAAM,QAAkB,EAAE;AAC1B,KAAI,WAAW,MACb,OAAM,KAAK,KAAK,WAAW,QAAQ;AAErC,KAAI,WAAW,aAAa;AAC1B,QAAM,KAAK,GAAG;AACd,QAAM,KAAK,WAAW,YAAY;;AAEpC,OAAM,KAAK,GAAG;AAEd,QAAO,MAAM,KAAK,KAAK;;;;;;AAOzB,SAAS,sBAAsB,SAAiB,aAAoC;CAClF,MAAM,cAAc,mBAAmB,YAAY;CACnD,MAAM,YAAY,iBAAiB,YAAY;CAE/C,MAAM,aAAa,QAAQ,QAAQ,YAAY;AAC/C,KAAI,eAAe,GACjB,QAAO;CAGT,MAAM,WAAW,QAAQ,QAAQ,WAAW,WAAW;AACvD,KAAI,aAAa,GACf,QAAO;AAGT,QAAO,QAAQ,MAAM,YAAY,WAAW,UAAU,OAAO;;;;;;AAO/D,SAAS,sBACP,SACA,aACA,YACe;CACf,MAAM,cAAc,mBAAmB,YAAY;CACnD,MAAM,YAAY,iBAAiB,YAAY;CAE/C,MAAM,aAAa,QAAQ,QAAQ,YAAY;AAC/C,KAAI,eAAe,GACjB,QAAO;CAGT,MAAM,WAAW,QAAQ,QAAQ,WAAW,WAAW;AACvD,KAAI,aAAa,GACf,QAAO;AAGT,QAAO,QAAQ,MAAM,GAAG,WAAW,GAAG,aAAa,QAAQ,MAAM,WAAW,UAAU,OAAO;;;;;;AAO/F,SAAS,qBACP,SACA,aACA,YACA,gBACQ;CAER,MAAM,cAAc,eAAe,QAAQ,YAAY;AACvD,KAAI,gBAAgB,GAElB,QAAO,QAAQ,SAAS,GAAG,SAAS,aAAa;AAInD,MAAK,IAAI,IAAI,cAAc,GAAG,IAAI,eAAe,QAAQ,KAAK;EAC5D,MAAM,UAAU,eAAe;AAC/B,MAAI,YAAY,OAAW;EAC3B,MAAM,aAAa,mBAAmB,QAAQ;EAC9C,MAAM,YAAY,QAAQ,QAAQ,WAAW;AAC7C,MAAI,cAAc,IAAI;GAGpB,IAAI,YAAY;AAEhB,UAAO,YAAY,KAAK,QAAQ,YAAY,OAAO,KACjD;AAGF,OAAI,YAAY,UACd;AAEF,UAAO,QAAQ,MAAM,GAAG,UAAU,GAAG,aAAa,OAAO,QAAQ,MAAM,UAAU;;;AAKrF,MAAK,IAAI,IAAI,cAAc,GAAG,KAAK,GAAG,KAAK;EACzC,MAAM,UAAU,eAAe;AAC/B,MAAI,YAAY,OAAW;EAC3B,MAAM,gBAAgB,iBAAiB,QAAQ;EAC/C,MAAM,eAAe,QAAQ,QAAQ,cAAc;AACnD,MAAI,iBAAiB,IAAI;GAEvB,MAAM,YAAY,eAAe,cAAc;AAC/C,UAAO,QAAQ,MAAM,GAAG,UAAU,GAAG,OAAO,aAAa,QAAQ,MAAM,UAAU;;;AAKrF,QAAO,QAAQ,SAAS,GAAG,OAAO,aAAa;;;;;AAMjD,SAAS,mBACP,aACA,OACA,aACA,SACe;AACf,MAAK,MAAM,CAAC,UAAU,kBAAkB,OAAO,QAAQ,MAAM,EAAE;EAE7D,MAAM,oBADa,oBAAoB,cAAc,CAChB;AAQrC,MAFqB,sBAHI,mBAAmB,mBAAmB,YAAY,EAGd,QAAQ,CAEpD,SAAS,YAAY,CACpC,QAAO;;AAGX,QAAO;;;;;;AAOT,SAAS,yBACP,gBACA,UACA,OACA,aACA,SACU;CACV,MAAM,gBAAgB,MAAM;AAC5B,KAAI,CAAC,cAAe,QAAO,EAAE;CAG7B,MAAM,oBADa,oBAAoB,cAAc,CAChB;CAMrC,MAAM,eAAe,sBAHI,mBAAmB,mBAAmB,YAAY,EAGd,QAAQ;CAIrE,MAAM,kCAAkB,IAAI,KAAa;AACzC,MAAK,MAAM,aAAa,gBAAgB;AACtC,MAAI,CAAC,aAAa,SAAS,UAAU,CAAE;AAGvC,kBAAgB,IAAI,UAAU;AAG9B,OAAK,MAAM,WAAW,aACpB,KAAI,eAAe,SAAS,UAAU,IAAI,CAAC,kBAAkB,SAAS,QAAQ,CAC5E,iBAAgB,IAAI,QAAQ;;AAKlC,QAAO,MAAM,KAAK,gBAAgB;;;;;AAMpC,SAAS,uBACP,SACA,aACA,QACA,UACA,SACe;CACf,MAAM,OAAO,YAAY,IAAI,QAAQ;AACrC,KAAI,CAAC,KAAM,QAAO;CASlB,MAAM,kBAAkB,OANiB;EACvC,GAAG;EACH;EACA;EACD,CAEkD;AAGnD,QAAO;EAAC,mBAAmB,QAAQ;EAAE;EAAiB,iBAAiB,QAAQ;EAAC,CAAC,KAAK,KAAK;;;;;;AAO7F,SAAS,qBACP,cACA,aACA,QACA,UACA,SACA,gBACA,YACQ;CACR,MAAM,WAAqB,EAAE;CAG7B,MAAM,SAAS,aAAa,mBAAmB,WAAW,GAAG;AAC7D,KAAI,OACF,UAAS,KAAK,OAAO;CAIvB,MAAM,cAAc,eAAe,cAAc,kBAAkB,EAAE,CAAC;AAEtE,MAAK,MAAM,WAAW,aAAa;EACjC,MAAM,UAAU,uBAAuB,SAAS,aAAa,QAAQ,UAAU,QAAQ;AACvF,MAAI,QACF,UAAS,KAAK,QAAQ;;AAI1B,QAAO,SAAS,KAAK,KAAK;;;;;AAM5B,SAAS,aACP,OACA,aACA,SACwB;CACxB,MAAM,UAAkC,EAAE;AAE1C,MAAK,MAAM,CAAC,UAAU,kBAAkB,OAAO,QAAQ,MAAM,EAAE;EAE7D,MAAM,oBADa,oBAAoB,cAAc,CAChB;EAMrC,MAAM,eAAe,sBAHI,mBAAmB,mBAAmB,YAAY,EAGd,QAAQ;AAErE,OAAK,MAAM,WAAW,aACpB,SAAQ,WAAW;;AAIvB,QAAO;;;;;AAMT,eAAe,0BACb,aACA,gBACA,aACe;AACf,MAAK,MAAM,CAAC,SAAS,cAAc,OAAO,QAAQ,eAAe,EAAE;EACjE,MAAM,cAAc,YAAY,IAAI,QAAQ;AAC5C,MAAI,CAAC,aAAa,UAAU,OAC1B;EAIF,MAAM,SAAS,cAAc,OAAO,EAAE,GAAG;EAGzC,MAAM,cAAc,UAAU,QAAQ,MAAM,IAAI,GAAG,EAAE;AAMrD,cAAY,iBAHI,MAAM,gBAAgB,YAAY,UAAU,QAAQ,aAAa,YAAY;;;;;;AAUjG,eAAsB,YAAY,QAAuD;CACvF,MAAM,EACJ,SACA,OACA,UAAU,EAAE,EACZ,SAAS,EAAE,EACX,WACA,UAAU,gBACV,mBACE;CACJ,MAAM,aAAa,cAAc;CAGjC,MAAM,cAAc,MAAM,mBAAmB,QAAQ;AAGrD,KAAI,eACF,OAAM,0BAA0B,aAAa,gBAAgB,QAAQ;CAIvE,MAAM,mBAA6B,EAAE;AACrC,MAAK,MAAM,iBAAiB,OAAO,OAAO,MAAM,EAAE;EAChD,MAAM,aAAa,oBAAoB,cAAc;AACrD,mBAAiB,KAAK,GAAG,WAAW,SAAS;;AAI/C,sBAAqB,SAAS,YAAY;AAG1C,qBAAoB,kBAAkB,SAAS,YAAY;CAG3D,MAAM,UAAU,aAAa,OAAO,aAAa,QAAQ;CAEzD,MAAM,UAAsC,EAAE;CAC9C,IAAI,WAAW;AAGf,KAAI,kBAAkB,eAAe,SAAS,GAC5C;OAAK,MAAM,iBAAiB,eAE1B,KAAI,CADmB,mBAAmB,eAAe,OAAO,aAAa,QAAQ,CAEnF,OAAM,IAAI,MAAM,mBAAmB,cAAc,uCAAuC;;AAM9F,MAAK,MAAM,CAAC,UAAU,kBAAkB,OAAO,QAAQ,MAAM,EAAE;EAC7D,MAAM,aAAa,oBAAoB,cAAc;EACrD,MAAM,oBAAoB,WAAW;AAErC,MAAI,kBAAkB,WAAW,EAC/B;EAOF,MAAM,eAAe,sBAHI,mBAAmB,mBAAmB,YAAY,EAGd,QAAQ;AAErE,MAAI,aAAa,WAAW,EAC1B;EAIF,MAAM,WAAW,KAAK,IAAI,GAAG,aAAa,KAAK,MAAM,YAAY,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC;EAGrF,MAAM,uBAAuB,KAAK,IAAI,IAAI,QAAQ,gBAAgB,MAAM,WAAW,GAAG;EAStF,MAAM,eAAe,sBAAsB;GACzC,GAAG;GACH,cAAc;GACf,CAAC;EAGF,MAAM,SAAS,WAAW,UAAU;AAGpC,MAAI,mBAAmB,UAAa,eAAe,SAAS,GAAG;GAE7D,MAAM,qBAAqB,yBACzB,gBACA,UACA,OACA,aACA,QACD;AAGD,OAAI,mBAAmB,WAAW,EAChC;GAIF,IAAI,kBAAkB,SAAS,SAAS;GACxC,IAAI,aAAuD;GAC3D,MAAM,QAAkB,EAAE;AAE1B,QAAK,MAAM,iBAAiB,oBAAoB;IAE9C,MAAM,aAAa,uBACjB,eACA,aACA,QACA,UACA,QACD;AAED,QAAI,CAAC,WACH,OAAM,IAAI,MAAM,mBAAmB,cAAc,yBAAyB;IAK5E,MAAM,SADgB,kBAAkB,MACR,aAAa,mBAAmB,WAAW,GAAG;IAI9E,MAAM,mBAAmB,MAAM,eAHZ,SAAS,GAAG,OAAO,IAAI,eAAe,YAGC,UAAU;AAEpE,QAAI,CAAC,iBAAiB;AAEpB,SAAI,YAAY;AACd,gBAAU,UAAU,iBAAiB;AACrC,wBAAkB;AAClB,mBAAa;YACR;AACL,iBAAW;AACX,mBAAa;AACb,YAAM,KACJ,wCAAwC,cAAc,gCACvD;;AAEH;;IAIF,MAAM,kBAAkB,sBAAsB,iBAAiB,cAAc;IAG7E,MAAM,uBAAuB,sBAAsB,kBAAkB,cAAc;AAEnF,QAAI,CAAC,qBACH,OAAM,IAAI,MACR,2DAA2D,cAAc,GAC1E;AAGH,QAAI,CAAC,iBAAiB;AAEpB,SAAI,YAAY;AACd,wBAAkB,qBAChB,iBACA,eACA,sBACA,kBACD;AACD,gBAAU,UAAU,gBAAgB;AACpC,UAAI,eAAe,UACjB,cAAa;YAEV;AACL,iBAAW;AACX,mBAAa;AACb,YAAM,KAAK,uDAAuD,cAAc,GAAG;;AAErF;;AAIF,QAAI,oBAAoB,qBACtB,KAAI,YAAY;KAEd,MAAM,iBAAiB,sBACrB,iBACA,eACA,qBACD;AACD,SAAI,gBAAgB;AAClB,wBAAkB;AAClB,gBAAU,UAAU,gBAAgB;AACpC,UAAI,eAAe,UACjB,cAAa;WAGf,OAAM,IAAI,MAAM,0CAA0C,cAAc,GAAG;WAExE;AACL,gBAAW;AACX,kBAAa;AACb,WAAM,KAAK,WAAW,iBAAiB,qBAAqB,CAAC;;;AAKnE,WAAQ,KAAK;IACX,MAAM;IACN,QAAQ;IACR,MAAM,MAAM,SAAS,IAAI,MAAM,KAAK,OAAO,GAAG;IAC/C,CAAC;SACG;GAaL,MAAM,oBAAoB,MAAM,eAXZ,qBAClB,cACA,aACA,QACA,UACA,SACA,mBACA,WACD,EAG2D,UAAU;GAEtE,MAAM,aAAa,oBAAoB,mBAAmB,SAAS;AAEnE,OAAI,WAAW,MACb,SAAQ,KAAK;IACX,MAAM;IACN,QAAQ;IACT,CAAC;YACO,YAAY;AACrB,cAAU,UAAU,kBAAkB;AACtC,YAAQ,KAAK;KACX,MAAM;KACN,QAAQ,WAAW,aAAa,YAAY;KAC7C,CAAC;UACG;AACL,eAAW;AACX,YAAQ,KAAK;KACX,MAAM;KACN,QAAQ;KACR,MAAM,WAAW;KAClB,CAAC;;;;AAKR,QAAO;EACL,SAAS,CAAC;EACV,OAAO;EACP,OAAO,WACH,0CAA0C,kBAAkB,oBAC5D;EACL;;;;;;AAOH,eAAsB,eAAe,QAA0C;CAC7E,MAAM,SAAS,MAAM,YAAY,OAAO;AAExC,KAAI,CAAC,OAAO,SAAS;EACnB,MAAM,eAAe,OAAO,MACzB,QAAQ,MAAM,EAAE,WAAW,OAAO,CAClC,KAAK,MAAM;GACV,IAAI,MAAM,SAAS,EAAE,KAAK;AAC1B,OAAI,EAAE,KACJ,QAAO,EAAE;AAEX,UAAO;IACP,CACD,KAAK,OAAO;AAEf,QAAM,IAAI,MACR,iDAAiD,aAAa,eAChD,kBAAkB,oCACjC;;;;;;;;;;AAWL,SAAgB,YACd,QACA,YACM;AACN,KAAI,CAAC,cAAc,CACjB;AAGF,KAAI,OAAO,WAAW,SACpB,YAAW,QAAQ,WAAW;KAE9B,MAAK,MAAM,YAAY,OAAO,KAAK,OAAO,MAAM,CAC9C,YAAW,UAAU,WAAW;;;;;;;;;;;ACz4BtC,SAAS,kBAAkB,MAAsC;AAI/D,QADkBC,uCADHC,MAAE,OAAO,KAAK,CACU,CACtB;;;;;;;;;;;;;;;;;;;;;;;;;AA0BnB,SAAgB,gBAAgB,MAAiB,SAAoC;CAInF,MAAM,eAHS,kBAAkB,KAAK,CAGV,QAAQ,MAAM,CAAC,EAAE,WAAW;AAExD,KAAI,aAAa,WAAW,EAC1B,QAAO;AAMT,KAAI,SAAS,QACX,QAAO,oBAAoB,cAAc,QAAQ,QAAQ;AAG3D,QAAO,4BAA4B,aAAa;;;;;AAMlD,SAASC,kBAAgB,KAAqB;AAC5C,QAAO,IAAI,QAAQ,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;;;;;AAMtD,SAAS,mBAAmB,OAAwB;AAClD,KAAI,UAAU,OACZ,QAAO;AAET,QAAO,KAAK,KAAK,UAAU,MAAM,CAAC;;;;;AAMpC,SAAS,oBACP,SACA,SACQ;CACR,MAAM,QAAkB,EAAE;CAG1B,MAAM,cAAwB,EAAE;CAChC,MAAM,iBAA2B,EAAE;AAEnC,MAAK,MAAM,OAAO,QAChB,SAAQ,KAAR;EACE,KAAK;AACH,eAAY,KAAK,SAAS;AAC1B,kBAAe,KAAK,SAAS;AAC7B;EACF,KAAK;AACH,eAAY,KAAK,QAAQ;AACzB,kBAAe,KAAK,QAAQ;AAC5B;EACF,KAAK;AACH,eAAY,KAAK,cAAc;AAC/B,kBAAe,KAAK,cAAc;AAClC;EACF,KAAK;AACH,eAAY,KAAK,UAAU;AAC3B,kBAAe,KAAK,UAAU;AAC9B;EACF,KAAK;AACH,eAAY,KAAK,MAAM;AACvB,kBAAe,KAAK,MAAM;AAC1B;;AAIN,OAAM,KAAK,KAAK,YAAY,KAAK,MAAM,CAAC,IAAI;AAC5C,OAAM,KAAK,KAAK,eAAe,KAAK,MAAM,CAAC,IAAI;AAG/C,MAAK,MAAM,OAAO,SAAS;EACzB,MAAM,QAAkB,EAAE;AAE1B,OAAK,MAAM,OAAO,QAChB,SAAQ,KAAR;GACE,KAAK,UAAU;IACb,MAAM,cAAc,IAAI,eAAe,IAAI,QAAQ,aAAa,CAAC,QAAQ,MAAM,IAAI;IACnF,MAAM,aACJ,IAAI,SAAS,YACT,OAAO,IAAI,QAAQ,MACnB,OAAO,IAAI,QAAQ,IAAI,YAAY;AACzC,UAAM,KAAK,WAAW;AACtB;;GAEF,KAAK;AACH,UAAM,KAAK,IAAI,QAAQ,MAAM,IAAI,MAAM,MAAM,IAAI;AACjD;GACF,KAAK;AACH,UAAM,KAAKA,kBAAgB,IAAI,eAAe,GAAG,CAAC;AAClD;GACF,KAAK;AACH,UAAM,KAAK,mBAAmB,IAAI,aAAa,CAAC;AAChD;GACF,KAAK,OAAO;IACV,MAAM,WAAW,IAAI,MACjB,MAAM,QAAQ,IAAI,IAAI,GACpB,IAAI,IAAI,KAAK,MAAM,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,GACzC,KAAK,IAAI,IAAI,MACf;AACJ,UAAM,KAAK,SAAS;AACpB;;;AAKN,QAAM,KAAK,KAAK,MAAM,KAAK,MAAM,CAAC,IAAI;;AAGxC,QAAO,MAAM,KAAK,KAAK;;;;;;;;ACpKzB,SAAS,gBAAgB,KAAqB;AAC5C,QAAO,IAAI,QAAQ,OAAO,MAAM,CAAC,QAAQ,OAAO,IAAI;;;;;AAMtD,SAAS,eAAe,aAA6B;AACnD,QAAO,YAAY,QAAQ,QAAQ,IAAI,CAAC,aAAa;;;;;AA8BvD,SAAS,cAAc,MAA4B;AACjD,QAAO,KAAK,YAAY,WAAW;;;;;;;;;;AAWrC,SAAS,eACP,cACA,aACA,UACU;CACV,MAAM,SAAmB,EAAE;AAE3B,MAAK,MAAM,WAAW,cAAc;EAClC,MAAM,OAAO,YAAY,IAAI,QAAQ;AACrC,MAAI,CAAC,KAAM;AAEX,MAAI,cAAc,KAAK,CAErB,QAAO,KAAK,QAAQ;MAGpB,MAAK,MAAM,CAAC,MAAM,aAAa,YAK7B,KAFE,YAAY,KAAK,KAAK,SAAS,IAAI,KAAK,WAAW,UAAU,IAAI,IAAI,SAAS,SAI9E;OAAI,cAAc,SAAS,IAAI,CAAC,SAC9B,QAAO,KAAK,KAAK;;;AAO3B,QAAO;;;;;AAMT,SAAS,eACP,UACA,aACA,cACA,UACQ;CACR,MAAM,IAAI,IAAI,OAAO,aAAa;CAClC,MAAM,QAAkB,EAAE;AAG1B,OAAM,KAAK,GAAG,EAAE,IAAI,SAAS,MAAM,IAAI,SAAS,QAAQ,GAAG;AAC3D,OAAM,KAAK,GAAG;AAGd,OAAM,KAAK,SAAS,YAAY;AAChC,OAAM,KAAK,GAAG;CAGd,MAAM,eAAe,eAAe,SAAS,UAAU,aAAa,SAAS;AAG7E,OAAM,KAAK,4BAA4B;AACvC,OAAM,KAAK,4BAA4B;AAEvC,MAAK,MAAM,WAAW,cAAc;EAClC,MAAM,OAAO,YAAY,IAAI,QAAQ;AACrC,MAAI,CAAC,KAAM;AAGX,MAAI,YAAY,CAAC,cAAc,KAAK,CAAE;EAEtC,MAAM,cAAc,WAAW,KAAK;EACpC,MAAM,SAAS,eAAe,YAAY;EAC1C,MAAM,OAAO,gBAAgB,KAAK,eAAe,GAAG;AAEpD,QAAM,KAAK,MAAM,YAAY,IAAI,SAAS,QAAQ,GAAG,OAAO,MAAM,KAAK,IAAI;;AAG7E,QAAO,MAAM,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCzB,eAAsB,mBACpB,SACA,YACA,SACiB;CACjB,MAAM,eAAe,SAAS,gBAAgB;CAC9C,MAAM,WAAW,SAAS,YAAY;CAGtC,MAAM,cAAc,MAAM,mBAAmB,QAAQ;CAGrD,MAAM,WAAqB,EAAE;AAC7B,MAAK,MAAM,YAAY,YAAY;EACjC,MAAM,UAAU,eAAe,UAAU,aAAa,cAAc,SAAS;AAC7E,WAAS,KAAK,QAAQ;;AAGxB,QAAO,SAAS,KAAK,OAAO"}
1
+ {"version":3,"file":"index.cjs","names":["escapeTableCell","formatDefaultValue","generateAnchor","path","fs","getExtractedFields","resolveLazyCommand","createLogCollector","extractFields","z","escapeTableCell"],"sources":["../../src/docs/default-renderers.ts","../../src/docs/doc-comparator.ts","../../src/docs/doc-generator.ts","../../src/docs/example-executor.ts","../../src/docs/types.ts","../../src/docs/golden-test.ts","../../src/docs/render-args.ts","../../src/docs/render-index.ts"],"sourcesContent":["import type { ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { Example } from \"../types.js\";\nimport type {\n ArgumentsRenderContext,\n CommandInfo,\n DefaultRendererOptions,\n ExampleExecutionResult,\n ExamplesRenderContext,\n ExamplesRenderOptions,\n OptionsRenderContext,\n RenderContentOptions,\n RenderFunction,\n SimpleRenderContext,\n SubCommandInfo,\n SubcommandsRenderContext,\n SubcommandsRenderOptions,\n} from \"./types.js\";\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Format default value for display\n */\nfunction formatDefaultValue(value: unknown): string {\n if (value === undefined) {\n return \"-\";\n }\n return `\\`${JSON.stringify(value)}\\``;\n}\n\n/**\n * Render usage line\n */\nexport function renderUsage(info: CommandInfo): string {\n const parts: string[] = [info.fullCommandPath];\n\n if (info.options.length > 0) {\n parts.push(\"[options]\");\n }\n\n if (info.subCommands.length > 0) {\n parts.push(\"[command]\");\n }\n\n for (const arg of info.positionalArgs) {\n if (arg.required) {\n parts.push(`<${arg.name}>`);\n } else {\n parts.push(`[${arg.name}]`);\n }\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Render arguments as table\n */\nexport function renderArgumentsTable(info: CommandInfo): string {\n if (info.positionalArgs.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Argument | Description | Required |\");\n lines.push(\"|----------|-------------|----------|\");\n\n for (const arg of info.positionalArgs) {\n const desc = escapeTableCell(arg.description ?? \"\");\n const required = arg.required ? \"Yes\" : \"No\";\n lines.push(`| \\`${arg.name}\\` | ${desc} | ${required} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments as list\n */\nexport function renderArgumentsList(info: CommandInfo): string {\n if (info.positionalArgs.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const arg of info.positionalArgs) {\n const required = arg.required ? \"(required)\" : \"(optional)\";\n const desc = arg.description ? ` - ${arg.description}` : \"\";\n lines.push(`- \\`${arg.name}\\`${desc} ${required}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format environment variable info for display\n */\nfunction formatEnvInfo(env: string | string[] | undefined): string {\n if (!env) return \"\";\n const envNames = Array.isArray(env) ? env : [env];\n return ` [env: ${envNames.join(\", \")}]`;\n}\n\n/**\n * Format option flags (uses kebab-case cliName)\n */\nfunction formatOptionFlags(opt: ResolvedFieldMeta): string {\n const parts: string[] = [];\n\n // Use cliName (kebab-case) for CLI display\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const longFlag =\n opt.type === \"boolean\" ? `--${opt.cliName}` : `--${opt.cliName} <${placeholder}>`;\n\n if (opt.alias) {\n parts.push(`\\`-${opt.alias}\\`, \\`${longFlag}\\``);\n } else {\n parts.push(`\\`${longFlag}\\``);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Render options as markdown table\n *\n * Features:\n * - Uses kebab-case (cliName) for option names (e.g., `--dry-run` instead of `--dryRun`)\n * - Automatically adds Env column when any option has env configured\n * - Displays multiple env vars as comma-separated list\n *\n * @example\n * | Option | Alias | Description | Required | Default | Env |\n * |--------|-------|-------------|----------|---------|-----|\n * | `--dry-run` | `-d` | Dry run mode | No | `false` | - |\n * | `--port <PORT>` | - | Server port | Yes | - | `PORT`, `SERVER_PORT` |\n */\nexport function renderOptionsTable(info: CommandInfo): string {\n if (info.options.length === 0) {\n return \"\";\n }\n\n // Check if any option has env configured\n const hasEnv = info.options.some((opt) => opt.env);\n\n const lines: string[] = [];\n if (hasEnv) {\n lines.push(\"| Option | Alias | Description | Required | Default | Env |\");\n lines.push(\"|--------|-------|-------------|----------|---------|-----|\");\n } else {\n lines.push(\"| Option | Alias | Description | Required | Default |\");\n lines.push(\"|--------|-------|-------------|----------|---------|\");\n }\n\n for (const opt of info.options) {\n // Use cliName (kebab-case) for CLI display\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\" ? `\\`--${opt.cliName}\\`` : `\\`--${opt.cliName} <${placeholder}>\\``;\n const alias = opt.alias ? `\\`-${opt.alias}\\`` : \"-\";\n const desc = escapeTableCell(opt.description ?? \"\");\n const required = opt.required ? \"Yes\" : \"No\";\n const defaultVal = formatDefaultValue(opt.defaultValue);\n\n if (hasEnv) {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n lines.push(\n `| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`,\n );\n } else {\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options as markdown list\n *\n * Features:\n * - Uses kebab-case (cliName) for option names (e.g., `--dry-run` instead of `--dryRun`)\n * - Appends env info at the end of each option (e.g., `[env: PORT, SERVER_PORT]`)\n *\n * @example\n * - `-d`, `--dry-run` - Dry run mode (default: false)\n * - `--port <PORT>` - Server port (required) [env: PORT, SERVER_PORT]\n */\nexport function renderOptionsList(info: CommandInfo): string {\n if (info.options.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const opt of info.options) {\n const flags = formatOptionFlags(opt);\n const desc = opt.description ? ` - ${opt.description}` : \"\";\n const required = opt.required ? \" (required)\" : \"\";\n const defaultVal =\n opt.defaultValue !== undefined ? ` (default: ${JSON.stringify(opt.defaultValue)})` : \"\";\n const envInfo = formatEnvInfo(opt.env);\n lines.push(`- ${flags}${desc}${required}${defaultVal}${envInfo}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Generate anchor from command path\n */\nfunction generateAnchor(commandPath: string[]): string {\n return commandPath.join(\"-\").toLowerCase();\n}\n\n/**\n * Generate relative path from one file to another\n */\nfunction getRelativePath(from: string, to: string): string {\n const fromParts = from.split(\"/\").slice(0, -1); // directory of 'from'\n const toParts = to.split(\"/\");\n\n // Find common prefix\n let commonLength = 0;\n while (\n commonLength < fromParts.length &&\n commonLength < toParts.length - 1 &&\n fromParts[commonLength] === toParts[commonLength]\n ) {\n commonLength++;\n }\n\n // Build relative path\n const upCount = fromParts.length - commonLength;\n const relativeParts = [...Array(upCount).fill(\"..\"), ...toParts.slice(commonLength)];\n\n return relativeParts.join(\"/\") || (toParts[toParts.length - 1] ?? \"\");\n}\n\n/**\n * Render subcommands as table\n */\nexport function renderSubcommandsTable(info: CommandInfo, generateAnchors = true): string {\n if (info.subCommands.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n const currentFile = info.filePath;\n const fileMap = info.fileMap;\n\n for (const sub of info.subCommands) {\n const fullName = sub.fullPath.join(\" \");\n const desc = escapeTableCell(sub.description ?? \"\");\n const subCommandPath = sub.fullPath.join(\" \");\n\n if (generateAnchors) {\n const anchor = generateAnchor(sub.fullPath);\n const subFile = fileMap?.[subCommandPath];\n\n if (currentFile && subFile && currentFile !== subFile) {\n // Cross-file link\n const relativePath = getRelativePath(currentFile, subFile);\n lines.push(`| [\\`${fullName}\\`](${relativePath}#${anchor}) | ${desc} |`);\n } else {\n // Same-file anchor\n lines.push(`| [\\`${fullName}\\`](#${anchor}) | ${desc} |`);\n }\n } else {\n lines.push(`| \\`${fullName}\\` | ${desc} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options from array as table\n */\nexport function renderOptionsTableFromArray(options: ResolvedFieldMeta[]): string {\n if (options.length === 0) {\n return \"\";\n }\n\n // Check if any option has env configured\n const hasEnv = options.some((opt) => opt.env);\n\n const lines: string[] = [];\n if (hasEnv) {\n lines.push(\"| Option | Alias | Description | Required | Default | Env |\");\n lines.push(\"|--------|-------|-------------|----------|---------|-----|\");\n } else {\n lines.push(\"| Option | Alias | Description | Required | Default |\");\n lines.push(\"|--------|-------|-------------|----------|---------|\");\n }\n\n for (const opt of options) {\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\" ? `\\`--${opt.cliName}\\`` : `\\`--${opt.cliName} <${placeholder}>\\``;\n const alias = opt.alias ? `\\`-${opt.alias}\\`` : \"-\";\n const desc = escapeTableCell(opt.description ?? \"\");\n const required = opt.required ? \"Yes\" : \"No\";\n const defaultVal = formatDefaultValue(opt.defaultValue);\n\n if (hasEnv) {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n lines.push(\n `| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} | ${envNames} |`,\n );\n } else {\n lines.push(`| ${optionName} | ${alias} | ${desc} | ${required} | ${defaultVal} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render options from array as list\n */\nexport function renderOptionsListFromArray(options: ResolvedFieldMeta[]): string {\n if (options.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const opt of options) {\n const flags = formatOptionFlags(opt);\n const desc = opt.description ? ` - ${opt.description}` : \"\";\n const required = opt.required ? \" (required)\" : \"\";\n const defaultVal =\n opt.defaultValue !== undefined ? ` (default: ${JSON.stringify(opt.defaultValue)})` : \"\";\n const envInfo = formatEnvInfo(opt.env);\n lines.push(`- ${flags}${desc}${required}${defaultVal}${envInfo}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments from array as table\n */\nexport function renderArgumentsTableFromArray(args: ResolvedFieldMeta[]): string {\n if (args.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Argument | Description | Required |\");\n lines.push(\"|----------|-------------|----------|\");\n\n for (const arg of args) {\n const desc = escapeTableCell(arg.description ?? \"\");\n const required = arg.required ? \"Yes\" : \"No\";\n lines.push(`| \\`${arg.name}\\` | ${desc} | ${required} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render arguments from array as list\n */\nexport function renderArgumentsListFromArray(args: ResolvedFieldMeta[]): string {\n if (args.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n for (const arg of args) {\n const required = arg.required ? \"(required)\" : \"(optional)\";\n const desc = arg.description ? ` - ${arg.description}` : \"\";\n lines.push(`- \\`${arg.name}\\`${desc} ${required}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render subcommands from array as table\n */\nexport function renderSubcommandsTableFromArray(\n subcommands: SubCommandInfo[],\n info: CommandInfo,\n generateAnchors = true,\n): string {\n if (subcommands.length === 0) {\n return \"\";\n }\n\n const lines: string[] = [];\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n const currentFile = info.filePath;\n const fileMap = info.fileMap;\n\n for (const sub of subcommands) {\n const fullName = sub.fullPath.join(\" \");\n const desc = escapeTableCell(sub.description ?? \"\");\n const subCommandPath = sub.fullPath.join(\" \");\n\n if (generateAnchors) {\n const anchor = generateAnchor(sub.fullPath);\n const subFile = fileMap?.[subCommandPath];\n\n if (currentFile && subFile && currentFile !== subFile) {\n // Cross-file link\n const relativePath = getRelativePath(currentFile, subFile);\n lines.push(`| [\\`${fullName}\\`](${relativePath}#${anchor}) | ${desc} |`);\n } else {\n // Same-file anchor\n lines.push(`| [\\`${fullName}\\`](#${anchor}) | ${desc} |`);\n }\n } else {\n lines.push(`| \\`${fullName}\\` | ${desc} |`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render examples as markdown\n *\n * @example\n * **Basic usage**\n *\n * ```bash\n * $ greet World\n * ```\n *\n * Output:\n * ```\n * Hello, World!\n * ```\n */\nexport function renderExamplesDefault(\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n): string {\n if (examples.length === 0) {\n return \"\";\n }\n\n const showOutput = opts?.showOutput ?? true;\n const prefix = opts?.commandPrefix ? `${opts.commandPrefix} ` : \"\";\n const lines: string[] = [];\n\n for (let i = 0; i < examples.length; i++) {\n const example = examples[i];\n if (!example) continue;\n\n const result = results?.[i];\n\n // Description as bold text\n lines.push(`**${example.desc}**`);\n lines.push(\"\");\n\n // Command and output in a single code block\n lines.push(\"```bash\");\n lines.push(`$ ${prefix}${example.cmd}`);\n\n // Output\n if (showOutput) {\n if (result) {\n // Use captured output from execution\n if (result.stdout) {\n lines.push(result.stdout);\n }\n if (result.stderr) {\n lines.push(`[stderr] ${result.stderr}`);\n }\n } else if (example.output) {\n // Use expected output from definition\n lines.push(example.output);\n }\n }\n\n lines.push(\"```\");\n lines.push(\"\");\n }\n\n // Remove trailing empty lines\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Create command renderer with options\n */\nexport function createCommandRenderer(options: DefaultRendererOptions = {}): RenderFunction {\n const {\n headingLevel = 1,\n optionStyle = \"table\",\n generateAnchors = true,\n includeSubcommandDetails = true,\n renderDescription: customRenderDescription,\n renderUsage: customRenderUsage,\n renderArguments: customRenderArguments,\n renderOptions: customRenderOptions,\n renderSubcommands: customRenderSubcommands,\n renderNotes: customRenderNotes,\n renderFooter: customRenderFooter,\n renderExamples: customRenderExamples,\n } = options;\n\n return (info: CommandInfo): string => {\n const lines: string[] = [];\n // Calculate effective heading level based on command depth\n // depth=1 → headingLevel, depth=2 → headingLevel+1, etc.\n const effectiveLevel = Math.min(headingLevel + (info.depth - 1), 6);\n const h = \"#\".repeat(effectiveLevel);\n\n // Title - use commandPath for subcommands, name for root\n const title = info.commandPath || info.name;\n lines.push(`${h} ${title}`);\n lines.push(\"\");\n\n // Description\n if (info.description) {\n const context: SimpleRenderContext = {\n content: info.description,\n heading: \"\",\n info,\n };\n const content = customRenderDescription ? customRenderDescription(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Usage\n {\n const defaultUsage = `**Usage**\\n\\n\\`\\`\\`\\n${renderUsage(info)}\\n\\`\\`\\``;\n const context: SimpleRenderContext = {\n content: defaultUsage,\n heading: \"**Usage**\",\n info,\n };\n const content = customRenderUsage ? customRenderUsage(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Arguments\n if (info.positionalArgs.length > 0) {\n const renderArgs = (args: ResolvedFieldMeta[], opts?: RenderContentOptions): string => {\n const style = opts?.style ?? optionStyle;\n const withHeading = opts?.withHeading ?? true;\n const content =\n style === \"table\"\n ? renderArgumentsTableFromArray(args)\n : renderArgumentsListFromArray(args);\n return withHeading ? `**Arguments**\\n\\n${content}` : content;\n };\n\n const context: ArgumentsRenderContext = {\n args: info.positionalArgs,\n render: renderArgs,\n heading: \"**Arguments**\",\n info,\n };\n\n const content = customRenderArguments\n ? customRenderArguments(context)\n : renderArgs(context.args);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Options\n if (info.options.length > 0) {\n const renderOpts = (opts: ResolvedFieldMeta[], renderOpts?: RenderContentOptions): string => {\n const style = renderOpts?.style ?? optionStyle;\n const withHeading = renderOpts?.withHeading ?? true;\n const content =\n style === \"table\" ? renderOptionsTableFromArray(opts) : renderOptionsListFromArray(opts);\n return withHeading ? `**Options**\\n\\n${content}` : content;\n };\n\n const context: OptionsRenderContext = {\n options: info.options,\n render: renderOpts,\n heading: \"**Options**\",\n info,\n };\n\n const content = customRenderOptions\n ? customRenderOptions(context)\n : renderOpts(context.options);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Subcommands\n if (info.subCommands.length > 0) {\n const effectiveAnchors = generateAnchors && includeSubcommandDetails;\n\n const renderSubs = (subs: SubCommandInfo[], opts?: SubcommandsRenderOptions): string => {\n const anchors = opts?.generateAnchors ?? effectiveAnchors;\n const withHeading = opts?.withHeading ?? true;\n const content = renderSubcommandsTableFromArray(subs, info, anchors);\n return withHeading ? `**Commands**\\n\\n${content}` : content;\n };\n\n const context: SubcommandsRenderContext = {\n subcommands: info.subCommands,\n render: renderSubs,\n heading: \"**Commands**\",\n info,\n };\n\n const content = customRenderSubcommands\n ? customRenderSubcommands(context)\n : renderSubs(context.subcommands);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Examples\n if (info.examples && info.examples.length > 0) {\n const renderEx = (\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n ): string => {\n const withHeading = opts?.withHeading ?? true;\n const mergedOpts: ExamplesRenderOptions = {\n commandPrefix: info.fullCommandPath,\n ...opts,\n };\n const content = renderExamplesDefault(examples, results, mergedOpts);\n return withHeading ? `**Examples**\\n\\n${content}` : content;\n };\n\n const context: ExamplesRenderContext = {\n examples: info.examples,\n results: info.exampleResults,\n render: renderEx,\n heading: \"**Examples**\",\n info,\n };\n\n const content = customRenderExamples\n ? customRenderExamples(context)\n : renderEx(context.examples, context.results);\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Notes\n if (info.notes) {\n const context: SimpleRenderContext = {\n content: `**Notes**\\n\\n${info.notes}`,\n heading: \"**Notes**\",\n info,\n };\n const content = customRenderNotes ? customRenderNotes(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Footer (default is empty)\n {\n const context: SimpleRenderContext = {\n content: \"\",\n heading: \"\",\n info,\n };\n const content = customRenderFooter ? customRenderFooter(context) : context.content;\n if (content) {\n lines.push(content);\n lines.push(\"\");\n }\n }\n\n // Remove trailing empty lines and ensure single newline at end\n while (lines.length > 0 && lines[lines.length - 1] === \"\") {\n lines.pop();\n }\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n };\n}\n\n/**\n * Default renderers presets\n */\nexport const defaultRenderers = {\n /** Standard command documentation */\n command: (options?: DefaultRendererOptions) => createCommandRenderer(options),\n /** Table style options (default) */\n tableStyle: createCommandRenderer({ optionStyle: \"table\" }),\n /** List style options */\n listStyle: createCommandRenderer({ optionStyle: \"list\" }),\n};\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\n/**\n * Comparison result\n */\nexport interface CompareResult {\n /** Whether the content matches */\n match: boolean;\n /** Diff content (only when match is false) */\n diff?: string;\n /** Whether the file exists */\n fileExists: boolean;\n}\n\n/**\n * Compare generated content with existing file\n */\nexport function compareWithExisting(generatedContent: string, filePath: string): CompareResult {\n const absolutePath = path.resolve(filePath);\n\n if (!fs.existsSync(absolutePath)) {\n return {\n match: false,\n fileExists: false,\n };\n }\n\n const existingContent = fs.readFileSync(absolutePath, \"utf-8\");\n\n if (generatedContent === existingContent) {\n return {\n match: true,\n fileExists: true,\n };\n }\n\n return {\n match: false,\n diff: formatDiff(existingContent, generatedContent),\n fileExists: true,\n };\n}\n\n/**\n * Format diff between two strings in unified diff format\n */\nexport function formatDiff(expected: string, actual: string): string {\n const expectedLines = expected.split(\"\\n\");\n const actualLines = actual.split(\"\\n\");\n\n const result: string[] = [];\n result.push(\"--- existing\");\n result.push(\"+++ generated\");\n result.push(\"\");\n\n // Simple line-by-line diff\n const maxLines = Math.max(expectedLines.length, actualLines.length);\n let inChunk = false;\n let chunkStart = 0;\n const chunk: string[] = [];\n\n const flushChunk = (): void => {\n if (chunk.length > 0) {\n result.push(`@@ -${chunkStart + 1},${chunk.length} @@`);\n result.push(...chunk);\n chunk.length = 0;\n }\n inChunk = false;\n };\n\n for (let i = 0; i < maxLines; i++) {\n const expectedLine = expectedLines[i];\n const actualLine = actualLines[i];\n\n if (expectedLine === actualLine) {\n if (inChunk) {\n // Add context line\n chunk.push(` ${expectedLine ?? \"\"}`);\n // If we have more than 3 context lines after a change, flush the chunk\n const lastChangeIndex = chunk.findIndex(\n (line, idx) =>\n (line.startsWith(\"-\") || line.startsWith(\"+\")) &&\n chunk.slice(idx + 1).every((l) => l.startsWith(\" \")),\n );\n if (lastChangeIndex !== -1 && chunk.length - lastChangeIndex > 3) {\n flushChunk();\n }\n }\n } else {\n if (!inChunk) {\n inChunk = true;\n chunkStart = i;\n // Add up to 3 lines of context before\n const contextStart = Math.max(0, i - 3);\n for (let j = contextStart; j < i; j++) {\n chunk.push(` ${expectedLines[j] ?? \"\"}`);\n }\n }\n\n if (expectedLine !== undefined && (actualLine === undefined || expectedLine !== actualLine)) {\n chunk.push(`-${expectedLine}`);\n }\n if (actualLine !== undefined && (expectedLine === undefined || expectedLine !== actualLine)) {\n chunk.push(`+${actualLine}`);\n }\n }\n }\n\n flushChunk();\n\n return result.join(\"\\n\");\n}\n\n/**\n * Write content to file, creating directories if needed\n */\nexport function writeFile(filePath: string, content: string): void {\n const absolutePath = path.resolve(filePath);\n const dir = path.dirname(absolutePath);\n\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n fs.writeFileSync(absolutePath, content, \"utf-8\");\n}\n\n/**\n * Read file content if it exists\n * Returns null if file does not exist\n */\nexport function readFile(filePath: string): string | null {\n const absolutePath = path.resolve(filePath);\n\n if (!fs.existsSync(absolutePath)) {\n return null;\n }\n\n return fs.readFileSync(absolutePath, \"utf-8\");\n}\n\n/**\n * Minimal fs interface for deleteFile\n */\nexport interface DeleteFileFs {\n existsSync: typeof fs.existsSync;\n unlinkSync: typeof fs.unlinkSync;\n}\n\n/**\n * Delete file if it exists\n * @param filePath - Path to the file to delete\n * @param fileSystem - Optional fs implementation (useful when fs is mocked)\n */\nexport function deleteFile(filePath: string, fileSystem: DeleteFileFs = fs): void {\n const absolutePath = path.resolve(filePath);\n\n if (fileSystem.existsSync(absolutePath)) {\n fileSystem.unlinkSync(absolutePath);\n }\n}\n","import { getExtractedFields } from \"../core/schema-extractor.js\";\nimport { resolveLazyCommand } from \"../executor/subcommand-router.js\";\nimport type { AnyCommand } from \"../types.js\";\nimport type { CommandInfo, SubCommandInfo } from \"./types.js\";\n\n/**\n * Build CommandInfo from a command\n */\nexport async function buildCommandInfo(\n command: AnyCommand,\n rootName: string,\n commandPath: string[] = [],\n): Promise<CommandInfo> {\n const extracted = getExtractedFields(command);\n\n const positionalArgs = extracted?.fields.filter((f) => f.positional) ?? [];\n const options = extracted?.fields.filter((f) => !f.positional) ?? [];\n\n const subCommands: SubCommandInfo[] = [];\n if (command.subCommands) {\n for (const [name, subCmd] of Object.entries(command.subCommands)) {\n const resolved = await resolveLazyCommand(subCmd);\n const fullPath = [...commandPath, name];\n subCommands.push({\n name,\n description: resolved.description,\n fullPath,\n });\n }\n }\n\n return {\n name: command.name ?? \"\",\n description: command.description,\n fullCommandPath: commandPath.length > 0 ? `${rootName} ${commandPath.join(\" \")}` : rootName,\n commandPath: commandPath.join(\" \"),\n depth: commandPath.length + 1,\n positionalArgs,\n options,\n subCommands,\n extracted,\n command,\n notes: command.notes,\n examples: command.examples,\n };\n}\n\n/**\n * Collect all commands with their paths\n * Returns a map of command path -> CommandInfo\n */\nexport async function collectAllCommands(\n command: AnyCommand,\n rootName?: string,\n): Promise<Map<string, CommandInfo>> {\n const root = rootName ?? command.name ?? \"command\";\n const result = new Map<string, CommandInfo>();\n\n async function traverse(cmd: AnyCommand, path: string[]): Promise<void> {\n const info = await buildCommandInfo(cmd, root, path);\n const pathKey = path.join(\" \");\n result.set(pathKey, info);\n\n if (cmd.subCommands) {\n for (const [name, subCmd] of Object.entries(cmd.subCommands)) {\n const resolved = await resolveLazyCommand(subCmd);\n await traverse(resolved, [...path, name]);\n }\n }\n }\n\n await traverse(command, []);\n return result;\n}\n","import { createLogCollector } from \"../executor/log-collector.js\";\nimport type { AnyCommand, Example } from \"../types.js\";\nimport type { ExampleCommandConfig, ExampleExecutionResult } from \"./types.js\";\n\n/**\n * Execute examples for a command and capture output\n *\n * @param examples - Examples to execute\n * @param config - Execution configuration (mock setup/cleanup)\n * @param rootCommand - Root command to execute against\n * @param commandPath - Command path for subcommands (e.g., [\"config\", \"get\"])\n * @returns Array of execution results with captured stdout/stderr\n */\nexport async function executeExamples(\n examples: Example[],\n config: ExampleCommandConfig,\n rootCommand: AnyCommand,\n commandPath: string[] = [],\n): Promise<ExampleExecutionResult[]> {\n const results: ExampleExecutionResult[] = [];\n\n // Setup mock if provided\n if (config.mock) {\n await config.mock();\n }\n\n try {\n for (const example of examples) {\n const result = await executeSingleExample(example, rootCommand, commandPath);\n results.push(result);\n }\n } finally {\n // Cleanup mock if provided\n if (config.cleanup) {\n await config.cleanup();\n }\n }\n\n return results;\n}\n\n/**\n * Execute a single example and capture output\n */\nasync function executeSingleExample(\n example: Example,\n rootCommand: AnyCommand,\n commandPath: string[],\n): Promise<ExampleExecutionResult> {\n // Parse command string into argv\n const exampleArgs = parseExampleCmd(example.cmd);\n\n // Build full argv: command path + example args\n const argv = [...commandPath, ...exampleArgs];\n\n // Use unified log collector (don't passthrough to console)\n const collector = createLogCollector({ passthrough: false });\n collector.start();\n\n let success = true;\n try {\n // Import runCommand dynamically to avoid circular dependency\n const { runCommand } = await import(\"../core/runner.js\");\n const result = await runCommand(rootCommand, argv);\n success = result.success;\n\n // Also capture any errors from the result\n if (!result.success && result.error) {\n console.error(result.error.message);\n }\n } catch (error) {\n success = false;\n console.error(error instanceof Error ? error.message : String(error));\n } finally {\n collector.stop();\n }\n\n // Convert entries to stdout/stderr strings\n const logs = collector.getLogs();\n const stdout = logs.entries\n .filter((e) => e.stream === \"stdout\")\n .map((e) => e.message)\n .join(\"\\n\");\n const stderr = logs.entries\n .filter((e) => e.stream === \"stderr\")\n .map((e) => e.message)\n .join(\"\\n\");\n\n return {\n cmd: example.cmd,\n desc: example.desc,\n expectedOutput: example.output,\n stdout,\n stderr,\n success,\n };\n}\n\n/**\n * Parse example command string into argv array\n * Handles quoted strings (single and double quotes)\n *\n * @example\n * parseExampleCmd('World') // ['World']\n * parseExampleCmd('--name \"John Doe\"') // ['--name', 'John Doe']\n * parseExampleCmd(\"--greeting 'Hello World'\") // ['--greeting', 'Hello World']\n */\nfunction parseExampleCmd(cmd: string): string[] {\n const args: string[] = [];\n let current = \"\";\n let inQuote = false;\n let quoteChar = \"\";\n\n for (let i = 0; i < cmd.length; i++) {\n const char = cmd[i]!;\n\n if ((char === '\"' || char === \"'\") && !inQuote) {\n inQuote = true;\n quoteChar = char;\n } else if (char === quoteChar && inQuote) {\n inQuote = false;\n quoteChar = \"\";\n } else if (char === \" \" && !inQuote) {\n if (current) {\n args.push(current);\n current = \"\";\n }\n } else {\n current += char;\n }\n }\n\n if (current) {\n args.push(current);\n }\n\n return args;\n}\n","import type { ExtractedFields, ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport type { AnyCommand, Example } from \"../types.js\";\n\n/**\n * Command information for rendering\n */\nexport interface CommandInfo {\n /** Command name */\n name: string;\n /** Command description */\n description?: string | undefined;\n /** Full command path (e.g., \"my-cli config get\") */\n fullCommandPath: string;\n /** Command path relative to root (e.g., \"\" for root, \"config\" for subcommand) */\n commandPath: string;\n /** Command depth (1 for root commands, 2 for subcommands, etc.) */\n depth: number;\n /** Positional arguments */\n positionalArgs: ResolvedFieldMeta[];\n /** Options (non-positional arguments) */\n options: ResolvedFieldMeta[];\n /** Subcommand information */\n subCommands: SubCommandInfo[];\n /** Extracted field information from schema */\n extracted: ExtractedFields | null;\n /** Original command object */\n command: AnyCommand;\n /** Additional notes */\n notes?: string | undefined;\n /** File path where this command is rendered (for cross-file links) */\n filePath?: string | undefined;\n /** Map of command path to file path (for cross-file links) */\n fileMap?: Record<string, string> | undefined;\n /** Example definitions from command */\n examples?: Example[] | undefined;\n /** Example execution results (populated when examples are executed) */\n exampleResults?: ExampleExecutionResult[] | undefined;\n}\n\n/**\n * Subcommand information\n */\nexport interface SubCommandInfo {\n /** Subcommand name */\n name: string;\n /** Subcommand description */\n description?: string | undefined;\n /** Full command path */\n fullPath: string[];\n}\n\n/**\n * Example execution result\n */\nexport interface ExampleExecutionResult {\n /** Command arguments that were executed */\n cmd: string;\n /** Description of the example */\n desc: string;\n /** Expected output (if defined in example) */\n expectedOutput?: string | undefined;\n /** Captured stdout */\n stdout: string;\n /** Captured stderr */\n stderr: string;\n /** Whether execution was successful */\n success: boolean;\n}\n\n/**\n * Example execution config for a specific command path\n * If a command path is specified in ExampleConfig, its examples will be executed\n */\nexport interface ExampleCommandConfig {\n /** Mock setup before running examples */\n mock?: () => void | Promise<void>;\n /** Mock cleanup after running examples */\n cleanup?: () => void | Promise<void>;\n}\n\n/**\n * Example execution configuration\n * Key is command path (e.g., \"\", \"config\", \"config get\")\n * All specified command paths will have their examples executed\n *\n * @example\n * // With mock setup\n * { \"\": { mock: () => mockFs(), cleanup: () => restoreFs() } }\n *\n * // Without mock (just execute)\n * { \"user\": true }\n */\nexport type ExampleConfig = Record<string, ExampleCommandConfig | true>;\n\n/**\n * Render function type for custom markdown generation\n */\nexport type RenderFunction = (info: CommandInfo) => string;\n\n/**\n * Section render function type (legacy)\n * @param defaultContent - The default rendered content for this section\n * @param info - Command information\n * @returns The final content to render (return empty string to hide section)\n * @deprecated Use context-based render functions instead\n */\nexport type SectionRenderFunction = (defaultContent: string, info: CommandInfo) => string;\n\n/**\n * Render options for options/arguments\n */\nexport interface RenderContentOptions {\n /** Style for rendering */\n style?: \"table\" | \"list\";\n /** Include heading (default: true) */\n withHeading?: boolean;\n}\n\n/**\n * Options render context\n */\nexport interface OptionsRenderContext {\n /** Options to render */\n options: ResolvedFieldMeta[];\n /** Render function that accepts options and optional rendering options */\n render: (options: ResolvedFieldMeta[], opts?: RenderContentOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type OptionsRenderFunction = (context: OptionsRenderContext) => string;\n\n/**\n * Arguments render context\n */\nexport interface ArgumentsRenderContext {\n /** Arguments to render */\n args: ResolvedFieldMeta[];\n /** Render function that accepts arguments and optional rendering options */\n render: (args: ResolvedFieldMeta[], opts?: RenderContentOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type ArgumentsRenderFunction = (context: ArgumentsRenderContext) => string;\n\n/**\n * Subcommands render options\n */\nexport interface SubcommandsRenderOptions {\n /** Generate anchor links */\n generateAnchors?: boolean;\n /** Include heading (default: true) */\n withHeading?: boolean;\n}\n\n/**\n * Subcommands render context\n */\nexport interface SubcommandsRenderContext {\n /** Subcommands to render */\n subcommands: SubCommandInfo[];\n /** Render function that accepts subcommands and optional rendering options */\n render: (subcommands: SubCommandInfo[], opts?: SubcommandsRenderOptions) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type SubcommandsRenderFunction = (context: SubcommandsRenderContext) => string;\n\n/**\n * Examples render options\n */\nexport interface ExamplesRenderOptions {\n /** Include heading (default: true) */\n withHeading?: boolean;\n /** Show execution output (default: true when results available) */\n showOutput?: boolean;\n /** Command prefix to prepend to example commands (e.g., \"my-cli config get\") */\n commandPrefix?: string;\n}\n\n/**\n * Examples render context\n */\nexport interface ExamplesRenderContext {\n /** Examples to render */\n examples: Example[];\n /** Execution results (if examples were executed) */\n results?: ExampleExecutionResult[] | undefined;\n /** Render function that accepts examples, results, and optional rendering options */\n render: (\n examples: Example[],\n results?: ExampleExecutionResult[],\n opts?: ExamplesRenderOptions,\n ) => string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type ExamplesRenderFunction = (context: ExamplesRenderContext) => string;\n\n/**\n * Simple section render context (for description, usage, notes, footer)\n */\nexport interface SimpleRenderContext {\n /** Default content */\n content: string;\n /** Heading prefix (e.g., \"###\") */\n heading: string;\n /** Command information */\n info: CommandInfo;\n}\nexport type SimpleRenderFunction = (context: SimpleRenderContext) => string;\n\n/**\n * Default renderer customization options\n */\nexport interface DefaultRendererOptions {\n /** Heading level (default: 1) */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Option display style */\n optionStyle?: \"table\" | \"list\";\n /** Generate anchor links to subcommands */\n generateAnchors?: boolean;\n /** Include subcommand details */\n includeSubcommandDetails?: boolean;\n /** Custom renderer for description section */\n renderDescription?: SimpleRenderFunction;\n /** Custom renderer for usage section */\n renderUsage?: SimpleRenderFunction;\n /** Custom renderer for arguments section */\n renderArguments?: ArgumentsRenderFunction;\n /** Custom renderer for options section */\n renderOptions?: OptionsRenderFunction;\n /** Custom renderer for subcommands section */\n renderSubcommands?: SubcommandsRenderFunction;\n /** Custom renderer for notes section */\n renderNotes?: SimpleRenderFunction;\n /** Custom renderer for footer (default content is empty) */\n renderFooter?: SimpleRenderFunction;\n /** Custom renderer for examples section */\n renderExamples?: ExamplesRenderFunction;\n}\n\n/**\n * Per-file configuration with custom renderer\n */\nexport interface FileConfig {\n /** Command paths to include in this file (e.g., [\"\", \"user\", \"config get\"]) */\n commands: string[];\n /** Custom renderer for this file (optional) */\n render?: RenderFunction;\n /** File title (prepended to the file content) */\n title?: string;\n /** File description (added after title) */\n description?: string;\n}\n\n/**\n * File mapping configuration\n * Key: output file path (e.g., \"docs/cli.md\")\n * Value: command paths array or FileConfig object\n *\n * @example\n * // Simple: single file with multiple commands\n * { \"docs/cli.md\": [\"\", \"user\", \"config\"] }\n *\n * // With custom renderer\n * { \"docs/cli.md\": { commands: [\"\"], render: customRenderer } }\n */\nexport type FileMapping = Record<string, string[] | FileConfig>;\n\n/**\n * generateDoc configuration\n */\nexport interface GenerateDocConfig {\n /** Command to generate documentation for */\n command: AnyCommand;\n /** File output configuration (command path -> file mapping) */\n files: FileMapping;\n /** Command paths to ignore (including their subcommands) */\n ignores?: string[];\n /** Default renderer options (used when render is not specified per file) */\n format?: DefaultRendererOptions;\n /** Formatter function to apply to generated content before comparison */\n formatter?: FormatterFunction;\n /** Example execution configuration (per command path) */\n examples?: ExampleConfig;\n /**\n * Target command paths to validate (e.g., [\"read\", \"config get\"])\n * When specified, only these commands' sections are validated.\n * The full document structure is used to maintain cross-file links.\n */\n targetCommands?: string[];\n}\n\n/**\n * generateDoc result\n */\nexport interface GenerateDocResult {\n /** Whether all files matched or were updated successfully */\n success: boolean;\n /** File processing results */\n files: Array<{\n /** File path */\n path: string;\n /** Status of this file */\n status: \"match\" | \"created\" | \"updated\" | \"diff\";\n /** Diff content (only when status is \"diff\") */\n diff?: string | undefined;\n }>;\n /** Error message (when success is false) */\n error?: string | undefined;\n}\n\n/**\n * Formatter function type\n * Formats generated content before comparison\n */\nexport type FormatterFunction = (content: string) => string | Promise<string>;\n\n/**\n * Environment variable name for update mode\n */\nexport const UPDATE_GOLDEN_ENV = \"POLITTY_DOCS_UPDATE\";\n\n/**\n * Marker prefix for command sections in generated documentation\n * Format: <!-- politty:command:<path>:start --> ... <!-- politty:command:<path>:end -->\n */\nexport const COMMAND_MARKER_PREFIX = \"politty:command\";\n\n/**\n * Generate start marker for a command section\n */\nexport function commandStartMarker(commandPath: string): string {\n return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:start -->`;\n}\n\n/**\n * Generate end marker for a command section\n */\nexport function commandEndMarker(commandPath: string): string {\n return `<!-- ${COMMAND_MARKER_PREFIX}:${commandPath}:end -->`;\n}\n","import { createCommandRenderer } from \"./default-renderers.js\";\nimport {\n compareWithExisting,\n deleteFile,\n formatDiff,\n readFile,\n writeFile,\n type DeleteFileFs,\n} from \"./doc-comparator.js\";\nimport { collectAllCommands } from \"./doc-generator.js\";\nimport { executeExamples } from \"./example-executor.js\";\nimport type {\n CommandInfo,\n ExampleConfig,\n FileConfig,\n FormatterFunction,\n GenerateDocConfig,\n GenerateDocResult,\n RenderFunction,\n} from \"./types.js\";\nimport { commandEndMarker, commandStartMarker, UPDATE_GOLDEN_ENV } from \"./types.js\";\n\n/**\n * Apply formatter to content if provided\n * Supports both sync and async formatters\n */\nasync function applyFormatter(\n content: string,\n formatter: FormatterFunction | undefined,\n): Promise<string> {\n if (!formatter) {\n return content;\n }\n return await formatter(content);\n}\n\n/**\n * Check if update mode is enabled via environment variable\n */\nfunction isUpdateMode(): boolean {\n const value = process.env[UPDATE_GOLDEN_ENV];\n return value === \"true\" || value === \"1\";\n}\n\n/**\n * Normalize file mapping entry to FileConfig\n */\nfunction normalizeFileConfig(config: string[] | FileConfig): FileConfig {\n if (Array.isArray(config)) {\n return { commands: config };\n }\n return config;\n}\n\n/**\n * Check if a command path is a subcommand of another\n */\nfunction isSubcommandOf(childPath: string, parentPath: string): boolean {\n if (parentPath === \"\") return true; // Root is parent of everything\n if (childPath === parentPath) return true;\n return childPath.startsWith(parentPath + \" \");\n}\n\n/**\n * Check if a pattern contains wildcards\n */\nfunction containsWildcard(pattern: string): boolean {\n return pattern.includes(\"*\");\n}\n\n/**\n * Check if a command path matches a wildcard pattern\n * - `*` matches any single command segment\n * - Pattern segments are space-separated\n *\n * @example\n * matchesWildcard(\"config get\", \"* *\") // true\n * matchesWildcard(\"config\", \"* *\") // false\n * matchesWildcard(\"config get\", \"config *\") // true\n * matchesWildcard(\"greet\", \"*\") // true\n */\nfunction matchesWildcard(path: string, pattern: string): boolean {\n const pathSegments = path === \"\" ? [] : path.split(\" \");\n const patternSegments = pattern === \"\" ? [] : pattern.split(\" \");\n\n if (pathSegments.length !== patternSegments.length) {\n return false;\n }\n\n for (let i = 0; i < patternSegments.length; i++) {\n const patternSeg = patternSegments[i]!;\n const pathSeg = pathSegments[i]!;\n\n if (patternSeg !== \"*\" && patternSeg !== pathSeg) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Expand a wildcard pattern to matching command paths\n */\nfunction expandWildcardPattern(pattern: string, allCommands: Map<string, CommandInfo>): string[] {\n const matches: string[] = [];\n\n for (const cmdPath of allCommands.keys()) {\n if (matchesWildcard(cmdPath, pattern)) {\n matches.push(cmdPath);\n }\n }\n\n return matches;\n}\n\n/**\n * Check if a path matches any ignore pattern (with wildcard support)\n * For wildcard patterns, also ignores subcommands of matched commands\n */\nfunction matchesIgnorePattern(path: string, ignorePattern: string): boolean {\n if (containsWildcard(ignorePattern)) {\n // Check if path matches the wildcard pattern exactly\n if (matchesWildcard(path, ignorePattern)) {\n return true;\n }\n // Check if path is a subcommand of any command matching the pattern\n // e.g., \"config get\" is a subcommand of \"config\" which matches \"*\"\n const pathSegments = path === \"\" ? [] : path.split(\" \");\n const patternSegments = ignorePattern === \"\" ? [] : ignorePattern.split(\" \");\n\n // If path is deeper than pattern, check if prefix matches\n if (pathSegments.length > patternSegments.length) {\n const prefixPath = pathSegments.slice(0, patternSegments.length).join(\" \");\n return matchesWildcard(prefixPath, ignorePattern);\n }\n return false;\n }\n // For non-wildcards, use original subcommand logic\n return isSubcommandOf(path, ignorePattern);\n}\n\n/**\n * Expand command paths to include all subcommands (with wildcard support)\n */\nfunction expandCommandPaths(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n): string[] {\n const expanded = new Set<string>();\n\n for (const cmdPath of commandPaths) {\n if (containsWildcard(cmdPath)) {\n // Expand wildcard pattern to matching commands\n const matches = expandWildcardPattern(cmdPath, allCommands);\n for (const match of matches) {\n expanded.add(match);\n // Also add subcommands of matched commands\n for (const path of allCommands.keys()) {\n if (isSubcommandOf(path, match)) {\n expanded.add(path);\n }\n }\n }\n } else {\n // Add the command itself\n if (allCommands.has(cmdPath)) {\n expanded.add(cmdPath);\n }\n // Add all subcommands\n for (const path of allCommands.keys()) {\n if (isSubcommandOf(path, cmdPath)) {\n expanded.add(path);\n }\n }\n }\n }\n\n return Array.from(expanded);\n}\n\n/**\n * Filter out ignored commands (with wildcard support)\n */\nfunction filterIgnoredCommands(commandPaths: string[], ignores: string[]): string[] {\n return commandPaths.filter((path) => {\n return !ignores.some((ignorePattern) => matchesIgnorePattern(path, ignorePattern));\n });\n}\n\n/**\n * Validate that there are no conflicts between files and ignores (with wildcard support)\n */\nfunction validateNoConflicts(\n filesCommands: string[],\n ignores: string[],\n allCommands: Map<string, CommandInfo>,\n): void {\n const conflicts: string[] = [];\n\n for (const filePattern of filesCommands) {\n // Expand file pattern if it's a wildcard\n const filePaths = containsWildcard(filePattern)\n ? expandWildcardPattern(filePattern, allCommands)\n : [filePattern];\n\n for (const filePath of filePaths) {\n for (const ignorePattern of ignores) {\n if (containsWildcard(ignorePattern)) {\n // For wildcard ignores, check if file path matches the pattern\n if (matchesWildcard(filePath, ignorePattern)) {\n conflicts.push(`\"${filePath}\" is both in files and ignored by \"${ignorePattern}\"`);\n }\n } else {\n // For non-wildcard ignores, use original logic\n if (filePath === ignorePattern || isSubcommandOf(filePath, ignorePattern)) {\n conflicts.push(`\"${filePath}\" is both in files and ignored by \"${ignorePattern}\"`);\n }\n }\n }\n }\n }\n\n if (conflicts.length > 0) {\n throw new Error(`Conflict between files and ignores:\\n - ${conflicts.join(\"\\n - \")}`);\n }\n}\n\n/**\n * Validate that all ignored paths exist in the command tree (with wildcard support)\n */\nfunction validateIgnoresExist(ignores: string[], allCommands: Map<string, CommandInfo>): void {\n const nonExistent: string[] = [];\n\n for (const ignorePattern of ignores) {\n if (containsWildcard(ignorePattern)) {\n // For wildcard patterns, check if at least one command matches\n const matches = expandWildcardPattern(ignorePattern, allCommands);\n if (matches.length === 0) {\n nonExistent.push(`\"${ignorePattern}\"`);\n }\n } else {\n // For non-wildcard paths, check exact existence\n if (!allCommands.has(ignorePattern)) {\n nonExistent.push(`\"${ignorePattern}\"`);\n }\n }\n }\n\n if (nonExistent.length > 0) {\n throw new Error(`Ignored command paths do not exist: ${nonExistent.join(\", \")}`);\n }\n}\n\n/**\n * Sort command paths in depth-first order while preserving the specified command order\n * Parent commands are immediately followed by their subcommands\n */\nfunction sortDepthFirst(commandPaths: string[], specifiedOrder: string[]): string[] {\n // Build a set of all paths for quick lookup\n const pathSet = new Set(commandPaths);\n\n // Find top-level commands (those that match specified order or have no parent in the set)\n const topLevelPaths = specifiedOrder.filter((cmd) => pathSet.has(cmd));\n\n // Also include any commands not in specifiedOrder (for safety)\n for (const path of commandPaths) {\n const depth = path === \"\" ? 0 : path.split(\" \").length;\n if (depth === 1 && !topLevelPaths.includes(path)) {\n topLevelPaths.push(path);\n }\n }\n\n const result: string[] = [];\n const visited = new Set<string>();\n\n function addWithChildren(cmdPath: string): void {\n if (visited.has(cmdPath) || !pathSet.has(cmdPath)) return;\n visited.add(cmdPath);\n result.push(cmdPath);\n\n // Find and add direct children in alphabetical order\n const children = commandPaths\n .filter((p) => {\n if (p === cmdPath || visited.has(p)) return false;\n // Check if p is a direct child of cmdPath\n if (cmdPath === \"\") {\n return p.split(\" \").length === 1;\n }\n return p.startsWith(cmdPath + \" \") && p.split(\" \").length === cmdPath.split(\" \").length + 1;\n })\n .sort((a, b) => a.localeCompare(b));\n\n for (const child of children) {\n addWithChildren(child);\n }\n }\n\n // Start with top-level commands in specified order\n for (const topLevel of topLevelPaths) {\n addWithChildren(topLevel);\n }\n\n // Add any remaining paths (shouldn't happen normally)\n for (const path of commandPaths) {\n if (!visited.has(path)) {\n result.push(path);\n }\n }\n\n return result;\n}\n\n/**\n * Generate file header from FileConfig\n */\nfunction generateFileHeader(fileConfig: FileConfig): string | null {\n if (!fileConfig.title && !fileConfig.description) {\n return null;\n }\n\n const parts: string[] = [];\n if (fileConfig.title) {\n parts.push(`# ${fileConfig.title}`);\n }\n if (fileConfig.description) {\n parts.push(\"\");\n parts.push(fileConfig.description);\n }\n parts.push(\"\");\n\n return parts.join(\"\\n\");\n}\n\n/**\n * Extract a command section from content using markers\n * Returns the content between start and end markers (including markers)\n */\nfunction extractCommandSection(content: string, commandPath: string): string | null {\n const startMarker = commandStartMarker(commandPath);\n const endMarker = commandEndMarker(commandPath);\n\n const startIndex = content.indexOf(startMarker);\n if (startIndex === -1) {\n return null;\n }\n\n const endIndex = content.indexOf(endMarker, startIndex);\n if (endIndex === -1) {\n return null;\n }\n\n return content.slice(startIndex, endIndex + endMarker.length);\n}\n\n/**\n * Replace a command section in content using markers\n * Returns the updated content with the new section\n */\nfunction replaceCommandSection(\n content: string,\n commandPath: string,\n newSection: string,\n): string | null {\n const startMarker = commandStartMarker(commandPath);\n const endMarker = commandEndMarker(commandPath);\n\n const startIndex = content.indexOf(startMarker);\n if (startIndex === -1) {\n return null;\n }\n\n const endIndex = content.indexOf(endMarker, startIndex);\n if (endIndex === -1) {\n return null;\n }\n\n return content.slice(0, startIndex) + newSection + content.slice(endIndex + endMarker.length);\n}\n\n/**\n * Insert a command section at the correct position based on specified order\n * Returns the updated content with the section inserted at the right position\n */\nfunction insertCommandSection(\n content: string,\n commandPath: string,\n newSection: string,\n specifiedOrder: string[],\n): string {\n // Find the index of the target command in the specified order\n const targetIndex = specifiedOrder.indexOf(commandPath);\n if (targetIndex === -1) {\n // If not in order, append to end\n return content.trimEnd() + \"\\n\\n\" + newSection + \"\\n\";\n }\n\n // Find the next command in the order that exists in the content\n for (let i = targetIndex + 1; i < specifiedOrder.length; i++) {\n const nextCmd = specifiedOrder[i];\n if (nextCmd === undefined) continue;\n const nextMarker = commandStartMarker(nextCmd);\n const nextIndex = content.indexOf(nextMarker);\n if (nextIndex !== -1) {\n // Insert before the next section\n // Find the start of the line (after previous section's newlines)\n let insertPos = nextIndex;\n // Go back to find proper insertion point (skip leading newlines)\n while (insertPos > 0 && content[insertPos - 1] === \"\\n\") {\n insertPos--;\n }\n // Keep one newline as separator\n if (insertPos < nextIndex) {\n insertPos++;\n }\n return content.slice(0, insertPos) + newSection + \"\\n\" + content.slice(nextIndex);\n }\n }\n\n // Find the previous command in the order that exists in the content\n for (let i = targetIndex - 1; i >= 0; i--) {\n const prevCmd = specifiedOrder[i];\n if (prevCmd === undefined) continue;\n const prevEndMarker = commandEndMarker(prevCmd);\n const prevEndIndex = content.indexOf(prevEndMarker);\n if (prevEndIndex !== -1) {\n // Insert after the previous section\n const insertPos = prevEndIndex + prevEndMarker.length;\n return content.slice(0, insertPos) + \"\\n\" + newSection + content.slice(insertPos);\n }\n }\n\n // No reference point found, append to end\n return content.trimEnd() + \"\\n\" + newSection + \"\\n\";\n}\n\n/**\n * Find which file contains a specific command\n */\nfunction findFileForCommand(\n commandPath: string,\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): string | null {\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n if (commandPaths.includes(commandPath)) {\n return filePath;\n }\n }\n return null;\n}\n\n/**\n * Find which target commands are contained in a file\n * Also expands each target command to include subcommands that are NOT explicitly in specifiedCommands\n */\nfunction findTargetCommandsInFile(\n targetCommands: string[],\n filePath: string,\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): string[] {\n const fileConfigRaw = files[filePath];\n if (!fileConfigRaw) return [];\n\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n // Expand targetCommands to include their subcommands,\n // but exclude subcommands that are explicitly in specifiedCommands\n const expandedTargets = new Set<string>();\n for (const targetCmd of targetCommands) {\n if (!commandPaths.includes(targetCmd)) continue;\n\n // Add the target command itself\n expandedTargets.add(targetCmd);\n\n // Add subcommands that are NOT explicitly specified\n for (const cmdPath of commandPaths) {\n if (isSubcommandOf(cmdPath, targetCmd) && !specifiedCommands.includes(cmdPath)) {\n expandedTargets.add(cmdPath);\n }\n }\n }\n\n return Array.from(expandedTargets);\n}\n\n/**\n * Generate a single command section with markers\n */\nfunction generateCommandSection(\n cmdPath: string,\n allCommands: Map<string, CommandInfo>,\n render: RenderFunction,\n filePath?: string,\n fileMap?: Record<string, string>,\n): string | null {\n const info = allCommands.get(cmdPath);\n if (!info) return null;\n\n // Add file context to CommandInfo for cross-file link generation\n const infoWithFileContext: CommandInfo = {\n ...info,\n filePath,\n fileMap,\n };\n\n const renderedSection = render(infoWithFileContext);\n\n // Wrap section with markers for partial validation\n return [commandStartMarker(cmdPath), renderedSection, commandEndMarker(cmdPath)].join(\"\\n\");\n}\n\n/**\n * Generate markdown for a file containing multiple commands\n * Each command section is wrapped with markers for partial validation\n */\nfunction generateFileMarkdown(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n render: RenderFunction,\n filePath?: string,\n fileMap?: Record<string, string>,\n specifiedOrder?: string[],\n fileConfig?: FileConfig,\n): string {\n const sections: string[] = [];\n\n // Add file header if title or description is provided\n const header = fileConfig ? generateFileHeader(fileConfig) : null;\n if (header) {\n sections.push(header);\n }\n\n // Sort commands depth-first while preserving specified order\n const sortedPaths = sortDepthFirst(commandPaths, specifiedOrder ?? []);\n\n for (const cmdPath of sortedPaths) {\n const section = generateCommandSection(cmdPath, allCommands, render, filePath, fileMap);\n if (section) {\n sections.push(section);\n }\n }\n\n return sections.join(\"\\n\");\n}\n\n/**\n * Build a map of command path to file path\n */\nfunction buildFileMap(\n files: GenerateDocConfig[\"files\"],\n allCommands: Map<string, CommandInfo>,\n ignores: string[],\n): Record<string, string> {\n const fileMap: Record<string, string> = {};\n\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n for (const cmdPath of commandPaths) {\n fileMap[cmdPath] = filePath;\n }\n }\n\n return fileMap;\n}\n\n/**\n * Execute examples for commands based on configuration\n */\nasync function executeConfiguredExamples(\n allCommands: Map<string, CommandInfo>,\n examplesConfig: ExampleConfig,\n rootCommand: import(\"../types.js\").AnyCommand,\n): Promise<void> {\n for (const [cmdPath, cmdConfig] of Object.entries(examplesConfig)) {\n const commandInfo = allCommands.get(cmdPath);\n if (!commandInfo?.examples?.length) {\n continue;\n }\n\n // Normalize config: true means no mock setup\n const config = cmdConfig === true ? {} : cmdConfig;\n\n // Parse command path into array\n const commandPath = cmdPath ? cmdPath.split(\" \") : [];\n\n // Execute examples and store results\n const results = await executeExamples(commandInfo.examples, config, rootCommand, commandPath);\n\n // Update CommandInfo with execution results\n commandInfo.exampleResults = results;\n }\n}\n\n/**\n * Generate documentation from command definition\n */\nexport async function generateDoc(config: GenerateDocConfig): Promise<GenerateDocResult> {\n const {\n command,\n files,\n ignores = [],\n format = {},\n formatter,\n examples: examplesConfig,\n targetCommands,\n } = config;\n const updateMode = isUpdateMode();\n\n // Collect all commands\n const allCommands = await collectAllCommands(command);\n\n // Execute examples for all commands specified in examplesConfig\n if (examplesConfig) {\n await executeConfiguredExamples(allCommands, examplesConfig, command);\n }\n\n // Collect all explicitly specified commands from files\n const allFilesCommands: string[] = [];\n for (const fileConfigRaw of Object.values(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n allFilesCommands.push(...fileConfig.commands);\n }\n\n // Validate ignores refer to existing commands\n validateIgnoresExist(ignores, allCommands);\n\n // Validate no conflicts between files and ignores\n validateNoConflicts(allFilesCommands, ignores, allCommands);\n\n // Build file map for cross-file links\n const fileMap = buildFileMap(files, allCommands, ignores);\n\n const results: GenerateDocResult[\"files\"] = [];\n let hasError = false;\n\n // Validate all targetCommands exist in files\n if (targetCommands && targetCommands.length > 0) {\n for (const targetCommand of targetCommands) {\n const targetFilePath = findFileForCommand(targetCommand, files, allCommands, ignores);\n if (!targetFilePath) {\n throw new Error(`Target command \"${targetCommand}\" not found in any file configuration`);\n }\n }\n }\n\n // Process each file\n for (const [filePath, fileConfigRaw] of Object.entries(files)) {\n const fileConfig = normalizeFileConfig(fileConfigRaw);\n const specifiedCommands = fileConfig.commands;\n\n if (specifiedCommands.length === 0) {\n continue;\n }\n\n // Expand to include subcommands\n const expandedCommands = expandCommandPaths(specifiedCommands, allCommands);\n\n // Filter out ignored commands\n const commandPaths = filterIgnoredCommands(expandedCommands, ignores);\n\n if (commandPaths.length === 0) {\n continue;\n }\n\n // Calculate minimum depth in this file for relative heading level\n const minDepth = Math.min(...commandPaths.map((p) => allCommands.get(p)?.depth ?? 1));\n\n // Adjust headingLevel so that minimum depth command gets the configured headingLevel\n const adjustedHeadingLevel = Math.max(1, (format?.headingLevel ?? 1) - (minDepth - 1)) as\n | 1\n | 2\n | 3\n | 4\n | 5\n | 6;\n\n // Create file-specific renderer with adjusted headingLevel (if no custom renderer)\n const fileRenderer = createCommandRenderer({\n ...format,\n headingLevel: adjustedHeadingLevel,\n });\n\n // Use custom renderer if provided, otherwise use file-specific renderer\n const render = fileConfig.render ?? fileRenderer;\n\n // Handle partial validation when targetCommands are specified\n if (targetCommands !== undefined && targetCommands.length > 0) {\n // Find which target commands are in this file\n const fileTargetCommands = findTargetCommandsInFile(\n targetCommands,\n filePath,\n files,\n allCommands,\n ignores,\n );\n\n // Skip files that don't contain any target commands\n if (fileTargetCommands.length === 0) {\n continue;\n }\n\n // Read existing content once for all target commands in this file\n let existingContent = readFile(filePath);\n let fileStatus: \"match\" | \"created\" | \"updated\" | \"diff\" = \"match\";\n const diffs: string[] = [];\n\n for (const targetCommand of fileTargetCommands) {\n // Generate only the target command's section\n const rawSection = generateCommandSection(\n targetCommand,\n allCommands,\n render,\n filePath,\n fileMap,\n );\n\n if (!rawSection) {\n throw new Error(`Target command \"${targetCommand}\" not found in commands`);\n }\n\n // For root command, include file header if configured\n const isRootCommand = targetCommand === \"\";\n const header = isRootCommand && fileConfig ? generateFileHeader(fileConfig) : null;\n const rawContent = header ? `${header}\\n${rawSection}` : rawSection;\n\n // Apply formatter to the section\n const generatedSection = await applyFormatter(rawContent, formatter);\n\n if (!existingContent) {\n // File doesn't exist yet, create it with the section only\n if (updateMode) {\n writeFile(filePath, generatedSection);\n existingContent = generatedSection;\n fileStatus = \"created\";\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(\n `File does not exist. Target command \"${targetCommand}\" section cannot be validated.`,\n );\n }\n continue;\n }\n\n // Extract existing section for comparison\n const existingSection = extractCommandSection(existingContent, targetCommand);\n\n // For comparison, extract just the section from generated content (without header)\n const generatedSectionOnly = extractCommandSection(generatedSection, targetCommand);\n\n if (!generatedSectionOnly) {\n throw new Error(\n `Generated content does not contain section for command \"${targetCommand}\"`,\n );\n }\n\n if (!existingSection) {\n // Section doesn't exist in existing file - insert at correct position\n if (updateMode) {\n existingContent = insertCommandSection(\n existingContent,\n targetCommand,\n generatedSectionOnly,\n specifiedCommands,\n );\n writeFile(filePath, existingContent);\n if (fileStatus !== \"created\") {\n fileStatus = \"updated\";\n }\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(`Existing file does not contain section for command \"${targetCommand}\"`);\n }\n continue;\n }\n\n // Compare sections\n if (existingSection !== generatedSectionOnly) {\n if (updateMode) {\n // Replace only the target command section in the existing file\n const updatedContent = replaceCommandSection(\n existingContent,\n targetCommand,\n generatedSectionOnly,\n );\n if (updatedContent) {\n existingContent = updatedContent;\n writeFile(filePath, existingContent);\n if (fileStatus !== \"created\") {\n fileStatus = \"updated\";\n }\n } else {\n throw new Error(`Failed to replace section for command \"${targetCommand}\"`);\n }\n } else {\n hasError = true;\n fileStatus = \"diff\";\n diffs.push(formatDiff(existingSection, generatedSectionOnly));\n }\n }\n }\n\n results.push({\n path: filePath,\n status: fileStatus,\n diff: diffs.length > 0 ? diffs.join(\"\\n\\n\") : undefined,\n });\n } else {\n // Generate markdown with file context (pass specifiedCommands as order hint)\n const rawMarkdown = generateFileMarkdown(\n commandPaths,\n allCommands,\n render,\n filePath,\n fileMap,\n specifiedCommands,\n fileConfig,\n );\n\n // Apply formatter if provided\n const generatedMarkdown = await applyFormatter(rawMarkdown, formatter);\n // Full file comparison (original behavior)\n const comparison = compareWithExisting(generatedMarkdown, filePath);\n\n if (comparison.match) {\n results.push({\n path: filePath,\n status: \"match\",\n });\n } else if (updateMode) {\n writeFile(filePath, generatedMarkdown);\n results.push({\n path: filePath,\n status: comparison.fileExists ? \"updated\" : \"created\",\n });\n } else {\n hasError = true;\n results.push({\n path: filePath,\n status: \"diff\",\n diff: comparison.diff,\n });\n }\n }\n }\n\n return {\n success: !hasError,\n files: results,\n error: hasError\n ? `Documentation is out of date. Run with ${UPDATE_GOLDEN_ENV}=true to update.`\n : undefined,\n };\n}\n\n/**\n * Assert that documentation matches golden files\n * Throws an error if there are differences and update mode is not enabled\n */\nexport async function assertDocMatch(config: GenerateDocConfig): Promise<void> {\n const result = await generateDoc(config);\n\n if (!result.success) {\n const diffMessages = result.files\n .filter((f) => f.status === \"diff\")\n .map((f) => {\n let msg = `File: ${f.path}\\n`;\n if (f.diff) {\n msg += f.diff;\n }\n return msg;\n })\n .join(\"\\n\\n\");\n\n throw new Error(\n `Documentation does not match golden files.\\n\\n${diffMessages}\\n\\n` +\n `Run with ${UPDATE_GOLDEN_ENV}=true to update the documentation.`,\n );\n }\n}\n\n/**\n * Initialize documentation files by deleting them\n * Only deletes when update mode is enabled (POLITTY_DOCS_UPDATE=true)\n * Use this in beforeAll to ensure skipped tests don't leave stale sections\n * @param config - Config containing files to initialize, or a single file path\n * @param fileSystem - Optional fs implementation (useful when fs is mocked)\n */\nexport function initDocFile(\n config: Pick<GenerateDocConfig, \"files\"> | string,\n fileSystem?: DeleteFileFs,\n): void {\n if (!isUpdateMode()) {\n return;\n }\n\n if (typeof config === \"string\") {\n deleteFile(config, fileSystem);\n } else {\n for (const filePath of Object.keys(config.files)) {\n deleteFile(filePath, fileSystem);\n }\n }\n}\n","import { z } from \"zod\";\nimport { extractFields, type ResolvedFieldMeta } from \"../core/schema-extractor.js\";\nimport { renderOptionsTableFromArray } from \"./default-renderers.js\";\n\n/**\n * Args shape type (Record of string keys to Zod schemas)\n * This matches the typical structure of `commonArgs`, `workspaceArgs`, etc.\n */\nexport type ArgsShape = Record<string, z.ZodType>;\n\n/**\n * Options for rendering args table\n */\nexport type ArgsTableOptions = {\n /** Columns to include in the table (default: all columns) */\n columns?: (\"option\" | \"alias\" | \"description\" | \"required\" | \"default\" | \"env\")[];\n};\n\n/**\n * Extract ResolvedFieldMeta array from ArgsShape\n *\n * This converts a raw args shape (like `commonArgs`) into the\n * ResolvedFieldMeta format used by politty's rendering functions.\n */\nfunction extractArgsFields(args: ArgsShape): ResolvedFieldMeta[] {\n // Wrap in z.object to use extractFields\n const schema = z.object(args);\n const extracted = extractFields(schema);\n return extracted.fields;\n}\n\n/**\n * Render args definition as a markdown options table\n *\n * This function takes raw args definitions (like `commonArgs`) and\n * renders them as a markdown table suitable for documentation.\n *\n * @example\n * import { renderArgsTable } from \"politty/docs\";\n * import { commonArgs, workspaceArgs } from \"./args\";\n *\n * const table = renderArgsTable({\n * ...commonArgs,\n * ...workspaceArgs,\n * });\n * // | Option | Alias | Description | Default |\n * // |--------|-------|-------------|---------|\n * // | `--env-file <ENV_FILE>` | `-e` | Path to environment file | - |\n * // ...\n *\n * @param args - Args shape (Record of string keys to Zod schemas with arg() metadata)\n * @param options - Rendering options\n * @returns Rendered markdown table string\n */\nexport function renderArgsTable(args: ArgsShape, options?: ArgsTableOptions): string {\n const fields = extractArgsFields(args);\n\n // Filter to non-positional args only (options)\n const optionFields = fields.filter((f) => !f.positional);\n\n if (optionFields.length === 0) {\n return \"\";\n }\n\n // Use existing renderOptionsTableFromArray for consistency\n // Note: column filtering is not yet supported by renderOptionsTableFromArray\n // If columns option is needed, we would need to implement custom rendering\n if (options?.columns) {\n return renderFilteredTable(optionFields, options.columns);\n }\n\n return renderOptionsTableFromArray(optionFields);\n}\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Format default value for display\n */\nfunction formatDefaultValue(value: unknown): string {\n if (value === undefined) {\n return \"-\";\n }\n return `\\`${JSON.stringify(value)}\\``;\n}\n\n/**\n * Render table with filtered columns\n */\nfunction renderFilteredTable(\n options: ResolvedFieldMeta[],\n columns: (\"option\" | \"alias\" | \"description\" | \"required\" | \"default\" | \"env\")[],\n): string {\n const lines: string[] = [];\n\n // Build header\n const headerCells: string[] = [];\n const separatorCells: string[] = [];\n\n for (const col of columns) {\n switch (col) {\n case \"option\":\n headerCells.push(\"Option\");\n separatorCells.push(\"------\");\n break;\n case \"alias\":\n headerCells.push(\"Alias\");\n separatorCells.push(\"-----\");\n break;\n case \"description\":\n headerCells.push(\"Description\");\n separatorCells.push(\"-----------\");\n break;\n case \"required\":\n headerCells.push(\"Required\");\n separatorCells.push(\"--------\");\n break;\n case \"default\":\n headerCells.push(\"Default\");\n separatorCells.push(\"-------\");\n break;\n case \"env\":\n headerCells.push(\"Env\");\n separatorCells.push(\"---\");\n break;\n }\n }\n\n lines.push(`| ${headerCells.join(\" | \")} |`);\n lines.push(`| ${separatorCells.join(\" | \")} |`);\n\n // Build rows\n for (const opt of options) {\n const cells: string[] = [];\n\n for (const col of columns) {\n switch (col) {\n case \"option\": {\n const placeholder = opt.placeholder ?? opt.cliName.toUpperCase().replace(/-/g, \"_\");\n const optionName =\n opt.type === \"boolean\"\n ? `\\`--${opt.cliName}\\``\n : `\\`--${opt.cliName} <${placeholder}>\\``;\n cells.push(optionName);\n break;\n }\n case \"alias\":\n cells.push(opt.alias ? `\\`-${opt.alias}\\`` : \"-\");\n break;\n case \"description\":\n cells.push(escapeTableCell(opt.description ?? \"\"));\n break;\n case \"required\":\n cells.push(opt.required ? \"Yes\" : \"No\");\n break;\n case \"default\":\n cells.push(formatDefaultValue(opt.defaultValue));\n break;\n case \"env\": {\n const envNames = opt.env\n ? Array.isArray(opt.env)\n ? opt.env.map((e) => `\\`${e}\\``).join(\", \")\n : `\\`${opt.env}\\``\n : \"-\";\n cells.push(envNames);\n break;\n }\n }\n }\n\n lines.push(`| ${cells.join(\" | \")} |`);\n }\n\n return lines.join(\"\\n\");\n}\n","import type { AnyCommand } from \"../types.js\";\nimport { collectAllCommands } from \"./doc-generator.js\";\nimport type { CommandInfo } from \"./types.js\";\n\n/**\n * Escape markdown special characters in table cells\n */\nfunction escapeTableCell(str: string): string {\n return str.replace(/\\|/g, \"\\\\|\").replace(/\\n/g, \" \");\n}\n\n/**\n * Generate anchor from command path\n */\nfunction generateAnchor(commandPath: string): string {\n return commandPath.replace(/\\s+/g, \"-\").toLowerCase();\n}\n\n/**\n * Configuration for a command category\n */\nexport type CommandCategory = {\n /** Category title (e.g., \"Application Commands\") */\n title: string;\n /** Category description */\n description: string;\n /** Command paths to include (parent commands will auto-expand to leaf commands) */\n commands: string[];\n /** Path to documentation file for links (e.g., \"./cli/application.md\") */\n docPath: string;\n};\n\n/**\n * Options for rendering command index\n */\nexport type CommandIndexOptions = {\n /** Base heading level (default: 3, which renders as ###) */\n headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;\n /** Only include leaf commands (commands without subcommands). Default: true */\n leafOnly?: boolean;\n};\n\n/**\n * Check if a command is a leaf (has no subcommands)\n */\nfunction isLeafCommand(info: CommandInfo): boolean {\n return info.subCommands.length === 0;\n}\n\n/**\n * Expand commands to include their subcommands\n * If a command has subcommands, recursively find all commands under it\n *\n * @param commandPaths - Command paths to expand\n * @param allCommands - Map of all available commands\n * @param leafOnly - If true, only include leaf commands; if false, include all commands\n */\nfunction expandCommands(\n commandPaths: string[],\n allCommands: Map<string, CommandInfo>,\n leafOnly: boolean,\n): string[] {\n const result: string[] = [];\n\n for (const cmdPath of commandPaths) {\n const info = allCommands.get(cmdPath);\n if (!info) continue;\n\n if (isLeafCommand(info)) {\n // Already a leaf command\n result.push(cmdPath);\n } else {\n // Find all commands under this parent\n for (const [path, pathInfo] of allCommands) {\n // Check if this is a subcommand of the current command\n const isSubcommand =\n cmdPath === \"\" ? path.length > 0 : path.startsWith(cmdPath + \" \") || path === cmdPath;\n\n if (isSubcommand) {\n // Include if it's a leaf command, or if we're including all commands\n if (isLeafCommand(pathInfo) || !leafOnly) {\n result.push(path);\n }\n }\n }\n }\n }\n\n return result;\n}\n\n/**\n * Render a single category section\n */\nfunction renderCategory(\n category: CommandCategory,\n allCommands: Map<string, CommandInfo>,\n headingLevel: number,\n leafOnly: boolean,\n): string {\n const h = \"#\".repeat(headingLevel);\n const lines: string[] = [];\n\n // Category title with link\n lines.push(`${h} [${category.title}](${category.docPath})`);\n lines.push(\"\");\n\n // Category description\n lines.push(category.description);\n lines.push(\"\");\n\n // Determine which commands to include (always expand, leafOnly controls filtering)\n const commandPaths = expandCommands(category.commands, allCommands, leafOnly);\n\n // Build command table\n lines.push(\"| Command | Description |\");\n lines.push(\"|---------|-------------|\");\n\n for (const cmdPath of commandPaths) {\n const info = allCommands.get(cmdPath);\n if (!info) continue;\n\n // Skip non-leaf commands if leafOnly is true\n if (leafOnly && !isLeafCommand(info)) continue;\n\n const displayName = cmdPath || info.name;\n const anchor = generateAnchor(displayName);\n const desc = escapeTableCell(info.description ?? \"\");\n\n lines.push(`| [${displayName}](${category.docPath}#${anchor}) | ${desc} |`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Render command index from categories\n *\n * Generates a category-based index of commands with links to documentation.\n *\n * @example\n * const categories: CommandCategory[] = [\n * {\n * title: \"Application Commands\",\n * description: \"Commands for managing applications.\",\n * commands: [\"init\", \"generate\", \"apply\"],\n * docPath: \"./cli/application.md\",\n * },\n * ];\n *\n * const index = await renderCommandIndex(mainCommand, categories);\n * // ### [Application Commands](./cli/application.md)\n * //\n * // Commands for managing applications.\n * //\n * // | Command | Description |\n * // |---------|-------------|\n * // | [init](./cli/application.md#init) | Initialize a project |\n * // ...\n *\n * @param command - Root command to extract command information from\n * @param categories - Category definitions for grouping commands\n * @param options - Rendering options\n * @returns Rendered markdown string\n */\nexport async function renderCommandIndex(\n command: AnyCommand,\n categories: CommandCategory[],\n options?: CommandIndexOptions,\n): Promise<string> {\n const headingLevel = options?.headingLevel ?? 3;\n const leafOnly = options?.leafOnly ?? true;\n\n // Collect all commands\n const allCommands = await collectAllCommands(command);\n\n // Render each category\n const sections: string[] = [];\n for (const category of categories) {\n const section = renderCategory(category, allCommands, headingLevel, leafOnly);\n sections.push(section);\n }\n\n return sections.join(\"\\n\\n\");\n}\n"],"mappings":"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"}
@@ -347,10 +347,10 @@ declare function renderArgumentsList(info: CommandInfo): string;
347
347
  * - Displays multiple env vars as comma-separated list
348
348
  *
349
349
  * @example
350
- * | Option | Alias | Description | Default | Env |
351
- * |--------|-------|-------------|---------|-----|
352
- * | `--dry-run` | `-d` | Dry run mode | `false` | - |
353
- * | `--port <PORT>` | - | Server port | - | `PORT`, `SERVER_PORT` |
350
+ * | Option | Alias | Description | Required | Default | Env |
351
+ * |--------|-------|-------------|----------|---------|-----|
352
+ * | `--dry-run` | `-d` | Dry run mode | No | `false` | - |
353
+ * | `--port <PORT>` | - | Server port | Yes | - | `PORT`, `SERVER_PORT` |
354
354
  */
355
355
  declare function renderOptionsTable(info: CommandInfo): string;
356
356
  /**
@@ -362,7 +362,7 @@ declare function renderOptionsTable(info: CommandInfo): string;
362
362
  *
363
363
  * @example
364
364
  * - `-d`, `--dry-run` - Dry run mode (default: false)
365
- * - `--port <PORT>` - Server port [env: PORT, SERVER_PORT]
365
+ * - `--port <PORT>` - Server port (required) [env: PORT, SERVER_PORT]
366
366
  */
367
367
  declare function renderOptionsList(info: CommandInfo): string;
368
368
  /**
@@ -502,7 +502,7 @@ type ArgsShape = Record<string, z.ZodType>;
502
502
  * Options for rendering args table
503
503
  */
504
504
  type ArgsTableOptions = {
505
- /** Columns to include in the table (default: all columns) */columns?: ("option" | "alias" | "description" | "default" | "env")[];
505
+ /** Columns to include in the table (default: all columns) */columns?: ("option" | "alias" | "description" | "required" | "default" | "env")[];
506
506
  };
507
507
  /**
508
508
  * Render args definition as a markdown options table