一行行实现 vuepress自动生成导航栏 & 侧边栏

1,894 阅读2分钟

第一部分:简介

以我的博客官网举例子 博客地址,文件夹目录如下,一个传统的Vuepress文件目录


第二部分: .vuepress/confing.js 使用

let VuepressEs = require('./src/index.js')

// 初始化定义 & 启动报警提示
let vuepressEs = new VuepressEs({
    // 1.导航栏文案(因为导航栏文件夹不能是中文的)
    navDataConfig: [
        ['1.quickcheck', '速查'],
        ['2.note', '前端体系'],
        ['3.other', '其他']
    ]
})

module.exports = {
    "title": "Notes",
    "description": "知识速查(了不起的个人工具库)",
    "head": [
        [
            "link",
            {
                "rel": "icon",
                "href": "/favicon.ico"
            }
        ]
    ],
    "themeConfig": {
        "repo": "https://github.com/zhukunpenglinyutong/notes",
        "nav": vuepressEs.getNavData(),
        "sidebar": vuepressEs.getSidebarData(),
    },
    "serviceWorker": true,
    "markdown": {
        "lineNumbers": false
    },
    "plugins": [
        [
            "vuepress-plugin-zooming",
            {
                "selector": ".theme-default-content img",
                "delay": 500,
                "options": {
                    "bgColor": "black",
                    "zIndex": 10000
                }
            }
        ],
        [
            "@vuepress/pwa",
            {
                "serviceWorker": true,
                "updatePopup": {
                    "/": {
                        "message": "发现新内容可用",
                        "buttonText": "刷新"
                    }
                }
            }
        ]
    ]
}

第三部分:代码实现

// index.js

// vuepress-es 主入口

let { readDirToObjTreeTool } = require('./tool.js'); // 工具函数
let { createNavData } = require('./navData.js'); // 生成导航栏
let { createSidebarData } = require('./sidebarData'); // 生成侧边栏

let dirObjTree = readDirToObjTreeTool() // 文件对象

class VuepressEs {
  
  constructor(navDataConfig = null) {  //构造器
    // 1.导航栏文案配置
    this.navDataConfig = navDataConfig
  }

  // 生成导航栏
  getNavData() {
    return createNavData(dirObjTree, this.navDataConfig);
  }

  // 生成侧边栏
  getSidebarData() {
    return createSidebarData(dirObjTree);
  }
}

module.exports = VuepressEs

// tool.js

const shelljs = require('shelljs'); // 前端写shell
const fs = require('fs');
const path = require('path');

/**
 * 遍历文件夹,生成 真实文件对象树
 * @return { name: '文件夹名称', data: [ {...}, {...} ], path: '路径'}
 */
function readDirToObjTreeTool() {

  let foldPath = shelljs.pwd().stdout // 当前目录的绝对路径
  let objTree = []

  function recursion(foldPath, data, isRootPath = true) {

    let files = fs.readdirSync(foldPath)

    // 1.目录循环
    files.forEach(item => {
      // 如果有配置表,这里还需要进行配置过滤一下

      let isDir = fs.statSync(`${foldPath}/${item}`).isDirectory()

      // 判断逻辑:是文件,并且不是以 .开头的隐藏文件,并且不是 node_modules && build
      if (isDir && !/^\./.test(item) && item !== 'node_modules' && item !== 'build') {
        data.push({
          name: item,
          data: [],
          path: `${foldPath}/${item}`
        })
      } else if (!isRootPath) {
        if (item !== '.DS_Store') data.push(item);
      }

    })

    // 2.遍历目录循环(递归)
    data.length > 0 && data[0].name !== undefined
      ? data.forEach(item => { if (item.path) recursion(item.path, item.data, false) })
      : ''
  }

  recursion(foldPath, objTree)

  return objTree
}

module.exports = {
  readDirToObjTreeTool: readDirToObjTreeTool
}

// navData.js

/**
 * 生成导航栏
 * @param { Array } 文件对象树
 * @param { Object } 配置文件(全部)
 * @return { Array } 导航栏数组
 */
function createNavData(dirObjTree, config) {
  let navArr = [];

  for (let i = 0; i < dirObjTree.length; i++) {
    if (dirObjTree[i] === undefined) return;
    // 1.生成导航
    navArr.push({
      text: textTool(dirObjTree[i].name, config.navDataConfig),
      link: `/${dirObjTree[i].name}/`
    })
  }

  return navArr
}

// 用于根据配置文件 生成到导航栏
function textTool(data, config) {
  if (config == null) return data;
  for (let i = 0; i < config.length; i++) {
    if (config[i][0] === data) return config[i][1]
  }
  return data
}

module.exports = {
  createNavData: createNavData
}

// sidebarData.js

// 生成侧边栏
function createSidebarData(dirObjTree) {
  let sidebarData = {};

  for (let i = 0; i < dirObjTree.length; i++) {
    if (dirObjTree[i] === undefined) return;
    
    let twLevelArr = []
    for (let j = 0; j < dirObjTree[i].data.length - 1; j++) {

      let childrenArr = []
      for (let z = 0; z < dirObjTree[i].data[j].data.length; z++) {
        childrenArr.push(`${dirObjTree[i].name}/${dirObjTree[i].data[j].name}/${dirObjTree[i].data[j].data[z]}`)
      }

      twLevelArr.push({
        title: dirObjTree[i].data[j].name,
        children: childrenArr
      })
    }

    sidebarData[`/${dirObjTree[i].name}`] = twLevelArr
  }

  return sidebarData
}

module.exports = {
  createSidebarData: createSidebarData
}

第四部分:后记

有空会整理成 npm 的,并添加一些更好用的功能,欢迎大家使用。