blob: 2dc413be4cd4d6d255a8cc6845c57f8333a0c3a2 [file]
const fs = require('fs');
const path = require('path');
const matter = require('gray-matter');
/**
* 遍历目录,返回所有 md/mdx 文件的路径
*/
function getAllDocs(dir) {
const result = [];
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
result.push(...getAllDocs(fullPath));
} else if (entry.isFile() && /\.(md|mdx)$/.test(entry.name)) {
result.push(fullPath);
}
}
return result;
}
/**
* 将父目录名转成人类可读格式
* 例如:
* "complex-types" → "Complex Types"
* "sql_data-type" → "Sql Data Type"
*/
function formatDirName(name) {
return name
.split(/[-_]/g)
.filter(Boolean)
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
/**
* 提取原始 front matter 类型(判断是否 JSON)
*/
function detectFrontMatterFormat(content) {
const fmMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
if (!fmMatch) return null;
const fmText = fmMatch[1].trim();
return fmText.startsWith('{') ? 'json' : 'yaml';
}
/**
* 主逻辑
*/
function fixDuplicateTitles(baseDir) {
const files = getAllDocs(baseDir);
// 1️⃣ 读取所有文档的 title
const titleMap = new Map(); // title -> [filePaths]
for (const file of files) {
const content = fs.readFileSync(file, 'utf8');
const { data } = matter(content);
if (data.title) {
const title = String(data.title).trim();
if (!titleMap.has(title)) titleMap.set(title, []);
titleMap.get(title).push(file);
}
}
// 2️⃣ 找出重复 title
for (const [title, paths] of titleMap.entries()) {
if (paths.length > 1) {
console.log(`\n⚠️ 发现重复标题 "${title}" (${paths.length} 个文件):`);
for (const filePath of paths) {
console.log(` → ${filePath}`);
const content = fs.readFileSync(filePath, 'utf8');
const parsed = matter(content);
const fmFormat = detectFrontMatterFormat(content);
const parentDir = path.basename(path.dirname(filePath));
const formattedParent = formatDirName(parentDir);
// 更新标题
parsed.data.title = `${title} | ${formattedParent}`;
// 保留 JSON 格式 front matter
let newFrontMatter = '';
if (fmFormat === 'json') {
newFrontMatter = `---\n${JSON.stringify(parsed.data, null, 4)}\n---`;
} else {
// fallback (YAML)
newFrontMatter = matter.stringify('', parsed.data).split('\n').slice(0, -1).join('\n');
}
// 拼回完整文件
const body = parsed.content.trimStart();
const newContent = `${newFrontMatter}\n\n${body}\n`;
fs.writeFileSync(filePath, newContent);
}
}
}
console.log('\n✅ 重复标题已修正完成。');
}
// CLI 调用
const baseDir = process.argv[2];
if (!baseDir) {
console.error('❌ 请提供要遍历的目录,如: node fix-duplicate-titles.js ./docs');
process.exit(1);
}
fixDuplicateTitles(path.resolve(baseDir));