/** * Counts words in markdown content, excluding fenced code blocks and inline code spans. * * The word-count rule is deliberately simple and deterministic: fenced code blocks (lines opening * with three or more backticks or tildes, up to the matching closing fence) and inline code spans * (backtick-delimited runs) are removed first, then the remaining text is split on whitespace and * every non-empty token counts as one word. Link syntax, headings markers, and punctuation all * count as part of their surrounding tokens. * * @category Commands * * @param content - Raw markdown file content * * @returns Number of whitespace-separated tokens outside code spans and fences */ export declare function countWords(content: string): number; /** * Per-file measurements gathered while scanning a markdown tree. * * A scanned file carries everything the tree renderer and the statistics builder need, so both stay * pure functions over this shape. * * @category Commands */ export interface ScannedMarkdownFile { /** Absolute file path */ path: string; /** Path relative to the scan root, with forward slashes regardless of platform */ relativePath: string; /** Word count outside code spans and fences (see countWords) */ wordCount: number; /** Total number of parsed links of every type */ linkCount: number; /** Number of parsed links whose type is internal */ internalLinkCount: number; /** Number of parsed links whose type is external */ externalLinkCount: number; /** Number of internal links whose target file does not exist */ brokenInternalLinkCount: number; /** Number of links from other scanned files that resolve to this file */ inboundLinkCount: number; } /** * Aggregate documentation statistics for a scanned markdown tree. * * Field order is the serialisation order used by the JSON output and is kept stable so machine * consumers see identical key ordering across runs. * * @category Commands */ export interface TreeStatistics { /** Total number of markdown files scanned */ totalFiles: number; /** Sum of per-file word counts */ totalWords: number; /** Total number of internal (file-to-file) links */ totalInternalLinks: number; /** Total number of external HTTP/HTTPS links */ totalExternalLinks: number; /** Internal links whose target file does not exist */ brokenInternalLinks: number; /** Files no other scanned file links to */ orphanedFiles: number; } /** * Aggregates per-file measurements into tree statistics. * * A file counts as orphaned when no other scanned file holds a link resolving to it * (inboundLinkCount === 0), so single-file scans report one orphan. * * @category Commands * * @param files - Scanned file measurements for the full scan * * @returns Aggregate statistics with a stable field order */ export declare function computeTreeStatistics(files: ScannedMarkdownFile[]): TreeStatistics; /** * A markdown file leaf in the rendered tree. * * Field order is the serialisation order used by the JSON output and is kept stable. * * @category Commands */ export interface TreeFileNode { /** File name including extension */ name: string; /** Path relative to the scan root, with forward slashes */ path: string; /** Word count outside code spans and fences */ wordCount: number; /** Total number of parsed links of every type */ linkCount: number; /** Internal links whose target file does not exist */ brokenInternalLinkCount: number; /** Whether no other scanned file links to this file */ orphaned: boolean; } /** * A directory node in the rendered tree. * * Directories always sort before files, each group alphabetically by codepoint order so the * rendering is deterministic across machines and locales. * * @category Commands */ export interface TreeDirectoryNode { /** Directory name; empty string for the scan root */ name: string; /** Path relative to the scan root, with forward slashes; empty string for the root */ path: string; /** Child directories, sorted alphabetically */ directories: TreeDirectoryNode[]; /** Markdown files directly inside this directory, sorted alphabetically */ files: TreeFileNode[]; /** Whether max-depth cut off this directory's children from the rendering */ truncated: boolean; } /** * Groups scanned markdown files into a nested directory tree. * * Files under node_modules, .git, or dist directories are excluded at any depth. Directories sort * before files and each group sorts alphabetically. When maxDepth is given, entries deeper than the * limit are cut from the rendering (the affected directory is flagged truncated); statistics * computed from the scanned files are unaffected because they never read this tree. * * @category Commands * * @param files - Scanned file measurements for the full scan * @param maxDepth - Maximum rendering depth, where the root is depth 0 and its children depth 1 * * @returns The root directory node; its name and path are empty strings * * @throws Error if a scanned file carries an empty relative path */ export declare function buildFileTree(files: ScannedMarkdownFile[], maxDepth?: number): TreeDirectoryNode; /** * Renders a tree node as an ASCII directory listing with box-drawing characters. * * Directory entries end with a slash; files carry a "(N words, M links)" annotation plus a "[N * broken]" marker for files with broken internal links and an "[orphan]" marker for files no other * scanned file links to. Directories cut off by max-depth render as "name/ ...". * * @category Commands * * @param root - Tree node to render, as produced by buildFileTree * @param rootLabel - Label printed on the first line for the scan root * * @returns The full rendering, one entry per line, without a trailing newline */ export declare function renderTreeAscii(root: TreeDirectoryNode, rootLabel: string): string; /** Options controlling scanner progress output */ export interface ScanOptions { /** Print each directory walked and each file parsed */ verbose?: boolean; } /** * Scans a directory (or a single markdown file) and measures every markdown file found. * * Files are parsed with LinkParser and internal links are checked with LinkValidator in * file-existence mode only, so no network access happens. The inbound link count is derived across * the whole parsed set: every link whose resolved path names another scanned file increments that * file's inbound count, and a file with zero inbound links is an orphan. * * @category Commands * * @param targetPath - Directory to scan recursively, or a single markdown file * @param options - Scan options * * @returns Scanned file measurements ordered by relative path, excluding skipped directories * * @throws Error if the target path does not exist or a file cannot be read or parsed */ export declare function scanMarkdownTree(targetPath: string, options?: ScanOptions): Promise; /** Output formats supported by the tree command */ export type TreeFormat = "ascii" | "json"; /** * CLI-specific options for the tree command. * * @category Commands */ export interface TreeCliOptions { /** Output format: ascii or json */ format?: string; /** Maximum tree rendering depth; statistics always cover the full scan */ maxDepth?: number; /** Show detailed output with processing information */ verbose?: boolean; /** Output results in JSON format (alias for --format json) */ json?: boolean; } /** * CLI command handler that renders the markdown tree under a path with documentation statistics. * * The scan is read-only, so there is no dry-run mode. Rendering is deterministic: directories * before files, each group alphabetically, node_modules/.git/dist excluded. Word counts follow the * countWords rule: whitespace-separated tokens outside fenced code blocks and inline code spans. * Internal links are checked for file existence only (no network). * * @category Commands * * @example * - markmv tree * - markmv tree docs/ --max-depth 2 * - markmv tree docs/ --format json * * @param targetPath - Directory or markdown file to scan (defaults to the current directory) * @param options - CLI options */ export declare function treeCommand(targetPath: string | undefined, options: TreeCliOptions): Promise; //# sourceMappingURL=tree.d.ts.map