npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vitepress-gen-navs

v0.1.3

Published

用于生成 vitepress 中的 nav 和 sidebar 配置

Readme

vitepress-gen-navs

自动扫描目录结构,为 VitePress 生成 nav 和 sidebar 配置

特性

  • 🚀 自动扫描目录,生成 VitePress 的 nav 和 sidebar 配置
  • 📁 支持 glob 规则的包含/排除过滤
  • 🎨 自定义回调函数,灵活控制导航名称
  • 📝 智能提取标题(frontmatter > h1 > 文件名)
  • 📊 深度控制,限制目录层级
  • 🔗 自动生成链接路径
  • 📦 支持侧边栏分组和折叠

安装

npm install vitepress-gen-navs

快速开始

通常来说,只需要配置一下 dir 即可,其余的保持默认配置即可正常使用。如果有特殊的配置需求,可以翻阅后续的文档。

我建议文档都放在一个目录中,便于管理,通常是 docs 或者 document。同时需要配置一下 vitepress 的 srcDir 选项,使其与 dir 保持一致。

import { genNavs } from 'vitepress-gen-navs'

const { nav, sidebar } = genNavs({
    dir: './docs'
})

export default {
    // https://vitepress.dev/zh/reference/site-config#srcdir
    srcDir: "./docs", // 建议与 dir 保持一致
    themeConfig: {
        nav,
        sidebar
    }
}

结构如图所示:

PixPin_2025-10-22_17-32-20

API

GenNavsOptions

| 属性名 | 描述 | 类型 | 是否必填 | 默认值 | |--------|------|------|----------|--------| | dir | 扫描目录 | string | 否 | 当前目录 | | include | 全局包含规则 | string[] | 否 | ['**/node_modules/**', '**/.git/**'] | | exclude | 全局排除规则 | string[] | 否 | - | | nav | nav 特定配置 | NavSidebarConfig | 否 | - | | sidebar | sidebar 特定配置 | SidebarConfig | 否 | - | | onDirectory | 全局目录回调(nav/sidebar 未配置时的默认值)。返回的字符串会作为最终的展示名称。 | (info: DirInfo) => string | 否 | - | | onFile | 全局文件回调(nav/sidebar 未配置时的默认值)。返回的字符串会作为最终的展示名称。 | (info: FileInfo) => string | 否 | - | | excludeRootIndex | 是否在 nav 中排除根目录的 index.md | boolean | 否 | false | | formatSortPrefix | 是否格式化排序前缀(移除文件名中的排序前缀) | boolean | 否 | true |

NavSidebarConfig 配置项(用于 nav 配置)

| 属性名 | 描述 | 类型 | 是否必填 | 默认值 | |--------|------|------|----------|--------| | depth | 深度限制 | number | 否 | 2 | | onDirectory | 目录回调,优先级高于全局 | (info: DirInfo) => string \| null | 否 | - | | onFile | 文件回调,优先级高于全局 | (info: FileInfo) => string \| null | 否 | - |

SidebarConfig 配置项(用于 sidebar 配置)

| 属性名 | 描述 | 类型 | 是否必填 | 默认值 | |--------|------|------|----------|--------| | collapsed | 侧边栏组折叠状态。如果未指定,则不可折叠;如果为 true,则可折叠并且默认折叠;如果为 false,则可折叠但默认展开 | boolean | 否 | false | | onDirectory | 目录回调,优先级高于全局 | (info: DirInfo) => string \| null | 否 | - | | onFile | 文件回调,优先级高于全局 | (info: FileInfo) => string \| null | 否 | - |

回调参数

DirInfo(目录信息)

interface DirInfo {
    name: string           // 目录名
    path: string           // 绝对路径
    relativePath: string   // 相对路径
    depth: number          // 当前深度
}

FileInfo(文件信息)

interface FileInfo {
    name: string           // 文件名(不含扩展名)
    originalName: string   // 文件名
    path: string           // 绝对路径
    relativePath: string   // 相对路径
    frontmatter?: any      // frontmatter 数据
    firstHeading?: string  // 第一个 h1 标题
    depth: number          // 当前深度
}

使用示例

过滤特定目录

const { nav, sidebar } = genNavs({
    dir: './docs',
    exclude: ['**/drafts/**', '**/private/**']
})

自定义名称

const { nav, sidebar } = genNavs({
    dir: './docs',
    onDirectory: (info) => {
        // 使用目录名的大写形式
        return info.name.toUpperCase()
    },
    onFile: (info) => {
        // 优先使用 frontmatter 中的自定义字段
        return info.frontmatter?.customTitle || null
    }
})

限制深度

depth 参数控制生成配置的目录层级深度。

Nav 支持多层级嵌套

Nav 现在支持生成带下拉菜单的多层级导航结构:

const { nav, sidebar } = genNavs({
    dir: './docs',
    nav: {
        depth: 2  // nav 显示两层,第一层作为下拉菜单,第二层作为子项,如果你的 nav 不需要展示子项,只需要第一级,设置为 1 即可
    }
})

生成的 nav 配置示例:

// depth: 1 时(单层)
[
    { text: '指南', link: '/guide/' },
    { text: 'API', link: '/api/' }
]

// depth: 2 时(带下拉菜单)
[
    { 
        text: '指南', 
        items: [
            { text: '快速开始', link: '/guide/getting-started' },
            { text: '配置', link: '/guide/configuration' }
        ]
    },
    { 
        text: 'API', 
        items: [
            { text: '核心 API', link: '/api/core' },
            { text: '工具函数', link: '/api/utils' }
        ]
    }
]

深度限制的智能链接处理

当达到深度限制时,系统会智能处理 link:

  • 文件节点:直接使用该文件的路径作为 link
  • 目录节点:递归查找该目录下的第一个文件,使用该文件的路径作为 link

示例:

// 目录结构
docs/
  ├── guide/
  │   ├── basic/
  │   │   ├── intro.md
  │   │   └── config.md
  │   └── advanced/
  │       └── custom.md

// depth: 1 时,guide 会指向第一个找到的文件
const { nav } = genNavs({
    dir: './docs',
    nav: { depth: 1 }
})

// 生成结果
[
    { text: 'guide', link: '/guide/basic/intro' }  // 自动链接到第一个文件
]

排除根目录的 index.md

当文档根目录包含首页 index.md 文件时,可以通过 excludeRootIndex 选项控制其是否显示在 nav 配置中:

// 目录结构
docs/
  ├── index.md       // 首页,不需要在 nav 中显示
  ├── guide.md
  └── api.md

const { nav, sidebar } = genNavs({
    dir: './docs',
    excludeRootIndex: true  // 排除根目录的 index.md
})

// 生成的 nav 将不包含 index.md
[
    { text: 'guide', link: '/guide' },
    { text: 'api', link: '/api' }
]

注意

  • 此选项仅影响 nav 配置,不影响 sidebar 配置
  • 只排除根目录(扫描目录)下的 index.md,子目录中的 index.md 不受影响
  • 默认值为 false,即默认会包含根目录的 index.md

数字前缀排序

本工具内部针对 index.md 做出了特殊处理,永远排在当前列表层级的第一位

排序并没有提供特定的方法,依赖的是一种约定规范,即你在内部对你的文件夹或者文件名,标记一个序号,实现排序。(如 01-intro.md, 02-guide.md):

docs/
  ├── 01-getting-started.md
  ├── 02-configuration.md
  └── 03-advanced.md
默认支持的前缀格式如下:
 * - 数字 + 标题
 * - 数字 + . 后 + 标题
 * - 数字 + 多个空格 + 标题
 * - 数字 + 、后 + 标题
 * - 数字 + -后 + 标题
 * - 数字 + _后 + 标题
const { nav, sidebar } = genNavs({
    dir: './docs',
})

默认本工具内部 formatSortPrefix 配置为 true,会格式化掉前缀,只保留标题内容。即 01-intro.md 格式化后的结果为intro.md。如果你希望保留前缀,将此配置改为 false 即可。

侧边栏折叠

此行为与 vitepress 的 collapsed 一致。

const { nav, sidebar } = genNavs({
    dir: './docs',
    sidebar: {
        /**
         * 如果未指定,侧边栏组不可折叠
         * 如果为 `true`,则侧边栏组可折叠并且默认折叠
         * 如果为 `false`,则侧边栏组可折叠但默认展开
         * 如果不希望有这个功能,可以直接设置 undefined
         */
        collapsed: true  // 默认折叠所有分组
    }
})

分别配置 nav 和 sidebar

const { nav, sidebar } = genNavs({
    dir: './docs',
    nav: {
        depth: 1,
        exclude: ['**/internal/**']
    },
    sidebar: {
        depth: 3,
        collapsed: false,
        onDirectory: (info) => {
          	// TODO: 你的条件
          	// 返回的结果将作为最终的展示 nav 或 sidebar 名称
            return `📁 ${info.name}`
        }
    }
})

标题提取优先级

默认情况下(即不使用 onDirectory 或 onFile 的情况),标题按以下优先级提取:

  1. frontmatter.title - markdown 文件的 frontmatter 中的 title 字段
  2. 第一个 h1 标题 - markdown 文件中的第一个 # 标题
  3. 文件名 - 移除扩展名和数字前缀后的文件名

例如:

---
title: 自定义标题
---

# 文档标题

内容...

目录结构示例

License

MIT