@entro314labs/starlight-document-converter
Version:
A comprehensive document converter for Astro Starlight that transforms various document formats into Starlight-compatible Markdown with proper frontmatter
175 lines (174 loc) • 6.54 kB
JavaScript
import {
boxes,
createResultsTable,
status
} from "./chunk-RI3FHBT3.js";
// src/utils/cli-commands.ts
import { readdir, readFile, writeFile } from "fs/promises";
import { dirname, join } from "path";
import { spinner } from "@clack/prompts";
import pc from "picocolors";
async function repairSingleFile(filePath, options) {
const { FrontmatterRepair } = await import("./frontmatter-repair-JNEPELNZ.js");
const { LinkImageProcessor } = await import("./link-image-processor-5LK3OBO7.js");
const { TocGenerator } = await import("./toc-generator-XJPRHRCH.js");
const repairer = new FrontmatterRepair();
const linkProcessor = new LinkImageProcessor(
dirname(filePath),
options.output || dirname(filePath)
);
const tocGenerator = new TocGenerator();
const content = await readFile(filePath, "utf-8");
const repairResult = repairer.repairFrontmatter(content, filePath);
let processedContent = repairResult.repairedContent;
let wasRepaired = repairResult.fixed;
const issues = [...repairResult.issues];
if (options.fixLinks || options.processImages) {
const { content: linkProcessedContent } = await linkProcessor.processContent(
processedContent,
filePath,
filePath
);
if (linkProcessedContent !== processedContent) {
processedContent = linkProcessedContent;
wasRepaired = true;
issues.push("Processed links and images");
}
}
if (options.generateToc && !tocGenerator.hasExistingToc(processedContent)) {
const tocContent = tocGenerator.insertTocIntoContent(processedContent);
if (tocContent !== processedContent) {
processedContent = tocContent;
wasRepaired = true;
issues.push("Added table of contents");
}
}
if (!options.dryRun && processedContent !== content) {
await writeFile(filePath, processedContent, "utf-8");
}
return { repaired: wasRepaired, issues };
}
async function repairDirectory(inputPath, options) {
const files = await readdir(inputPath, { recursive: true });
let totalRepaired = 0;
let totalIssues = 0;
let filesProcessed = 0;
for (const file of files) {
if (typeof file === "string" && (file.endsWith(".md") || file.endsWith(".mdx"))) {
const filePath = join(inputPath, file);
try {
const result = await repairSingleFile(filePath, options);
if (result.repaired) {
totalRepaired++;
totalIssues += result.issues.length;
if (options.verbose) {
console.log(`
${pc.cyan(file)}:`);
result.issues.forEach((issue) => console.log(` \u2022 ${issue}`));
}
}
filesProcessed++;
} catch (error) {
console.warn(`Failed to process ${file}:`, error);
}
}
}
return { totalRepaired, totalIssues, filesProcessed };
}
async function validateSingleFile(filePath, options) {
const { FrontmatterRepair } = await import("./frontmatter-repair-JNEPELNZ.js");
const validator = new FrontmatterRepair();
const content = await readFile(filePath, "utf-8");
const validation = validator.validateContent(content, filePath);
return { valid: validation.valid, validation };
}
async function validateDirectory(inputPath, options) {
const files = await readdir(inputPath, { recursive: true });
let totalFiles = 0;
let validFiles = 0;
let issueCount = 0;
const allIssues = [];
for (const file of files) {
if (typeof file === "string" && (file.endsWith(".md") || file.endsWith(".mdx"))) {
const filePath = join(inputPath, file);
try {
const result = await validateSingleFile(filePath, options);
totalFiles++;
if (result.valid) {
validFiles++;
} else {
issueCount += result.validation.issues.filter((i) => i.type === "error").length;
allIssues.push({ file, validation: result.validation });
}
if (options.showDetails || !result.valid) {
console.log(
`
${pc.cyan(file)}: ${result.valid ? pc.green("\u2705 Valid") : pc.red("\u274C Issues")}`
);
if (result.validation.score) {
const scoreColor = result.validation.score.overall === "good" ? pc.green : result.validation.score.overall === "fair" ? pc.yellow : pc.red;
console.log(` Quality: ${scoreColor(result.validation.score.overall.toUpperCase())}`);
}
if (!result.valid && options.verbose) {
result.validation.issues.forEach((issue) => {
const icon = issue.type === "error" ? "\u274C" : issue.type === "warning" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
console.log(` ${icon} ${issue.message}`);
});
}
}
} catch (error) {
console.warn(`Failed to validate ${file}:`, error);
}
}
}
return { totalFiles, validFiles, issueCount, allIssues };
}
function showRepairResults(stats, options) {
const table = createResultsTable({
filesProcessed: stats.filesProcessed,
totalRepaired: stats.totalRepaired,
totalIssues: stats.totalIssues
});
const title = options.dryRun ? "Repair Analysis (Dry Run)" : "Repair Results";
const isDryRun = options.dryRun;
const header = isDryRun ? boxes.warning(
`${status.info("Analysis completed without making changes")}
${table.toString()}`,
title
) : boxes.success(`${status.success("Files successfully repaired")}
${table.toString()}`, title);
return header;
}
function showValidationResults(stats) {
const successRate = stats.totalFiles > 0 ? Math.round(stats.validFiles / stats.totalFiles * 100) : 100;
const table = createResultsTable({
totalFiles: stats.totalFiles,
validFiles: stats.validFiles,
issueCount: stats.issueCount
});
const title = "Validation Results";
const header = successRate >= 90 ? boxes.success(`${status.success("Excellent content quality!")}
${table.toString()}`, title) : successRate >= 70 ? boxes.warning(`${status.warning("Some issues found")}
${table.toString()}`, title) : boxes.error(
`${status.error("Multiple issues need attention")}
${table.toString()}`,
title
);
return header;
}
function createSpinner(message, dryRun = false) {
const s = spinner();
const styledMessage = dryRun ? status.warning(`Analyzing: ${message}`) : status.processing(message);
s.start(styledMessage);
return s;
}
export {
createSpinner,
repairDirectory,
repairSingleFile,
showRepairResults,
showValidationResults,
validateDirectory,
validateSingleFile
};
//# sourceMappingURL=cli-commands-IAGYE2JW.js.map