Skip to content

思路

遍历文件目录, 生成我们需要的格式数据, 例如: 下列

ts
sidebar: {
    '/': [
    {
        text: '/',
        collapsed: false,
        items: [
        {
            text: 'test',
            link: '/test'

        }
        ]
    }
    ],
    '/javascript/': [
    {
        text: 'java',
        collapsed: false,
        items: [
        { text: '开始', link: "/javascript/test1" },
        {
            text: 'test',
            items: [
            { text: '测试', link: "/javascript/code/index" }
            ]
        }
        ]
    }
    ],
},

提示

文件夹里面不只是有普通的文件, 例如.md, /ts等等, 还会有着文件夹, 这时就需要使用到递归, 而自动生成目录, 又不得不提到回溯算法


以下是实现代码, 但在此之前需要查看我的目录结构, 因为目录结构的不同可能会导致路径出错, 最终报错.

.
├─ docs
│  ├─ .vitepress
│  │  └─ config.ts
│  ├─ .javascript
│  │  └─ test1.md
│  |  ├─ code
│  │     └─ index.md
│  ├─ auto-sidebar.ts //自己创建的文件
│  ├─ test1.md //测试文件1
│  └─ index.md
└─ package.json

注意点

  1. auto-sidebar.ts一定要放在docs文件夹下

实现

  1. docs文件夹下创建auto-sidebar.ts

  2. 将以下代码复制到auto-sidebar.ts

auto-sidebar.ts
ts
//导入fs模块, 需要对文件目录进行处理
import fs from "node:fs";
//DefaultTheme是对类型进行约束
import { type DefaultTheme } from "vitepress";
//设置基础路径, 如果auto-sidebar.ts放在docs文件夹下, 那么basePath路径就是/docs
const basePath = __dirname;// __dirname获取当前文件所在目录的绝对路径
//设置白名单, 数组中的文件不会被遍历, 以下是一些常见的不需要被遍历的文件
const whiteList = [".vitepress", "components", "config", "public", "img", 'assets']
//lstatSync函数的作用是同步地获取文件或目录的状态信息, isDirectory判断当前文件是否为文件夹
const isDirectory = (path: string) => fs.lstatSync(path).isDirectory();
//获取当前目录信息
const root = fs.readdirSync(__dirname);
//过滤白名单函数
const filter = (arr: string[]) => {
  return arr.filter(val => !whiteList.includes(val));
}
//最终的目录结构
const config: DefaultTheme.Sidebar = {};

/**
 * 
 * @param arr 目录文件信息
 * @param deep 目录深度
 * @param curArr 当前信息需要添加的数组
 * @param prefixPath 前缀路径
 */
const setDir2 = (arr: string[], deep: number, curArr: any[], prefixPath: string) => {
  //例外处理
  if (deep === 1) {
    //第一层不是文件夹的部分都会存放在'/'路径下
    config['/'] = [{
      text: 'other',
      collapsed: false,
      items: curArr
    }]
  }
  //过滤白名单
  arr = filter(arr);
  
  for (let i = 0; i < arr.length; i++) {
    //获取当前文件名, 可能是文件夹, 可能是文件
    const item = arr[i];
    const prefix = prefixPath === '/' ? "" : prefixPath;
    //完整路径
    const finalPrefixPath = prefix + '/' + item;
    const path = basePath + finalPrefixPath;
    //对路径前缀的一些处理
    //判断是否是文件夹 
    if (isDirectory(path)) {
      const tempArr: DefaultTheme.SidebarItem[] = [];
      //是 ==> 继续递归
      //例外: 第一层的文件夹不需要存放在 curArr中; 而其他层需要
      if (deep === 1) {
        //第一层处理数据为: 创建一个数组, 其中的items递归传递给curArr
        //需保证路径格式为: '/xxx/'
        config['/' + item + '/'] = [{
          text: item,
          collapsed: false,
          items: tempArr,
        }]
        //隐藏回溯递归下去
        setDir2(fs.readdirSync(path), deep + 1, tempArr, finalPrefixPath);
      } else {
        //第二层: 创建一个对象, 将此对象添加到curArr中 将其中的items递归传递给curArr
        const tempObj: DefaultTheme.SidebarItem = {
          text: item.replace(".md", ""),
          items: tempArr
        }
        curArr.push(tempObj);
        //回溯递归
        setDir2(fs.readdirSync(path), deep + 1, tempArr, finalPrefixPath);
      }
    } else {
      ////不是md文件, 跳过
      if (item.indexOf(".md") === -1) continue;
      //否 ==> 添加curArr数组中
      curArr.push({ text: item.replace(".md", ""), link: finalPrefixPath });
    }
  }

}

setDir2(root, 1, [], "/");

export default config;

使用

config.ts
ts
import { defineConfig } from 'vitepress'
import autoSidebar from "../auto-sidebar";
export default defineConfig({
    /* 其他配置 */
    sidebar: autoSidebar,
    /* 其他配置 */
})

最终实现结果

提示

目录结构查看最上方

Released under the MIT License.