// 构建前将 posts/ 目录处理为静态数据 // 1. 复制图片等静态文件到 public/posts/ // 2. 生成 posts-data.json 供前端直接导入 import { cpSync, existsSync, rmSync, readdirSync, statSync, readFileSync, mkdirSync, writeFileSync } from 'fs' import { join, dirname, relative } from 'path' import { fileURLToPath } from 'url' const __dirname = dirname(fileURLToPath(import.meta.url)) const root = join(__dirname, '..') const src = join(root, 'posts') const dst = join(root, 'public', 'posts') // 1. 复制静态文件到 public/posts/ if (existsSync(dst)) { rmSync(dst, { recursive: true, force: true }) } cpSync(src, dst, { recursive: true, filter: (srcPath) => !srcPath.endsWith('.md') }) console.log('已同步 posts 静态文件到 public/posts/') // 2. 扫描 posts/ 生成数据清单 function scanDir(dir) { const entries = readdirSync(dir) const result = { dirs: [], files: [] } for (const name of entries) { if (name.startsWith('.')) continue const full = join(dir, name) const st = statSync(full) if (st.isDirectory()) { const children = scanDir(full) // 跳过空目录 if (children.dirs.length === 0 && children.files.length === 0) continue result.dirs.push({ name, children }) } else if (name.endsWith('.md')) { const relPath = relative(src, full).replace(/\\/g, '/').replace(/\.md$/, '') const content = readFileSync(full, 'utf-8') result.files.push({ name: name.replace('.md', ''), path: relPath, content }) } } // 排序:文件夹在前,文件在后,各自字母排序 result.dirs.sort((a, b) => a.name.localeCompare(b.name)) result.files.sort((a, b) => a.name.localeCompare(b.name)) return result } function buildTree(scanResult) { const items = [] for (const dir of scanResult.dirs) { items.push({ type: 'category', name: dir.name, children: buildTree(dir.children) }) } for (const file of scanResult.files) { items.push({ type: 'post', name: file.name, path: file.path }) } return items } function buildContentMap(scanResult, map = {}) { for (const file of scanResult.files) { map[file.path] = file.content } for (const dir of scanResult.dirs) { buildContentMap(dir.children, map) } return map } function getAllPaths(scanResult, paths = []) { for (const file of scanResult.files) { paths.push(file.path) } for (const dir of scanResult.dirs) { getAllPaths(dir.children, paths) } return paths } const scanResult = scanDir(src) const data = { tree: buildTree(scanResult), contentMap: buildContentMap(scanResult), paths: getAllPaths(scanResult) } const outDir = join(root, 'src', 'generated') mkdirSync(outDir, { recursive: true }) writeFileSync(join(outDir, 'posts-data.json'), JSON.stringify(data)) console.log(`已生成 posts-data.json (${data.paths.length} 篇文章)`)