一直显示?点击任意区域即可关闭

vitepress-theme-ninc:给 VitePress 用的博客主题

用 VitePress 搭文档的人不少,搭博客的却不多,默认主题确实偏素。市面上的 VitePress 博客主题要么功能不全,要么改起来费劲,于是有了这个项目。

首页首页

主题基于 imsyy/vitepress-theme-curve 二次开发。curve 的底子不错,我在此基础上做了大量重构与扩展:抽成 npm 包、重写配置系统、梳理文档、补充功能和样式,让它能够直接装好就用。

相关链接

快速开始

bash
mkdir my-blog && cd my-blog
npx vitepress-theme-ninc init

init 是交互式的,方向键选择、回车确认。问题依次是:

  1. 初始化模式基础博客配置(带示例文章和全部页面)或 极简配置(仅核心文件)
  2. 配置方式使用默认配置自定义配置(自定义会多问几个开关,比如是否启用 PWA、评论)
  3. 基础信息:站点标题、描述、网址、作者名、邮箱

选择完成后生成完整的项目结构:

text
my-blog/
├─ .vitepress/
│  ├─ config.mts          ← 站点配置(已注入 defineConfig)
│  ├─ theme/
│  │  └─ index.ts         ← 主题入口
│  └─ themeConfig.ts      ← 主题配置(含你输入的站点信息)
├─ posts/
│  └─ articles/
│     └─ hello-world.md   ← 示例文章
├─ public/
│  ├─ images/             ← 占位头像、Logo、封面
│  └─ svg/                ← 自定义 SVG 图标目录
├─ index.md               ← 首页
└─ package.json           ← 含 dev/build/preview/summary/init-proxy 脚本

pnpm install && pnpm dev,打开 http://localhost:5173 就能看到博客页面。

首页首页

配置系统

主题采用「双工厂」配置体系:defineConfig 决定「怎么构建」(Vite 插件、PWA、RSS、sitemap),defineThemeConfig 决定「长什么样、有什么功能」(导航、评论、搜索、外观)。两者分别住在 config.mtsthemeConfig.ts,互不干扰。

主题配置基于 defu 深合并,只需要声明想修改的字段,其余沿用默认值:

ts
// .vitepress/themeConfig.ts
import { defineThemeConfig } from 'vitepress-theme-ninc/defineThemeConfig'

export const themeConfig = defineThemeConfig({
  siteMeta: {
    title: '我的博客',
    site: 'https://example.com',
  },
  comment: {
    enable: true,
    twikoo: { envId: 'https://your-twikoo.example.com' }
  }
})

主题升级时默认值会同步更新,用户侧的覆盖不受影响。配置顶层共有 22 个功能模块(siteMetahomeTopnavcommentsearchmusicasidenesaiSummaryfancyboxjumpRedirect 等),全部字段附带 TypeScript 类型提示。

数组合并为整体替换

navinject.headercover.showCover.defaultCover 等数组字段是整体替换而非拼接,写入时需给完整列表。对象字段则递归合并,未声明的子字段保持默认。

功能

以下功能默认内置,不需要额外安装插件:

  • Twikoo 评论系统:开源自部署,数据自己掌控。支持表情、图片、嵌套回复,配合 Twikoo 后台可启用 Akismet 反垃圾与 SMTP 邮件通知
  • Algolia 全站搜索:基于 Algolia DocSearch / InstantSearch,导航栏搜索框实时下拉匹配文章标题、摘要与高亮关键词
  • APlayer + MetingJS 音乐播放器:支持网易云、QQ 音乐、酷狗三个平台,可配置歌单、专辑、单曲
  • AI 文章摘要:兼容 OpenAI 接口,内置 DeepSeek、智谱 GLM、通义千问、Kimi、MiniMax、小米 MiMo、豆包、StepFun、OpenAI 等多家预设,构建期自动为文章生成打字机效果摘要。支持 CLI 本地预生成(pnpm run summary)跳过构建耗时,也可部署运行时代理实现浏览器流式生成
  • 文章加密:采用密钥文件 + 密码双重验证,HMAC-SHA256 哈希处理。访问者需先上传与站点密钥一致的本地密钥文件,再输入密码才能解锁正文;连续 5 次密码错误锁定 30 秒,防暴力破解
  • PWA 离线支持:基于 @vite-pwa/vitepress,自动生成 Service Worker 与 Manifest,内置 4 条运行时缓存规则。未安装依赖时主题自动降级跳过 PWA,不会报错
  • Fancybox 图片灯箱:默认启用,点击图片放大查看,支持手势缩放、画廊浏览、键盘切换
  • RSS 订阅buildEnd 阶段自动生成 rss.xml,默认包含最近 10 篇非加密文章,按日期降序
  • 暗色模式:主题自实现暗色切换(关闭 VitePress 原生 appearance),支持亮色、暗色、跟随系统三种模式,状态持久化
  • 代码组图标:基于 vitepress-plugin-group-icons,内置 58 条语言/文件类型 → iconify 图标的默认映射,标签自动匹配,可通过 groupIconConfig 追加自定义映射
  • 自定义光标:三种状态适配明暗主题
  • 外链中转:默认启用,自动注入中转页(dev 通过 Vite 中间件、build 输出 redirect.html)。内置白/黑名单机制:白名单站点(github、vuejs 等)显示「已信任」并自动跳转,黑名单站点(购物类)显示危险警告,其余站点由用户确认
  • 个性化设置按钮:左下角齿轮按钮,可切换主题模式、字体大小等,设置项持久化到 localStorage
  • 数学公式:底层使用 markdown-it-mathjax3,支持行内 $...$ 与块级 $$...$$ 公式
  • 代码块默认折叠:文章 frontmatter 设置 cbx: true 折叠全文代码块,单块用 cbf=true
  • 站点地图:自动生成 sitemap.xml,内置过滤规则排除分页、加密文章、pages/ 下的非内容页
  • Gzip + Brotli 压缩:生产构建自动生成 .gz.br 文件
  • 自动导入unplugin-auto-import 自动注入 Vue/VitePress API,unplugin-vue-components 自动注册主题组件与用户组件,Markdown 中直接用标签名即可

此外还内置若干页面组件:关于、归档、分类、标签、留言板、赞赏名单、装备页,配合 frontmatter 还可启用转载声明、参考资料、文章置顶、推荐文章等写作功能。

NES 模拟器

附带的红白机模拟器页面。init 时选上会自动复制超级马里奥 ROM 到 public/nes-rom/,生成 pages/nes.md,并在导航栏添加入口。

NES 模拟器NES 模拟器

支持的能力:

  • 存档读档:快速存档(N)、快速读档(M),以及槽位 1/2 存读档(Shift+1/2/3/4),存档数据存于 IndexedDB,按 savePrefix 隔离不同游戏
  • TAS 录像:支持 .fm2 格式录像回放,可配置文件预设或页面临时上传(仅原版 ROM 兼容)
  • 双人控制:P1 用 WASD + JKIU,P2 用方向键 + 小键盘,连接手柄即可使用
  • 自定义按键:页面内进入改键模式,按下任意键立即生效,记录按游戏 savePrefix 隔离,存于 localStorage
  • 金手指:兼容 VirtuaNES 的 XXXX-YY-ZZ 格式,可在 themeConfig 预设(访客首次进入自动加入列表,默认关闭),也可运行时添加
  • 上传 ROM:页面拖放区支持临时加载本地 .nes 文件
  • 防误触模式:开启后所有功能键需配合 Shift 才能触发,避免游戏时误按

作者演示站 blog.ninc.top/pages/nes 内置 27 款游戏可体验。

文章页文章页

关于页关于页

Markdown 扩展

在标准 Markdown 与 VitePress 原生扩展(自定义容器、代码组、行高亮、Emoji、目录、数学公式)之上,主题额外集成了以下容器和语法:

::: timeline 2024
- 01-01 发布 1.0
- 03-15 支持 AI 摘要
:::

::: button primary
去 GitHub
:::

包含:

  • ::: timeline 标题:时间线容器,适合版本记录、编年史
  • ::: radio checked:单选容器,适合任务清单
  • ::: button 类名:CTA 按钮容器,类名拼接为 class="button xxx"
  • ::: card:信息卡片容器,内部支持任意 Markdown
  • %%k%%:按键标记,渲染为带样式的 <span class="keybutton">,如 %%Ctrl%% + %%C%%
  • {.class #id key=value}markdown-it-attrs 属性语法,给任意元素追加 HTML 属性
  • ::: code-group:代码组(标签页切换),自动显示对应语言图标
  • 表格自动包裹 <div class="table-container">,列数多时横向滚动

Vue 组件也可以直接嵌入 Markdown,<script setup> 语法照常使用。主题内置组件通过 unplugin-vue-components 自动注册,无需手动 import;主题页面视图则通过 vitepress-theme-ninc/views 显式导入使用。

CLI 工具

主题自带三个命令:

命令用途
npx vitepress-theme-ninc init从零生成完整博客项目
pnpm run summary本地预生成 AI 摘要,构建时只读缓存
pnpm run init-proxy生成 AI 摘要运行时代理脚手架(Cloudflare Worker / Vercel Serverless 二选一)

所有命令都是交互式的,中文提示,方向键选择、空格多选、回车确认,随时可 Ctrl+C 取消。

已有 VitePress 项目

已有的 VitePress 项目三步接入:

bash
pnpm add vitepress-theme-ninc
ts
// .vitepress/theme/index.ts
import Theme from 'vitepress-theme-ninc'
export default Theme
ts
// .vitepress/config.mts
import { defineConfig } from 'vitepress-theme-ninc/defineConfig'
import { themeConfig } from './themeConfig'

export default defineConfig(
  { sitemap: { hostname: 'https://your-site.com' } },
  themeConfig
)

新建 .vitepress/themeConfig.ts 填写站点信息,重启 dev server 即可。在已有项目根目录直接运行 npx vitepress-theme-ninc init 也行,命令会检测已存在文件并逐个询问是否覆盖,package.json 会做合并更新(强制对齐主题版本、补齐缺失依赖与脚本)。

MIT 协议,遇到问题欢迎提 Issue。