自动生成 vitepress 侧边栏
在网上找了几个自动生成的包都和我的项目不太兼容,层级不是很满意,于是自己写了一个
原理
通过递归遍历文件夹,拿到所有文件和文件夹,然后根据文件名生成路由,最后将路由写入到配置文件中 区分文件夹和文件,文件夹的路由需要添加一个 items
属性,文件则不需要
待优化点
现在修改了路由后,需要重新生成路由,需要手动执行脚本,后续可以考虑优化一下
js
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const BASE_PATH = path.resolve(__dirname, "../");
const NO_NEED_DIRS = ["index.md", "vite.config.js", ".vitepress", "public"];
// 读一级标题作为文章标题
function getFirstHeading(filePath) {
const content = fs.readFileSync(filePath, "utf-8");
const match = content.match(/^#\s+(.*)/m);
return match ? match[1] : path.basename(filePath, ".md");
}
function generateRoutes(dirPath, baseRoute = "") {
const items = [];
const files = fs.readdirSync(dirPath);
files.forEach((file) => {
if (NO_NEED_DIRS.includes(file)) return;
const fullPath = path.join(dirPath, file);
// 相当于是拿到实例,实例上有多个方法
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) {
// 递归调用了
const subItems = generateRoutes(fullPath, `${baseRoute}/${file}`);
items.push({
text: file,
collapsed: true,
items: subItems,
});
} else if (stat.isFile() && path.extname(file) === ".md") {
const title = getFirstHeading(fullPath);
items.push({
text: title,
link: `${baseRoute}/${path.basename(file, ".md")}`,
});
}
});
return items;
}
function generateAllRoutes(basePath) {
const routes = {};
const folders = fs.readdirSync(basePath);
folders.forEach((folder) => {
const fullPath = path.join(basePath, folder);
if (fs.statSync(fullPath).isDirectory() && !NO_NEED_DIRS.includes(folder)) {
routes[`/${folder}`] = generateRoutes(fullPath, `/${folder}`);
}
});
return routes;
}
const siderBar = generateAllRoutes(BASE_PATH);
export default siderBar;