kiira
Version:
Command-line interface for Kiira: validate TypeScript and JavaScript code fences in your Markdown docs.
1 lines • 41.8 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":[],"sources":["../src/args.ts","../src/entries.ts","../src/fix.ts","../src/reporters.ts","../src/spinner.ts","../src/commands/check.ts","../src/commands/init.ts","../src/help.ts","../src/index.ts"],"sourcesContent":["export type ReporterName = \"pretty\" | \"json\" | \"github\"\n\ntype Command = \"check\" | \"init\" | \"help\" | \"version\"\n\ninterface ParsedArgs {\n\tcommand: Command\n\tfiles: string[]\n\tconfig?: string\n\treporter: ReporterName\n\tfix: boolean\n\tverbose: boolean\n\traw: boolean\n\t/** `--entry` values: directories/files/globs to check (repeatable). */\n\tentry: string[]\n\t/** `--ignore` values: directories/files/globs to exclude (repeatable). */\n\tignore: string[]\n\t/** `--static`: disable the loading spinner. */\n\tstatic: boolean\n}\n\nconst REPORTERS: ReporterName[] = [\"pretty\", \"json\", \"github\"]\nconst COMMANDS = new Set([\"check\", \"init\"])\n\nfunction isReporter(value: string): value is ReporterName {\n\treturn (REPORTERS as string[]).includes(value)\n}\n\n/** Parse `process.argv.slice(2)` into a structured command invocation. */\nexport function parseArgs(argv: string[]): ParsedArgs {\n\tlet command: Command | undefined\n\tlet config: string | undefined\n\tlet reporter: ReporterName = \"pretty\"\n\tlet fix = false\n\tlet verbose = false\n\tlet raw = false\n\tlet staticOutput = false\n\tconst files: string[] = []\n\tconst entry: string[] = []\n\tconst ignore: string[] = []\n\n\tconst base = (): Omit<ParsedArgs, \"command\"> => ({\n\t\tfiles,\n\t\tconfig,\n\t\treporter,\n\t\tfix,\n\t\tverbose,\n\t\traw,\n\t\tentry,\n\t\tignore,\n\t\tstatic: staticOutput,\n\t})\n\n\tfor (let i = 0; i < argv.length; i += 1) {\n\t\tconst arg = argv[i] ?? \"\"\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\treturn { command: \"help\", ...base() }\n\t\t}\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\treturn { command: \"version\", ...base() }\n\t\t}\n\n\t\tif (arg === \"--entry\" || arg.startsWith(\"--entry=\")) {\n\t\t\tconst value = arg.includes(\"=\") ? arg.slice(\"--entry=\".length) : (argv[++i] ?? \"\")\n\t\t\tif (value) {\n\t\t\t\tentry.push(value)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--ignore\" || arg.startsWith(\"--ignore=\")) {\n\t\t\tconst value = arg.includes(\"=\") ? arg.slice(\"--ignore=\".length) : (argv[++i] ?? \"\")\n\t\t\tif (value) {\n\t\t\t\tignore.push(value)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif (arg === \"--fix\") {\n\t\t\tfix = true\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--verbose\") {\n\t\t\tverbose = true\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--raw\") {\n\t\t\traw = true\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--static\") {\n\t\t\tstaticOutput = true\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--config\" || arg.startsWith(\"--config=\")) {\n\t\t\tconfig = arg.includes(\"=\") ? arg.slice(\"--config=\".length) : argv[++i]\n\t\t\tcontinue\n\t\t}\n\t\tif (arg === \"--reporter\" || arg.startsWith(\"--reporter=\")) {\n\t\t\tconst value = arg.includes(\"=\") ? arg.slice(\"--reporter=\".length) : (argv[++i] ?? \"\")\n\t\t\tif (!isReporter(value)) {\n\t\t\t\tthrow new Error(`Unknown reporter \"${value}\". Expected one of: ${REPORTERS.join(\", \")}.`)\n\t\t\t}\n\t\t\treporter = value\n\t\t\tcontinue\n\t\t}\n\t\tif (arg.startsWith(\"-\")) {\n\t\t\tthrow new Error(`Unknown option \"${arg}\".`)\n\t\t}\n\n\t\t// First non-flag token may be a command; subsequent ones are files.\n\t\tif (command === undefined && COMMANDS.has(arg)) {\n\t\t\tcommand = arg as Command\n\t\t} else {\n\t\t\tfiles.push(arg)\n\t\t}\n\t}\n\n\treturn { command: command ?? \"check\", ...base() }\n}\n","import { statSync } from \"node:fs\"\nimport { isAbsolute, join } from \"node:path\"\n\n// Characters that make a path a glob pattern (used verbatim, not expanded).\nconst GLOB_MAGIC = /[*?{}[\\]()!]/\n\nfunction toPosix(path: string): string {\n\treturn path.split(\"\\\\\").join(\"/\")\n}\n\nfunction isDirectory(cwd: string, path: string): boolean {\n\ttry {\n\t\treturn statSync(isAbsolute(path) ? path : join(cwd, path)).isDirectory()\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Turn `--entry` / positional arguments into include globs. A glob is used as-is;\n * a directory becomes `<dir>/**\\/*.{md,mdx}`; a file path is used as-is.\n */\nexport function toIncludeGlobs(cwd: string, entries: string[]): string[] {\n\treturn entries.map((entry) => {\n\t\tconst value = toPosix(entry)\n\t\tif (GLOB_MAGIC.test(value)) {\n\t\t\treturn value\n\t\t}\n\t\tif (isDirectory(cwd, entry)) {\n\t\t\treturn `${value.replace(/\\/+$/, \"\")}/**/*.{md,mdx}`\n\t\t}\n\t\treturn value\n\t})\n}\n\n/**\n * Turn `--ignore` arguments into exclude globs. A glob is used as-is; a file path\n * (with an extension) is used as-is; anything else is treated as a directory\n * subtree (`<dir>/**`), so `--ignore docs/api` excludes the whole directory.\n */\nexport function toIgnoreGlobs(cwd: string, ignores: string[]): string[] {\n\treturn ignores.map((entry) => {\n\t\tconst value = toPosix(entry)\n\t\tif (GLOB_MAGIC.test(value)) {\n\t\t\treturn value\n\t\t}\n\t\tif (!isDirectory(cwd, entry) && /\\.[a-z0-9]+$/i.test(value)) {\n\t\t\treturn value\n\t\t}\n\t\treturn `${value.replace(/\\/+$/, \"\")}/**`\n\t})\n}\n","import { readFile, writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\nimport type { KiiraConfigOverrideFix, KiiraDiagnostic, KiiraOverride } from \"kiira-core\"\n\n// Captures the opening of a fenced code block: the prefix (indent + fence\n// delimiter + spaces) and the language identifier that follows.\nconst FENCE_LANG = /^(\\s*(?:`{3,}|~{3,})\\s*)([A-Za-z0-9_-]+)/\n\ninterface FixSummary {\n\tfilesChanged: number\n\tfixesApplied: number\n}\n\ninterface LineEdit {\n\t/** Replace the fence language identifier (e.g. ts -> tsx). */\n\tlanguage?: string\n\t/** Append a metadata token to the fence info string (e.g. group=foo). */\n\tappend?: string\n}\n\nfunction applyLineEdit(line: string, edit: LineEdit): string {\n\tlet next = line\n\tif (edit.language) {\n\t\tnext = next.replace(FENCE_LANG, (_match, prefix: string) => `${prefix}${edit.language}`)\n\t}\n\tif (edit.append && !next.includes(edit.append)) {\n\t\tnext = `${next.replace(/\\s+$/, \"\")} ${edit.append}`\n\t}\n\treturn next\n}\n\n/**\n * Apply fence auto-fixes to the Markdown sources: rewrite a mistagged language\n * (`ts` -> `tsx`) and/or append metadata (`group=foo`) on the opening fence line.\n * Returns how many fences were edited across how many files.\n */\nexport async function applyFixes(cwd: string, diagnostics: KiiraDiagnostic[]): Promise<FixSummary> {\n\tconst byFile = new Map<string, Map<number, LineEdit>>()\n\tfor (const d of diagnostics) {\n\t\tconst fix = d.fix\n\t\t// Only the line-based fence fixes are applied to Markdown here.\n\t\tif (fix?.kind !== \"fence-language\" && fix?.kind !== \"fence-meta\") {\n\t\t\tcontinue\n\t\t}\n\t\tconst edits = byFile.get(d.markdownFile) ?? new Map<number, LineEdit>()\n\t\tconst edit = edits.get(fix.line) ?? {}\n\t\tif (fix.kind === \"fence-language\") {\n\t\t\tedit.language = fix.language\n\t\t} else {\n\t\t\tedit.append = fix.append\n\t\t}\n\t\tedits.set(fix.line, edit)\n\t\tbyFile.set(d.markdownFile, edits)\n\t}\n\n\tlet filesChanged = 0\n\tlet fixesApplied = 0\n\n\tfor (const [file, edits] of byFile) {\n\t\tconst lines = (await readFile(join(cwd, file), \"utf8\")).split(\"\\n\")\n\t\tlet changed = false\n\n\t\tfor (const [line, edit] of edits) {\n\t\t\tconst current = lines[line]\n\t\t\tif (current === undefined) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tconst replaced = applyLineEdit(current, edit)\n\t\t\tif (replaced !== current) {\n\t\t\t\tlines[line] = replaced\n\t\t\t\tchanged = true\n\t\t\t\tfixesApplied += 1\n\t\t\t}\n\t\t}\n\n\t\tif (changed) {\n\t\t\tawait writeFile(join(cwd, file), lines.join(\"\\n\"), \"utf8\")\n\t\t\tfilesChanged += 1\n\t\t}\n\t}\n\n\treturn { filesChanged, fixesApplied }\n}\n\ninterface ConfigOverrideResult {\n\t/** Override objects added to the config. */\n\tapplied: KiiraOverride[]\n\t/** Fixes that could not be applied automatically (no JSON config to edit). */\n\tmanual: KiiraConfigOverrideFix[]\n}\n\n/**\n * Apply `config-override` fixes by merging per-glob compiler-option overrides into\n * a JSON Kiira config. Non-JSON configs (or none) can't be safely edited, so\n * those fixes are returned as `manual` for the caller to surface.\n */\nexport async function applyConfigOverrides(\n\tconfigPath: string | null,\n\tdiagnostics: KiiraDiagnostic[]\n): Promise<ConfigOverrideResult> {\n\tconst fixes: KiiraConfigOverrideFix[] = []\n\tconst seen = new Set<string>()\n\tfor (const d of diagnostics) {\n\t\tif (d.fix?.kind !== \"config-override\") {\n\t\t\tcontinue\n\t\t}\n\t\tconst key = `${d.fix.include}\u0000${JSON.stringify(d.fix.compilerOptions)}`\n\t\tif (!seen.has(key)) {\n\t\t\tseen.add(key)\n\t\t\tfixes.push(d.fix)\n\t\t}\n\t}\n\tif (fixes.length === 0) {\n\t\treturn { applied: [], manual: [] }\n\t}\n\tif (!configPath || !configPath.toLowerCase().endsWith(\".json\")) {\n\t\treturn { applied: [], manual: fixes }\n\t}\n\n\tconst json = JSON.parse(await readFile(configPath, \"utf8\")) as { overrides?: unknown }\n\tif (json.overrides !== undefined && !Array.isArray(json.overrides)) {\n\t\tthrow new Error('Kiira config field \"overrides\" must be an array; cannot apply the fix automatically.')\n\t}\n\tconst overrides: KiiraOverride[] = Array.isArray(json.overrides) ? (json.overrides as KiiraOverride[]) : []\n\tconst applied: KiiraOverride[] = []\n\tfor (const fix of fixes) {\n\t\tconst exists = overrides.some((o) => {\n\t\t\tconst include = Array.isArray(o.include) ? o.include : [o.include]\n\t\t\treturn include.includes(fix.include)\n\t\t})\n\t\tif (exists) {\n\t\t\tcontinue\n\t\t}\n\t\tconst override: KiiraOverride = { include: [fix.include], ...fix.compilerOptions }\n\t\toverrides.push(override)\n\t\tapplied.push(override)\n\t}\n\tif (applied.length > 0) {\n\t\tjson.overrides = overrides\n\t\tawait writeFile(configPath, `${JSON.stringify(json, null, 2)}\\n`, \"utf8\")\n\t}\n\treturn { applied, manual: [] }\n}\n","import { Chalk, type ChalkInstance } from \"chalk\"\nimport type { KiiraCheckResult, KiiraDiagnostic } from \"kiira-core\"\nimport type { ReporterName } from \"./args\"\n\ninterface ReporterContext {\n\tcwd: string\n\t/** Return the lines of a Markdown file (for code frames), or undefined if unavailable. */\n\tgetSourceLines?: (markdownFile: string) => string[] | undefined\n\t/** When true, render full messages and code frames; otherwise one line per diagnostic. */\n\tverbose?: boolean\n\t/** When true, strip ANSI styling (same layout, no colors). */\n\traw?: boolean\n}\n\n// Default instance honors TTY auto-detection; `raw` forces styling off.\nconst styled = new Chalk()\nconst plain = new Chalk({ level: 0 })\n\nfunction severityColor(c: ChalkInstance, severity: KiiraDiagnostic[\"severity\"]): ChalkInstance[\"red\"] {\n\tif (severity === \"error\") {\n\t\treturn c.red\n\t}\n\tif (severity === \"warning\") {\n\t\treturn c.yellow\n\t}\n\treturn c.blue\n}\n\n/** Render a TS code (e.g. 2305) as `TS2305`; pass other codes through. */\nfunction codeLabel(code: KiiraDiagnostic[\"code\"]): string {\n\tif (typeof code === \"number\") {\n\t\treturn `TS${code}`\n\t}\n\treturn code ?? \"\"\n}\n\nfunction pluralize(count: number, noun: string): string {\n\treturn `${count} ${noun}${count === 1 ? \"\" : \"s\"}`\n}\n\n// --- JSON -----------------------------------------------------------------\n\n/** Number of diagnostics that `kiira check --fix` can resolve automatically. */\nfunction fixableCount(result: KiiraCheckResult): number {\n\treturn result.diagnostics.filter((d) => d.fix).length\n}\n\n/** Machine-readable report. Positions are 1-based for both line and character. */\nexport function formatJson(result: KiiraCheckResult): string {\n\tconst diagnostics = result.diagnostics.map((d) => ({\n\t\tseverity: d.severity,\n\t\tsource: d.source,\n\t\tcode: d.code,\n\t\tmessage: d.message,\n\t\tmarkdownFile: d.markdownFile,\n\t\tmarkdownRange: {\n\t\t\tstart: { line: d.markdownRange.start.line + 1, character: d.markdownRange.start.character + 1 },\n\t\t\tend: { line: d.markdownRange.end.line + 1, character: d.markdownRange.end.character + 1 },\n\t\t},\n\t\tgenerated: d.generated ?? false,\n\t}))\n\treturn JSON.stringify({ stats: { ...result.stats, fixable: fixableCount(result) }, diagnostics }, null, 2)\n}\n\n// --- GitHub ---------------------------------------------------------------\n\nfunction githubSeverity(severity: KiiraDiagnostic[\"severity\"]): \"error\" | \"warning\" | \"notice\" {\n\tif (severity === \"error\") {\n\t\treturn \"error\"\n\t}\n\tif (severity === \"warning\") {\n\t\treturn \"warning\"\n\t}\n\treturn \"notice\"\n}\n\nfunction escapeGithubData(value: string): string {\n\treturn value.replace(/%/g, \"%25\").replace(/\\r/g, \"%0D\").replace(/\\n/g, \"%0A\")\n}\n\n/** GitHub Actions workflow command annotations (1-based line/col). */\nexport function formatGithub(result: KiiraCheckResult): string {\n\treturn result.diagnostics\n\t\t.map((d) => {\n\t\t\tconst line = d.markdownRange.start.line + 1\n\t\t\tconst col = d.markdownRange.start.character + 1\n\t\t\tconst title = codeLabel(d.code)\n\t\t\tconst titlePart = title ? `,title=${title}` : \"\"\n\t\t\treturn `::${githubSeverity(d.severity)} file=${d.markdownFile},line=${line},col=${col}${titlePart}::${escapeGithubData(d.message)}`\n\t\t})\n\t\t.join(\"\\n\")\n}\n\n// --- Pretty ---------------------------------------------------------------\n\nfunction renderCodeFrame(lines: string[], diagnostic: KiiraDiagnostic, c: ChalkInstance): string {\n\tconst lineIndex = diagnostic.markdownRange.start.line\n\tconst source = lines[lineIndex]\n\tif (source === undefined) {\n\t\treturn \"\"\n\t}\n\tconst gutter = String(lineIndex + 1)\n\tconst startCol = diagnostic.markdownRange.start.character\n\tconst sameLine = diagnostic.markdownRange.end.line === lineIndex\n\tconst endCol = sameLine ? Math.max(diagnostic.markdownRange.end.character, startCol + 1) : source.length\n\tconst caretPad = \" \".repeat(gutter.length)\n\tconst underline = `${\" \".repeat(startCol)}${\"^\".repeat(Math.max(1, endCol - startCol))}`\n\treturn [\n\t\t` ${c.dim(`${gutter} |`)} ${source}`,\n\t\t` ${c.dim(`${caretPad} |`)} ${severityColor(c, diagnostic.severity)(underline)}`,\n\t].join(\"\\n\")\n}\n\nfunction location(d: KiiraDiagnostic, c: ChalkInstance): string {\n\treturn c.cyan(`${d.markdownFile}:${d.markdownRange.start.line + 1}:${d.markdownRange.start.character + 1}`)\n}\n\n/** One compact line per diagnostic: `file:line:col severity CODE message`. */\nfunction compactLine(d: KiiraDiagnostic, c: ChalkInstance): string {\n\tconst severity = severityColor(c, d.severity)(d.severity)\n\tconst code = codeLabel(d.code)\n\tconst codePart = code ? `${c.dim(code)} ` : \"\"\n\treturn `${location(d, c)} ${severity} ${codePart}${d.message.split(\"\\n\")[0]}`\n}\n\n/** A verbose block: header, full message, and a code frame. */\nfunction verboseBlock(d: KiiraDiagnostic, ctx: ReporterContext, c: ChalkInstance): string {\n\tconst code = codeLabel(d.code)\n\tconst header = `${location(d, c)} ${severityColor(c, d.severity)(d.severity)}${code ? ` ${c.dim(code)}` : \"\"}`\n\tconst frameLines = ctx.getSourceLines?.(d.markdownFile)\n\tconst frame = frameLines ? renderCodeFrame(frameLines, d, c) : \"\"\n\treturn [header, d.message, frame].filter(Boolean).join(\"\\n\")\n}\n\nexport function formatPretty(result: KiiraCheckResult, ctx: ReporterContext): string {\n\tconst { stats } = result\n\tconst c = ctx.raw ? plain : styled\n\tconst sections: string[] = []\n\n\tif (ctx.verbose) {\n\t\tsections.push(...result.diagnostics.map((d) => verboseBlock(d, ctx, c)))\n\t} else {\n\t\t// Group compact lines under a per-file header.\n\t\tconst byFile = new Map<string, KiiraDiagnostic[]>()\n\t\tfor (const d of result.diagnostics) {\n\t\t\tconst list = byFile.get(d.markdownFile) ?? []\n\t\t\tlist.push(d)\n\t\t\tbyFile.set(d.markdownFile, list)\n\t\t}\n\t\tfor (const [file, diags] of byFile) {\n\t\t\tsections.push([c.underline(file), ...diags.map((d) => ` ${compactLine(d, c)}`)].join(\"\\n\"))\n\t\t}\n\t}\n\n\t// Count failed *snippets* (a single snippet can emit several errors), not\n\t// raw error messages, so \"Passed\" never goes negative.\n\tconst failedSnippets = new Set(\n\t\tresult.diagnostics\n\t\t\t.filter((d) => d.severity === \"error\")\n\t\t\t.map((d) => d.virtualFile ?? `${d.markdownFile}:${d.markdownRange.start.line}`)\n\t).size\n\tconst passedSnippets = Math.max(0, stats.checked - failedSnippets)\n\n\tconst summary: string[] = []\n\tif (stats.errors === 0 && stats.warnings === 0) {\n\t\tsummary.push(c.green(`✓ Kiira found no errors in ${pluralize(stats.markdownFiles, \"file\")}.`))\n\t} else {\n\t\tconst parts = [c.red(pluralize(stats.errors, \"error\"))]\n\t\tif (stats.warnings > 0) {\n\t\t\tparts.push(c.yellow(pluralize(stats.warnings, \"warning\")))\n\t\t}\n\t\tsummary.push(`${c.red(\"✖\")} Kiira found ${parts.join(\" and \")} in ${pluralize(stats.markdownFiles, \"file\")}.`)\n\t}\n\tsummary.push(\n\t\tc.dim(\n\t\t\t`Checked ${pluralize(stats.checked, \"snippet\")}. Passed ${passedSnippets}. Failed ${failedSnippets}. Ignored ${stats.ignored}.`\n\t\t)\n\t)\n\tconst fixable = fixableCount(result)\n\tif (fixable > 0) {\n\t\tsummary.push(c.cyan(`${pluralize(fixable, \"issue\")} fixable with \\`kiira check --fix\\`.`))\n\t}\n\n\tconst body = sections.join(ctx.verbose ? \"\\n\\n\" : \"\\n\")\n\tconst parts = body.length > 0 ? [body, \"\", summary.join(\"\\n\")] : [summary.join(\"\\n\")]\n\treturn parts.join(\"\\n\")\n}\n\n// --- Dispatch -------------------------------------------------------------\n\nexport function formatReport(reporter: ReporterName, result: KiiraCheckResult, ctx: ReporterContext): string {\n\tswitch (reporter) {\n\t\tcase \"json\":\n\t\t\treturn formatJson(result)\n\t\tcase \"github\":\n\t\t\treturn formatGithub(result)\n\t\tdefault:\n\t\t\treturn formatPretty(result, ctx)\n\t}\n}\n","const FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"]\n\n// ESC built at runtime to keep the source free of raw control characters.\nconst ESC = String.fromCharCode(27)\nconst HIDE_CURSOR = `${ESC}[?25l`\nconst SHOW_CURSOR = `${ESC}[?25h`\nconst CLEAR_LINE = `\\r${ESC}[K`\n\ninterface Spinner {\n\tstop(): void\n}\n\ninterface SpinnerStream {\n\tisTTY?: boolean\n\twrite(chunk: string): unknown\n}\n\ninterface SpinnerOptions {\n\tenabled: boolean\n\t/** Defaults to process.stderr, so the spinner never pollutes stdout (reports/JSON). */\n\tstream?: SpinnerStream\n}\n\n/**\n * Start a braille spinner on stderr while async work runs. A no-op when disabled\n * (`--static`) or when the stream is not a TTY (pipes, CI) so output stays clean.\n */\nexport function startSpinner(text: string, options: SpinnerOptions): Spinner {\n\tconst stream = options.stream ?? process.stderr\n\tif (!options.enabled || !stream.isTTY) {\n\t\treturn { stop() {} }\n\t}\n\n\tlet frame = 0\n\tconst render = (): void => {\n\t\tstream.write(`\\r${FRAMES[frame]} ${text}`)\n\t}\n\tstream.write(HIDE_CURSOR)\n\trender()\n\tconst timer = setInterval(() => {\n\t\tframe = (frame + 1) % FRAMES.length\n\t\trender()\n\t}, 80)\n\n\treturn {\n\t\tstop() {\n\t\t\tclearInterval(timer)\n\t\t\tstream.write(`${CLEAR_LINE}${SHOW_CURSOR}`)\n\t\t},\n\t}\n}\n","import { readFileSync } from \"node:fs\"\nimport { isAbsolute, join, resolve } from \"node:path\"\nimport {\n\ttype KiiraConfig,\n\tcheckMarkdownFiles,\n\tcollectExternalPackages,\n\tensureExternalPackages,\n\tfindConfigFile,\n\tloadConfig,\n\tloadConfigFile,\n} from \"kiira-core\"\nimport type { ReporterName } from \"../args\"\nimport { toIgnoreGlobs, toIncludeGlobs } from \"../entries\"\nimport { applyConfigOverrides, applyFixes } from \"../fix\"\nimport { formatReport } from \"../reporters\"\nimport { startSpinner } from \"../spinner\"\n\ninterface RunCheckOptions {\n\tcwd: string\n\tfiles: string[]\n\tentry?: string[]\n\tignore?: string[]\n\tconfig?: string\n\treporter: ReporterName\n\tfix?: boolean\n\tverbose?: boolean\n\traw?: boolean\n\tstatic?: boolean\n\tlog: (message: string) => void\n\terror: (message: string) => void\n}\n\nfunction createSourceLineReader(cwd: string): (markdownFile: string) => string[] | undefined {\n\tconst cache = new Map<string, string[] | undefined>()\n\treturn (markdownFile) => {\n\t\tif (cache.has(markdownFile)) {\n\t\t\treturn cache.get(markdownFile)\n\t\t}\n\t\tlet lines: string[] | undefined\n\t\ttry {\n\t\t\tlines = readFileSync(join(cwd, markdownFile), \"utf8\").split(/\\r?\\n/)\n\t\t} catch {\n\t\t\tlines = undefined\n\t\t}\n\t\tcache.set(markdownFile, lines)\n\t\treturn lines\n\t}\n}\n\n/**\n * Run `kiira check`. Returns the process exit code: 0 when clean, 1 when there\n * are validation errors. Configuration/runtime failures throw (the caller maps\n * those to exit code 2).\n */\nexport async function runCheck(options: RunCheckOptions): Promise<number> {\n\tconst { cwd } = options\n\n\tconst loaded: KiiraConfig = options.config\n\t\t? await loadConfigFile(isAbsolute(options.config) ? options.config : resolve(cwd, options.config))\n\t\t: await loadConfig(cwd)\n\n\t// Positional args and `--entry` are the directories/files/globs to check; they\n\t// override the config's `include`. `--ignore` adds to the config's `exclude`.\n\tconst entries = [...options.files, ...(options.entry ?? [])]\n\tconst include = entries.length > 0 ? toIncludeGlobs(cwd, entries) : loaded.include\n\tconst exclude = [...(loaded.exclude ?? []), ...toIgnoreGlobs(cwd, options.ignore ?? [])]\n\tconst config: KiiraConfig = { ...loaded, include, exclude }\n\n\t// Install any declared doc-only packages into the isolated cache so their\n\t// imports resolve during the check. Idempotent: a no-op when already current.\n\tconst externalPackages = collectExternalPackages(config)\n\tif (Object.keys(externalPackages).length > 0) {\n\t\tawait ensureExternalPackages(cwd, externalPackages, {\n\t\t\twarn: options.error,\n\t\t\tlog: options.verbose ? options.log : undefined,\n\t\t})\n\t}\n\n\t// Run the (slow) checking under a spinner, deferring all output until it stops\n\t// so the spinner line and the report never interleave.\n\tconst spinner = startSpinner(\"Checking Markdown…\", { enabled: !options.static })\n\tconst pending: string[] = []\n\tlet result: Awaited<ReturnType<typeof checkMarkdownFiles>>\n\ttry {\n\t\tresult = await checkMarkdownFiles({ cwd, config })\n\n\t\t// `--fix`: rewrite mistagged fences / add config overrides, then re-check so\n\t\t// the report reflects the corrected sources.\n\t\tif (options.fix) {\n\t\t\tconst configPath = options.config\n\t\t\t\t? isAbsolute(options.config)\n\t\t\t\t\t? options.config\n\t\t\t\t\t: resolve(cwd, options.config)\n\t\t\t\t: findConfigFile(cwd)\n\n\t\t\tconst fences = await applyFixes(cwd, result.diagnostics)\n\t\t\tconst overrides = await applyConfigOverrides(configPath, result.diagnostics)\n\n\t\t\tif (fences.fixesApplied > 0 || overrides.applied.length > 0) {\n\t\t\t\tconst parts: string[] = []\n\t\t\t\tif (fences.fixesApplied > 0) {\n\t\t\t\t\tparts.push(`${fences.fixesApplied} fence${fences.fixesApplied === 1 ? \"\" : \"s\"}`)\n\t\t\t\t}\n\t\t\t\tif (overrides.applied.length > 0) {\n\t\t\t\t\tparts.push(`${overrides.applied.length} config override${overrides.applied.length === 1 ? \"\" : \"s\"}`)\n\t\t\t\t}\n\t\t\t\tpending.push(`Fixed ${parts.join(\" and \")}.\\n`)\n\t\t\t\tconfig.overrides = [...(config.overrides ?? []), ...overrides.applied]\n\t\t\t\tresult = await checkMarkdownFiles({ cwd, config })\n\t\t\t}\n\n\t\t\tif (overrides.manual.length > 0) {\n\t\t\t\tpending.push(\"Add these overrides to your Kiira config (config is not JSON, so apply manually):\")\n\t\t\t\tfor (const fix of overrides.manual) {\n\t\t\t\t\tconst opts = Object.entries(fix.compilerOptions)\n\t\t\t\t\t\t.map(([k, v]) => `\"${k}\": \"${v}\"`)\n\t\t\t\t\t\t.join(\", \")\n\t\t\t\t\tpending.push(` { \"include\": [\"${fix.include}\"], ${opts} }`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tspinner.stop()\n\t}\n\n\tfor (const message of pending) {\n\t\toptions.log(message)\n\t}\n\n\tconst output = formatReport(options.reporter, result, {\n\t\tcwd,\n\t\tgetSourceLines: createSourceLineReader(cwd),\n\t\tverbose: options.verbose,\n\t\traw: options.raw,\n\t})\n\tif (output.length > 0) {\n\t\toptions.log(output)\n\t}\n\n\treturn result.stats.errors > 0 ? 1 : 0\n}\n","import { existsSync } from \"node:fs\"\nimport { writeFile } from \"node:fs/promises\"\nimport { join } from \"node:path\"\n\nconst CONFIG_TEMPLATE = `import { defineConfig } from \"kiira-core\"\n\nexport default defineConfig({\n\\tinclude: [\"docs/**/*.{md,mdx}\", \"README.md\"],\n\\ttsconfig: \"tsconfig.docs.json\",\n\\tdefaultValidate: \"type\",\n\\tlanguages: [\"ts\", \"tsx\", \"js\", \"jsx\"],\n\\tfixtures: {\n\\t\\tnode: { type: \"prepend\", content: \"export {}\" },\n\\t\\treact: { type: \"prepend\", content: 'import * as React from \"react\"' },\n\\t},\n})\n`\n\nconst TSCONFIG_TEMPLATE = `${JSON.stringify(\n\t{\n\t\textends: \"./tsconfig.json\",\n\t\tcompilerOptions: {\n\t\t\ttarget: \"ES2022\",\n\t\t\tmodule: \"ESNext\",\n\t\t\tmoduleResolution: \"Bundler\",\n\t\t\tjsx: \"react-jsx\",\n\t\t\tstrict: true,\n\t\t\tnoEmit: true,\n\t\t\tallowJs: true,\n\t\t\tcheckJs: true,\n\t\t\tskipLibCheck: true,\n\t\t\ttypes: [\"node\"],\n\t\t},\n\t},\n\tnull,\n\t2\n)}\\n`\n\ninterface RunInitOptions {\n\tcwd: string\n\tlog: (message: string) => void\n}\n\nasync function writeIfMissing(path: string, content: string, name: string, log: (m: string) => void): Promise<void> {\n\tif (existsSync(path)) {\n\t\tlog(`• ${name} already exists, skipping.`)\n\t\treturn\n\t}\n\tawait writeFile(path, content, \"utf8\")\n\tlog(`✓ Created ${name}.`)\n}\n\n/** Scaffold a Kiira config and a docs tsconfig. Existing files are left untouched. */\nexport async function runInit(options: RunInitOptions): Promise<number> {\n\tawait writeIfMissing(join(options.cwd, \"kiira.config.ts\"), CONFIG_TEMPLATE, \"kiira.config.ts\", options.log)\n\tawait writeIfMissing(join(options.cwd, \"tsconfig.docs.json\"), TSCONFIG_TEMPLATE, \"tsconfig.docs.json\", options.log)\n\toptions.log(\"\\nDone. Run `kiira check` to validate your Markdown.\")\n\treturn 0\n}\n","export const VERSION = \"0.1.0\"\n\nexport const HELP_TEXT = `kiira — type-check the code in your Markdown\n\nUsage:\n kiira [check] [files...] [options]\n kiira init\n\nCommands:\n check Validate Markdown code fences (default).\n init Scaffold kiira.config.ts and tsconfig.docs.json.\n\nOptions:\n --entry <path> Directory, file, or glob to check (repeatable).\n --ignore <path> Directory, file, or glob to exclude (repeatable).\n --config <path> Path to a Kiira config file.\n --reporter <name> Output format: pretty (default), json, or github.\n --fix Rewrite mistagged code fences (e.g. ts -> tsx for JSX).\n --verbose Show full error messages and code frames.\n --raw Disable colored output (plain text).\n --static Disable the loading spinner.\n -h, --help Show this help.\n -v, --version Show the version.\n\nExamples:\n kiira check\n kiira check --entry docs --entry README.md\n kiira check --entry docs --ignore docs/api\n kiira check --reporter github\n kiira check --config kiira.config.ts --reporter json\n`\n","#!/usr/bin/env node\nimport { parseArgs } from \"./args\"\nimport { runCheck } from \"./commands/check\"\nimport { runInit } from \"./commands/init\"\nimport { HELP_TEXT, VERSION } from \"./help\"\n\nasync function main(argv: string[]): Promise<number> {\n\tlet parsed: ReturnType<typeof parseArgs>\n\ttry {\n\t\tparsed = parseArgs(argv)\n\t} catch (error) {\n\t\tconsole.error((error as Error).message)\n\t\treturn 2\n\t}\n\n\tswitch (parsed.command) {\n\t\tcase \"help\":\n\t\t\tconsole.log(HELP_TEXT)\n\t\t\treturn 0\n\t\tcase \"version\":\n\t\t\tconsole.log(VERSION)\n\t\t\treturn 0\n\t\tcase \"init\":\n\t\t\treturn runInit({ cwd: process.cwd(), log: (m) => console.log(m) })\n\t\tdefault:\n\t\t\treturn runCheck({\n\t\t\t\tcwd: process.cwd(),\n\t\t\t\tfiles: parsed.files,\n\t\t\t\tentry: parsed.entry,\n\t\t\t\tignore: parsed.ignore,\n\t\t\t\tconfig: parsed.config,\n\t\t\t\treporter: parsed.reporter,\n\t\t\t\tfix: parsed.fix,\n\t\t\t\tverbose: parsed.verbose,\n\t\t\t\traw: parsed.raw,\n\t\t\t\tstatic: parsed.static,\n\t\t\t\tlog: (m) => console.log(m),\n\t\t\t\terror: (m) => console.error(m),\n\t\t\t})\n\t}\n}\n\nmain(process.argv.slice(2))\n\t.then((code) => {\n\t\tprocess.exitCode = code\n\t})\n\t.catch((error) => {\n\t\t// Configuration or runtime failure.\n\t\tconsole.error(`kiira: ${(error as Error).message}`)\n\t\tprocess.exitCode = 2\n\t})\n"],"mappings":"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"}