PaiGramDocs/docs/.vitepress/theme/plugins/autoSidebarBeta.ts
2023-10-21 01:15:41 +08:00

101 lines
2.6 KiB
TypeScript

import { join, resolve } from 'node:path'
import matter from 'gray-matter'
import fg from 'fast-glob'
import fs from 'fs-extra'
export interface Options {
base: string
title?: string
collapsed?: boolean
}
export const DIR_ROOT = resolve(__dirname, '../../../../')
export const DIR_SRC = resolve(DIR_ROOT, 'docs')
export function fastGlobSync(type: string, dir: string, ignore: string[] = []) {
const files = fg.sync('*', {
onlyDirectories: type === 'dir',
onlyFiles: type === 'file',
cwd: dir,
ignore: [
'_*',
'dist',
'node_modules',
...ignore,
],
})
files.sort()
return files
}
export const dirs = fastGlobSync('dir', DIR_SRC)
function getSidebar(dir: string, title: string | undefined) {
const curDir = resolve(DIR_SRC, dir)
const dirs = fastGlobSync('dir', curDir)
const res = []
if (dirs.length) {
// TODO 多级目录
dirs.forEach((e) => {
const childDir = resolve(curDir, e)
const mdFiles = fastGlobSync('file', childDir)
const sidebar = {
text: (e.charAt(0).toUpperCase() + e.slice(1)).replaceAll('-', ' '),
collapsed: false,
items: [] as any,
}
mdFiles.forEach((file) => {
if (file.endsWith('.md')) {
let prePath = join('/', dir, e, file)
if (file === 'index.md')
prePath = join('/', dir, e, '/')
const item = {
text: file.slice(0, -3),
link: prePath,
}
sidebar.items.push(item)
}
})
res.push(sidebar)
})
}
else {
const mdFiles = fastGlobSync('file', curDir)
const sidebar = {
text: title,
collapsed: false,
items: [] as any,
}
mdFiles.filter(e => e !== 'index.md').forEach((file) => {
if (file.endsWith('.md')) {
const prePath = join('/', dir, file)
const curDir = resolve(DIR_SRC, dir)
const mdPath = resolve(curDir, file)
const mdRaw = fs.readFileSync(mdPath, 'utf-8')
const { content: md } = matter(mdRaw)
const mdLine = md.split('\n').slice(0, 6)
const mdTitle = mdLine.filter(e => e.match(/^#\s*/))[0]?.replace('#', '').trim()
const item = {
text: mdTitle || file.slice(0, -3),
link: prePath,
}
sidebar.items.push(item)
}
})
res.push(sidebar)
}
return res
}
export default (options: Options) => {
options.collapsed = options?.collapsed ?? false
if (options.base !== '/') {
const dir = dirs.filter((dir: string) => dir.includes(options.base))[0]
if (dir) {
const sidebar = getSidebar(dir, options.title)
return sidebar
}
}
}