UNPKG

branch-commit-compare

Version:
145 lines (123 loc) 4.17 kB
const fs = require("fs").promises; const path = require("path"); const { loadIgnoredCommits } = require("./ignore"); const { generateOptimizedCommands } = require("./ignore"); function formatDate(date) { return new Date(date).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai", year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", }); } async function generateMarkdown(comparison) { let markdown = "# 分支提交差异对比\n\n"; markdown += `生成时间: ${formatDate(new Date())}\n\n`; const { sourceBranch, targetBranch, author, timeRange, commits } = comparison; markdown += `## ${sourceBranch} vs ${targetBranch}\n\n`; if (author !== "全部") markdown += `提交者: ${author}\n`; if (timeRange !== "全部时间") markdown += `时间范围: ${timeRange}\n`; markdown += "\n"; markdown += "| 提交信息 | 提交时间 | 作者 | 状态 | 提交哈希 |\n"; markdown += "|----------|----------|------|------|----------|\n"; // 按时间排序所有提交 commits.sort((a, b) => new Date(b.date) - new Date(a.date)); // 加载已忽略的提交 const ignoredCommits = await loadIgnoredCommits(); commits.forEach((commit) => { if (!ignoredCommits.some((item) => item.hash === commit.hash)) { const indicator = commit.status === "both" ? "🔴🔵" : commit.status === "source" ? "🔴" : "🔵"; markdown += `| ${commit.message} | ${formatDate(commit.date)} | ${ commit.authorName } | ${indicator} | ${commit.hash} |\n`; } }); // 添加 Cherry-pick 指令块 const sourceOnlyCommits = commits.filter( (c) => c.status === "source" && !ignoredCommits.some((item) => item.hash === c.hash) ); if (sourceOnlyCommits.length > 0) { markdown += "\n### Cherry-pick 指令\n\n"; markdown += "```bash\n"; markdown += `# 切换到 ${targetBranch} 分支\n`; markdown += `git checkout ${targetBranch}\n\n`; // 基础命令 markdown += "# 基础命令(逐个提交)\n"; sourceOnlyCommits.forEach((commit) => { markdown += `git cherry-pick ${commit.hash} # ${commit.message}\n`; }); markdown += "\n"; // 优化命令 markdown += "# 优化命令(一次性合并)\n"; markdown += generateOptimizedCommands(sourceOnlyCommits); markdown += "\n"; markdown += "```\n"; } return markdown; } async function generateTimelineHTML( commits, sourceBranch, targetBranch, author, timeRange, commitRemarks, port ) { try { // 读取模板文件 const templatePath = path.join( __dirname, "..", "templates", "timeline.html" ); let template = await fs.readFile(templatePath, "utf8"); // 加载已忽略的提交 const ignoredCommits = await loadIgnoredCommits(); // 格式化日期 const formattedCommits = commits.map((commit) => ({ ...commit, formattedDate: formatDate(commit.date), })); // 确保备注是数组格式 const remarksArray = Array.isArray(commitRemarks) ? commitRemarks : []; // 替换所有模板变量 const replacements = { "{{title}}": `分支对比: ${sourceBranch} vs ${targetBranch}`, "{{generatedTime}}": formatDate(new Date()), "{{sourceBranch}}": JSON.stringify(sourceBranch), "{{targetBranch}}": JSON.stringify(targetBranch), "{{commits}}": JSON.stringify(formattedCommits), "{{ignoredCommits}}": JSON.stringify(ignoredCommits), "{{commitRemarks}}": JSON.stringify(remarksArray), "{{author}}": JSON.stringify(author), "{{timeRange}}": JSON.stringify(timeRange), "{{port}}": port.toString(), }; // 执行所有替换 for (const [key, value] of Object.entries(replacements)) { template = template.replace( new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"), value ); } return template; } catch (error) { console.error("生成 HTML 报告失败:", error); throw error; } } module.exports = { generateMarkdown, generateTimelineHTML, };