65 lines
1.7 KiB
JavaScript
65 lines
1.7 KiB
JavaScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
|
|
const DOC_EXT = ['.md']
|
|
const EXCLUDED_DIRS = new Set(['.git', '.github', '.vitepress', 'node_modules', 'public'])
|
|
|
|
function isDirectory(p) {
|
|
return fs.existsSync(p) && fs.statSync(p).isDirectory()
|
|
}
|
|
|
|
function isMarkdown(p) {
|
|
return fs.existsSync(p) && fs.statSync(p).isFile() && DOC_EXT.includes(path.extname(p))
|
|
}
|
|
|
|
function titleFromName(name) {
|
|
return name.replace(/\.md$/i, '')
|
|
}
|
|
|
|
function sortByPinyinOrName(a, b) {
|
|
return a.localeCompare(b, 'zh-Hans-CN-u-co-pinyin')
|
|
}
|
|
|
|
export function generateNavAndSidebar(rootDir) {
|
|
const entries = fs.readdirSync(rootDir)
|
|
const sections = entries
|
|
.filter((e) => isDirectory(path.join(rootDir, e)))
|
|
.filter((e) => !EXCLUDED_DIRS.has(e) && !e.startsWith('.'))
|
|
.sort(sortByPinyinOrName)
|
|
|
|
const nav = []
|
|
const sidebar = {}
|
|
|
|
for (const dir of sections) {
|
|
const abs = path.join(rootDir, dir)
|
|
const readme = ['README.md', 'readme.md', 'index.md'].find((n) => fs.existsSync(path.join(abs, n)))
|
|
const files = fs
|
|
.readdirSync(abs)
|
|
.filter((f) => isMarkdown(path.join(abs, f)))
|
|
.sort(sortByPinyinOrName)
|
|
|
|
const items = files.map((f) => ({
|
|
text: titleFromName(f),
|
|
link: `/${encodeURI(dir)}/${encodeURI(f)}`,
|
|
}))
|
|
|
|
if (items.length > 0) {
|
|
sidebar[`/${dir}/`] = [
|
|
{
|
|
text: dir,
|
|
items,
|
|
},
|
|
]
|
|
if (readme) {
|
|
nav.push({ text: dir, link: `/${encodeURI(dir)}/${encodeURI(readme)}` })
|
|
} else {
|
|
nav.push({ text: dir, link: items[0].link })
|
|
}
|
|
} else {
|
|
nav.push({ text: dir, link: `/${encodeURI(dir)}/` })
|
|
}
|
|
}
|
|
|
|
return { nav, sidebar }
|
|
}
|