import http from "node:http"; import path from "node:path"; import { spawn } from "node:child_process"; import fs from "fs-extra"; import chalk from "chalk"; import prompts from "prompts"; import { getDirname } from "./esm-paths"; const GUIDE_FILE_NAME = "USER_GUIDE.md"; type TGuideMode = "terminal" | "web" | "commander-help"; const __dirname = getDirname(import.meta.url); function getPackageRootPath(): string { return path.resolve(__dirname, "..", ".."); } async function readGuideMarkdown(): Promise { const packageRootPath = getPackageRootPath(); const guidePath = path.join(packageRootPath, GUIDE_FILE_NAME); if (await fs.pathExists(guidePath)) { return fs.readFile(guidePath, "utf8"); } const readmePath = path.join(packageRootPath, "README.md"); if (await fs.pathExists(readmePath)) { return fs.readFile(readmePath, "utf8"); } return `# SimpleMDG Dev CLI\n\nGuide file was not found. Run smdg --help to see command help.`; } function escapeHtml(value: string): string { return value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function inlineMarkdown(value: string): string { return escapeHtml(value) .replace(/`([^`]+)`/g, "$1") .replace(/\*\*([^*]+)\*\*/g, "$1"); } function markdownToHtml(markdown: string): string { const lines = markdown.replace(/\r\n/g, "\n").split("\n"); const htmlLines: string[] = []; let inCodeBlock = false; let codeLines: string[] = []; let inList = false; function closeList(): void { if (inList) { htmlLines.push(""); inList = false; } } function closeCodeBlock(): void { if (inCodeBlock) { htmlLines.push(`
${escapeHtml(codeLines.join("\n"))}
`); codeLines = []; inCodeBlock = false; } } for (const line of lines) { if (line.trim().startsWith("```")) { if (inCodeBlock) { closeCodeBlock(); } else { closeList(); inCodeBlock = true; codeLines = []; } continue; } if (inCodeBlock) { codeLines.push(line); continue; } const trimmedLine = line.trim(); if (!trimmedLine) { closeList(); continue; } const headingMatch = /^(#{1,4})\s+(.+)$/.exec(trimmedLine); if (headingMatch) { closeList(); const level = headingMatch[1].length; htmlLines.push(`${inlineMarkdown(headingMatch[2])}`); continue; } const bulletMatch = /^[-*]\s+(.+)$/.exec(trimmedLine); if (bulletMatch) { if (!inList) { htmlLines.push("