UNPKG

@limy-org/vite-plugin-vitepress-auto-sidebar

Version:

Automatically generate VitePress sidebar

100 lines (97 loc) 2.74 kB
import glob from 'glob'; import fs from 'fs'; import path from 'path'; const titleCache = {}; function VitePluginAutoSidebar(options = {}) { const root = options.root || process.cwd(); return { name: "VitePluginAutoSidebar", config(config) { config.vitepress.site.themeConfig.sidebar = getSidebarConfig( root, options ); return config; }, configureServer: ({ watcher, restart }) => { const fsWatcher = watcher.add("*.md"); fsWatcher.on("all", (event, filePath) => { if (event === "addDir") return; if (event === "unlinkDir") return; if (event == "add") return; if (event === "unlink") { restart(); return; } if (event === "change") { const title = matchTitle(filePath); const route = "/" + path.relative(root, filePath); if (!route || !title) return; if (title === titleCache[route]) return; restart(); return; } }); } }; } function getSidebarConfig(root, opts) { const paths = glob.sync("**/*.md", { cwd: root, ignore: opts.ignores }); const obj = {}; const sidebar = {}; for (const path2 of paths) { const pathSegments = path2.split("/"); if (pathSegments[0].endsWith(".md")) continue; const key = "/" + pathSegments[0] + "/"; const data = pathSegments.slice(1); if (!obj[key]) { obj[key] = []; } obj[key].push(data); } for (const key of Object.keys(obj)) { const data = obj[key]; const result = []; for (const pathSegments of data) { let currentLevel = result; for (const segment of pathSegments) { let existingPath = currentLevel.find((item) => item.text === segment); if (!existingPath) { const itemConfig = {}; if (segment.endsWith(".md")) { const route = key + pathSegments.join("/"); itemConfig.text = matchTitle(path.join(root, route)); itemConfig.link = route; titleCache[route] = itemConfig.text; } else { itemConfig.text = segment; itemConfig.collapsed = false; itemConfig.items = []; } currentLevel.push(itemConfig); existingPath = itemConfig; } currentLevel = existingPath.items; } } sidebar[key] = result; } if (opts.sidebarResolved) { opts.sidebarResolved(sidebar); } return sidebar; } function matchTitle(p) { const content = fs.readFileSync(p, "utf-8"); return ((content.match(/^#(.*)\n?/) || [])[1] || "").trim(); } export { VitePluginAutoSidebar as default };