101 lines
2.8 KiB
JavaScript
101 lines
2.8 KiB
JavaScript
// 构建前将 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} 篇文章)`)
|