feat(theme)!: add collections support (#704)
* feat(theme)!: add collection support
This commit is contained in:
parent
fae5825618
commit
4d2361a704
@ -40,8 +40,8 @@
|
|||||||
},
|
},
|
||||||
"plume-deps": {
|
"plume-deps": {
|
||||||
"vuepress": "2.0.0-rc.24",
|
"vuepress": "2.0.0-rc.24",
|
||||||
"vue": "^3.5.21",
|
"vue": "^3.5.22",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"typescript": "^5.9.2"
|
"typescript": "^5.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
124
cli/templates/.vuepress/collections.ts.handlebars
Normal file
124
cli/templates/.vuepress/collections.ts.handlebars
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/**
|
||||||
|
* @see https://theme-plume.vuejs.press/guide/collection/ 查看文档了解配置详情。
|
||||||
|
*
|
||||||
|
* Collections 配置文件,它在 `.vuepress/plume.config.{{#if useTs}}ts{{else}}js{{/if}}` 中被导入。
|
||||||
|
*
|
||||||
|
* 请注意,你应该先在这里配置好 Collections,然后再启动 vuepress,主题会在启动 vuepress 时,
|
||||||
|
* 读取这里配置的 Collections,然后在与 Collection 相关的 Markdown 文件中,自动生成 permalink。
|
||||||
|
*
|
||||||
|
* collection 的 type 为 `post` 时,表示为 文档列表类型(即没有侧边导航栏,有文档列表页)
|
||||||
|
* 可用于实现如 博客、专栏 等以文章列表聚合形式的文档集合 (内容相对碎片化的)
|
||||||
|
*
|
||||||
|
* collection 的 type 为 `doc` 时,表示为文档类型(即有侧边导航栏)
|
||||||
|
* 可用于实现如 笔记、知识库、文档等以侧边导航栏形式的文档集合 (内容强关联、成体系的)
|
||||||
|
* 如果发现 侧边栏没有显示,那么请检查你的配置是否正确,以及 Markdown 文件中的 permalink
|
||||||
|
* 是否是以对应的 Collection 配置的 link 的前缀开头。 是否展示侧边栏是根据 页面链接 的前缀 与 `collection.link`
|
||||||
|
* 的前缀是否匹配来决定。
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在受支持的 IDE 中会智能提示配置项。
|
||||||
|
*
|
||||||
|
* - `defineCollections` 是用于定义 collection 集合的帮助函数
|
||||||
|
* - `defineCollection` 是用于定义单个 collection 配置的帮助函数
|
||||||
|
*
|
||||||
|
* 通过 `defineCollection` 定义的 collection 配置,应该填入 `defineCollections` 中
|
||||||
|
*/
|
||||||
|
import { defineCollection, defineCollections } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
{{#if multiLanguage}}
|
||||||
|
{{#each locales}}
|
||||||
|
/* =================== locale: {{ lang }} ======================= */
|
||||||
|
|
||||||
|
const {{ prefix }}Blog = defineCollection({
|
||||||
|
// post 类型,这里用于实现 博客功能
|
||||||
|
type: 'post',
|
||||||
|
// 文档集合所在目录,相对于 `docs{{ path }}`
|
||||||
|
dir: 'blog',
|
||||||
|
// 文档标题,它将用于在页面的面包屑导航中显示
|
||||||
|
title: 'Blog',
|
||||||
|
// 文章列表页的链接,如果 `linkPrefix` 未定义,它也将作为 相关的文章的 permalink 的前缀
|
||||||
|
link: '/blog/',
|
||||||
|
// linkPrefix: '/article/', // 相关文章的链接前缀
|
||||||
|
// postList: true, // 是否启用文章列表页
|
||||||
|
// tags: true, // 是否启用标签页
|
||||||
|
// archives: true, // 是否启用归档页
|
||||||
|
// categories: true, // 是否启用分类页
|
||||||
|
// postCover: 'right', // 文章封面位置
|
||||||
|
// pagination: 15, // 每页显示文章数量
|
||||||
|
})
|
||||||
|
|
||||||
|
const {{ prefix }}DemoDoc = defineCollection({
|
||||||
|
// doc 类型,该类型带有侧边栏
|
||||||
|
type: 'doc',
|
||||||
|
// 文档集合所在目录,相对于 `docs{{ path }}`
|
||||||
|
dir: 'demo',
|
||||||
|
// `dir` 所指向的目录中的所有 markdown 文件,其 permalink 需要以 `linkPrefix` 配置作为前缀
|
||||||
|
// 如果 前缀不一致,则无法生成侧边栏。
|
||||||
|
// 所以请确保 markdown 文件的 permalink 都以 `{{ path }}` + `linkPrefix` 开头
|
||||||
|
linkPrefix: '/demo',
|
||||||
|
// 文档标题,它将用于在页面的面包屑导航中显示
|
||||||
|
title: 'Demo',
|
||||||
|
// 手动配置侧边栏结构
|
||||||
|
sidebar: ['', 'foo', 'bar'],
|
||||||
|
// 根据文件结构自动生成侧边栏
|
||||||
|
// sidebar: 'auto',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出所有的 collections
|
||||||
|
* ({{ prefix }}Blog 为博客示例,如果不需要博客功能,请删除)
|
||||||
|
* ({{ prefix }}DemoDoc 为参考示例,如果不需要它,请删除)
|
||||||
|
*/
|
||||||
|
export const {{ prefix }}Collections = defineCollections([
|
||||||
|
{{ prefix }}Blog,
|
||||||
|
{{ prefix }}DemoDoc,
|
||||||
|
])
|
||||||
|
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
const blog = defineCollection({
|
||||||
|
// post 类型,这里用于实现 博客功能
|
||||||
|
type: 'post',
|
||||||
|
// 文档集合所在目录,相对于 `docs{{ path }}`
|
||||||
|
dir: 'blog',
|
||||||
|
// 文档标题,它将用于在页面的面包屑导航中显示
|
||||||
|
title: 'Blog',
|
||||||
|
// 文章列表页的链接,如果 `linkPrefix` 未定义,它也将作为 相关的文章的 permalink 的前缀
|
||||||
|
link: '/blog/',
|
||||||
|
// linkPrefix: '/article/', // 相关文章的链接前缀
|
||||||
|
// postList: true, // 是否启用文章列表页
|
||||||
|
// tags: true, // 是否启用标签页
|
||||||
|
// archives: true, // 是否启用归档页
|
||||||
|
// categories: true, // 是否启用分类页
|
||||||
|
// postCover: 'right', // 文章封面位置
|
||||||
|
// pagination: 15, // 每页显示文章数量
|
||||||
|
})
|
||||||
|
|
||||||
|
const demoDoc = defineCollection({
|
||||||
|
// doc 类型,该类型带有侧边栏
|
||||||
|
type: 'doc',
|
||||||
|
// 文档集合所在目录,相对于 `docs{{ path }}`
|
||||||
|
dir: 'demo',
|
||||||
|
// `dir` 所指向的目录中的所有 markdown 文件,其 permalink 需要以 `linkPrefix` 配置作为前缀
|
||||||
|
// 如果 前缀不一致,则无法生成侧边栏。
|
||||||
|
// 所以请确保 markdown 文件的 permalink 都以 `linkPrefix` 开头
|
||||||
|
linkPrefix: '/demo',
|
||||||
|
// 文档标题,它将用于在页面的面包屑导航中显示
|
||||||
|
title: 'Demo',
|
||||||
|
// 手动配置侧边栏结构
|
||||||
|
sidebar: ['', 'foo', 'bar'],
|
||||||
|
// 根据文件结构自动生成侧边栏
|
||||||
|
// sidebar: 'auto',
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出所有的 collections
|
||||||
|
* (blog 为博客示例,如果不需要博客功能,请删除)
|
||||||
|
* (demoDoc 为参考示例,如果不需要它,请删除)
|
||||||
|
*/
|
||||||
|
export default defineCollection([
|
||||||
|
blog,
|
||||||
|
demoDoc,
|
||||||
|
])
|
||||||
|
{{/if}}
|
||||||
@ -54,23 +54,6 @@ export default defineUserConfig({
|
|||||||
// contributors: true,
|
// contributors: true,
|
||||||
// changelog: false,
|
// changelog: false,
|
||||||
|
|
||||||
/**
|
|
||||||
* 博客
|
|
||||||
* @see https://theme-plume.vuejs.press/config/basic/#blog
|
|
||||||
*/
|
|
||||||
// blog: false, // 禁用博客
|
|
||||||
// blog: {
|
|
||||||
// postList: true, // 是否启用文章列表页
|
|
||||||
// tags: true, // 是否启用标签页
|
|
||||||
// archives: true, // 是否启用归档页
|
|
||||||
// categories: true, // 是否启用分类页
|
|
||||||
// postCover: 'right', // 文章封面位置
|
|
||||||
// pagination: 15, // 每页显示文章数量
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* 博客文章页面链接前缀 */
|
|
||||||
article: '/article/',
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编译缓存,加快编译速度
|
* 编译缓存,加快编译速度
|
||||||
* @see https://theme-plume.vuejs.press/config/basic/#cache
|
* @see https://theme-plume.vuejs.press/config/basic/#cache
|
||||||
@ -116,9 +99,9 @@ export default defineUserConfig({
|
|||||||
// readingTime: true,
|
// readingTime: true,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* markdown
|
* markdown
|
||||||
* @see https://theme-plume.vuejs.press/config/markdown/
|
* @see https://theme-plume.vuejs.press/config/markdown/
|
||||||
*/
|
*/
|
||||||
// markdown: {
|
// markdown: {
|
||||||
// abbr: true, // 启用 abbr 语法 *[label]: content
|
// abbr: true, // 启用 abbr 语法 *[label]: content
|
||||||
// annotation: true, // 启用 annotation 语法 [+label]: content
|
// annotation: true, // 启用 annotation 语法 [+label]: content
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export const {{prefix}}Navbar = defineNavbarConfig([
|
|||||||
{ text: '{{#if isEn}}Archives{{else}}归档{{/if}}', link: '{{ path }}blog/archives/' },
|
{ text: '{{#if isEn}}Archives{{else}}归档{{/if}}', link: '{{ path }}blog/archives/' },
|
||||||
{
|
{
|
||||||
text: '{{#if isEn}}Notes{{else}}笔记{{/if}}',
|
text: '{{#if isEn}}Notes{{else}}笔记{{/if}}',
|
||||||
items: [{ text: '{{#if isEn}}Demo{{else}}示例{{/if}}', link: '{{ path }}notes/demo/README.md' }]
|
items: [{ text: '{{#if isEn}}Demo{{else}}示例{{/if}}', link: '{{ path }}demo/README.md' }]
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ export default defineNavbarConfig([
|
|||||||
{ text: '{{#if isEn}}Archives{{else}}归档{{/if}}', link: '/blog/archives/' },
|
{ text: '{{#if isEn}}Archives{{else}}归档{{/if}}', link: '/blog/archives/' },
|
||||||
{
|
{
|
||||||
text: '{{#if isEn}}Notes{{else}}笔记{{/if}}',
|
text: '{{#if isEn}}Notes{{else}}笔记{{/if}}',
|
||||||
items: [{ text: '{{#if isEn}}Demo{{else}}示例{{/if}}', link: '/notes/demo/README.md' }]
|
items: [{ text: '{{#if isEn}}Demo{{else}}示例{{/if}}', link: '/demo/README.md' }]
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
/**
|
|
||||||
* @see https://theme-plume.vuejs.press/guide/document/ 查看文档了解配置详情。
|
|
||||||
*
|
|
||||||
* Notes 配置文件,它在 `.vuepress/plume.config.{{#if useTs}}ts{{else}}js{{/if}}` 中被导入。
|
|
||||||
*
|
|
||||||
* 请注意,你应该先在这里配置好 Notes,然后再启动 vuepress,主题会在启动 vuepress 时,
|
|
||||||
* 读取这里配置的 Notes,然后在与 Note 相关的 Markdown 文件中,自动生成 permalink。
|
|
||||||
*
|
|
||||||
* 如果你发现 侧边栏没有显示,那么请检查你的配置是否正确,以及 Markdown 文件中的 permalink
|
|
||||||
* 是否是以对应的 note 配置的 link 的前缀开头。 是否展示侧边栏是根据 页面链接 的前缀 与 `note.link`
|
|
||||||
* 的前缀是否匹配来决定。
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在受支持的 IDE 中会智能提示配置项。
|
|
||||||
*
|
|
||||||
* - `defineNoteConfig` 是用于定义单个 note 配置的帮助函数
|
|
||||||
* - `defineNotesConfig` 是用于定义 notes 集合的帮助函数
|
|
||||||
*
|
|
||||||
* 通过 `defineNoteConfig` 定义的 note 配置,应该填入 `defineNotesConfig` 的 notes 数组中
|
|
||||||
*/
|
|
||||||
import { defineNoteConfig, defineNotesConfig } from 'vuepress-theme-plume'
|
|
||||||
|
|
||||||
{{#if multiLanguage}}
|
|
||||||
{{#each locales}}
|
|
||||||
/* =================== locale: {{ lang }} ======================= */
|
|
||||||
|
|
||||||
const {{ prefix }}DemoNote = defineNoteConfig({
|
|
||||||
dir: 'demo',
|
|
||||||
// `dir` 所指向的目录中的所有 markdown 文件,其 permalink 需要以 `link` 配置作为前缀
|
|
||||||
// 如果 前缀不一致,则无法生成侧边栏。
|
|
||||||
// 所以请确保 markdown 文件的 permalink 都以 `link` 开头
|
|
||||||
link: '/demo',
|
|
||||||
// 手动配置侧边栏结构
|
|
||||||
sidebar: ['', 'foo', 'bar'],
|
|
||||||
// 根据文件结构自动生成侧边栏
|
|
||||||
// sidebar: 'auto',
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出所有的 note
|
|
||||||
* 每一个 note 都应该填入到 `notes.notes` 数组中
|
|
||||||
* ({{ prefix }}DemoNote 为参考示例,如果不需要它,请删除)
|
|
||||||
*/
|
|
||||||
export const {{ prefix }}Notes = defineNotesConfig({
|
|
||||||
dir: '{{ removeLeadingSlash path }}notes',
|
|
||||||
link: '{{ path }}',
|
|
||||||
notes: [{{ prefix }}DemoNote],
|
|
||||||
})
|
|
||||||
|
|
||||||
{{/each}}
|
|
||||||
{{else}}
|
|
||||||
const demoNote = defineNoteConfig({
|
|
||||||
dir: 'demo',
|
|
||||||
// `dir` 所指向的目录中的所有 markdown 文件,其 permalink 需要以 `link` 配置作为前缀
|
|
||||||
// 如果 前缀不一致,则无法生成侧边栏。
|
|
||||||
// 所以请确保 markdown 文件的 permalink 都以 `link` 开头
|
|
||||||
link: '/demo',
|
|
||||||
// 手动配置侧边栏结构
|
|
||||||
sidebar: ['', 'foo', 'bar'],
|
|
||||||
// 根据文件结构自动生成侧边栏
|
|
||||||
// sidebar: 'auto',
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出所有的 note
|
|
||||||
* 每一个 note 都应该填入到 `notes.notes` 数组中
|
|
||||||
* (DemoNote 为参考示例,如果不需要它,请删除)
|
|
||||||
*/
|
|
||||||
export default defineNotesConfig({
|
|
||||||
dir: 'notes',
|
|
||||||
link: '/',
|
|
||||||
notes: [demoNote],
|
|
||||||
})
|
|
||||||
{{/if}}
|
|
||||||
@ -12,11 +12,11 @@
|
|||||||
|
|
||||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
{{#if multiLanguage}}
|
{{#if multiLanguage}}
|
||||||
|
import { enCollections, zhCollections } from './collections'
|
||||||
import { enNavbar, zhNavbar } from './navbar'
|
import { enNavbar, zhNavbar } from './navbar'
|
||||||
import { enNotes, zhNotes } from './notes'
|
|
||||||
{{else}}
|
{{else}}
|
||||||
import navbar from './navbar'
|
import navbar from './navbar'
|
||||||
import notes from './notes'
|
import collections from './collections'
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +64,7 @@ export default defineThemeConfig({
|
|||||||
},
|
},
|
||||||
|
|
||||||
navbar,
|
navbar,
|
||||||
notes,
|
collections,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公告板
|
* 公告板
|
||||||
@ -102,7 +102,7 @@ export default defineThemeConfig({
|
|||||||
},
|
},
|
||||||
|
|
||||||
navbar: {{ prefix }}Navbar,
|
navbar: {{ prefix }}Navbar,
|
||||||
notes: {{ prefix }}Notes,
|
collections: {{ prefix }}Collections,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公告板
|
* 公告板
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import type { ClientConfig } from 'vuepress/client'
|
|||||||
import { defineMermaidConfig } from '@vuepress/plugin-markdown-chart/client'
|
import { defineMermaidConfig } from '@vuepress/plugin-markdown-chart/client'
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import { Layout } from 'vuepress-theme-plume/client'
|
import { Layout } from 'vuepress-theme-plume/client'
|
||||||
|
import VPPostItem from 'vuepress-theme-plume/components/Posts/VPPostItem.vue'
|
||||||
import { defineClientConfig } from 'vuepress/client'
|
import { defineClientConfig } from 'vuepress/client'
|
||||||
import AsideNav from '~/components/AsideNav.vue'
|
import AsideNav from '~/components/AsideNav.vue'
|
||||||
import { setupThemeColors } from '~/composables/theme-colors.js'
|
import { setupThemeColors } from '~/composables/theme-colors.js'
|
||||||
@ -14,6 +15,9 @@ defineMermaidConfig({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export default defineClientConfig({
|
export default defineClientConfig({
|
||||||
|
enhance({ app }) {
|
||||||
|
app.component('VPPostItem', VPPostItem)
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
setupThemeColors()
|
setupThemeColors()
|
||||||
},
|
},
|
||||||
|
|||||||
8
docs/.vuepress/collections/en/index.ts
Normal file
8
docs/.vuepress/collections/en/index.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { defineCollections, type ThemeCollections } from 'vuepress-theme-plume'
|
||||||
|
import { themeConfig } from './theme-config.js'
|
||||||
|
import { themeGuide } from './theme-guide.js'
|
||||||
|
|
||||||
|
export const enCollections: ThemeCollections = defineCollections([
|
||||||
|
themeGuide,
|
||||||
|
themeConfig,
|
||||||
|
])
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
import type { ThemeCollectionItem } from 'vuepress-theme-plume'
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
import { defineCollection } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
export const themeConfig: ThemeNote = defineNoteConfig({
|
export const themeConfig: ThemeCollectionItem = defineCollection({
|
||||||
dir: 'theme/config',
|
type: 'doc',
|
||||||
link: '/config/',
|
dir: 'config',
|
||||||
|
title: 'Config',
|
||||||
|
linkPrefix: '/config/',
|
||||||
sidebar: [
|
sidebar: [
|
||||||
{
|
{
|
||||||
text: 'Config',
|
text: 'Config',
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
import type { ThemeCollectionItem } from 'vuepress-theme-plume'
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
import { defineCollection } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
export const themeGuide: ThemeNote = defineNoteConfig({
|
export const themeGuide: ThemeCollectionItem = defineCollection({
|
||||||
dir: 'theme/guide',
|
type: 'doc',
|
||||||
link: '/guide/',
|
dir: 'guide',
|
||||||
|
title: 'Guide',
|
||||||
|
linkPrefix: '/guide/',
|
||||||
sidebar: [
|
sidebar: [
|
||||||
{
|
{
|
||||||
text: 'Quick Start',
|
text: 'Quick Start',
|
||||||
10
docs/.vuepress/collections/zh/index.ts
Normal file
10
docs/.vuepress/collections/zh/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { defineCollections, type ThemeCollections } from 'vuepress-theme-plume'
|
||||||
|
import { themeConfig } from './theme-config.js'
|
||||||
|
import { themeGuide } from './theme-guide.js'
|
||||||
|
import { tools } from './tools.js'
|
||||||
|
|
||||||
|
export const zhCollections: ThemeCollections = defineCollections([
|
||||||
|
themeGuide,
|
||||||
|
themeConfig,
|
||||||
|
tools,
|
||||||
|
])
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
import type { ThemeCollectionItem } from 'vuepress-theme-plume'
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
import { defineCollection } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
export const themeConfig: ThemeNote = defineNoteConfig({
|
export const themeConfig: ThemeCollectionItem = defineCollection({
|
||||||
dir: 'theme/config',
|
type: 'doc',
|
||||||
link: '/config/',
|
title: '配置',
|
||||||
|
dir: 'config',
|
||||||
|
linkPrefix: '/config/',
|
||||||
sidebar: [
|
sidebar: [
|
||||||
{
|
{
|
||||||
text: '配置',
|
text: '配置',
|
||||||
@ -13,8 +15,8 @@ export const themeConfig: ThemeNote = defineNoteConfig({
|
|||||||
'theme',
|
'theme',
|
||||||
'locales',
|
'locales',
|
||||||
'navbar',
|
'navbar',
|
||||||
'notes',
|
|
||||||
'sidebar',
|
'sidebar',
|
||||||
|
'collections',
|
||||||
'markdown',
|
'markdown',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -1,9 +1,11 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
import type { ThemeCollectionItem } from 'vuepress-theme-plume'
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
import { defineCollection } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
export const themeGuide: ThemeNote = defineNoteConfig({
|
export const themeGuide: ThemeCollectionItem = defineCollection({
|
||||||
dir: 'theme/guide',
|
type: 'doc',
|
||||||
link: '/guide/',
|
dir: 'guide',
|
||||||
|
title: '指南',
|
||||||
|
linkPrefix: '/guide/',
|
||||||
sidebar: [
|
sidebar: [
|
||||||
{
|
{
|
||||||
text: '从这里开始',
|
text: '从这里开始',
|
||||||
@ -14,9 +16,13 @@ export const themeGuide: ThemeNote = defineNoteConfig({
|
|||||||
'intro',
|
'intro',
|
||||||
'usage',
|
'usage',
|
||||||
'project-structure',
|
'project-structure',
|
||||||
|
{
|
||||||
|
text: '集合',
|
||||||
|
link: 'collection',
|
||||||
|
items: ['collection-post', 'collection-doc'],
|
||||||
|
},
|
||||||
|
'sidebar',
|
||||||
'write',
|
'write',
|
||||||
'blog',
|
|
||||||
'document',
|
|
||||||
'locales',
|
'locales',
|
||||||
'deployment',
|
'deployment',
|
||||||
'optimize-build',
|
'optimize-build',
|
||||||
20
docs/.vuepress/collections/zh/tools.ts
Normal file
20
docs/.vuepress/collections/zh/tools.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import type { ThemeCollectionItem } from 'vuepress-theme-plume'
|
||||||
|
import { defineCollection } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export const tools: ThemeCollectionItem = defineCollection({
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'tools',
|
||||||
|
title: '工具',
|
||||||
|
linkPrefix: '/tools/',
|
||||||
|
sidebar: [
|
||||||
|
{
|
||||||
|
text: '工具',
|
||||||
|
icon: 'tabler:tools',
|
||||||
|
items: [
|
||||||
|
'custom-theme',
|
||||||
|
'home-hero-tint-plate',
|
||||||
|
'caniuse',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
@ -28,7 +28,7 @@ export default defineUserConfig({
|
|||||||
['meta', { name: 'google-site-verification', content: 'AaTP7bapCAcoO9ZGE67ilpy99GL6tYqtD30tRHjO9Ps' }],
|
['meta', { name: 'google-site-verification', content: 'AaTP7bapCAcoO9ZGE67ilpy99GL6tYqtD30tRHjO9Ps' }],
|
||||||
],
|
],
|
||||||
|
|
||||||
pagePatterns: ['**/*.md', '!**/*.snippet.md', '!.vuepress', '!node_modules', '!docs/notes/theme/guide/代码演示/demo/*'],
|
pagePatterns: ['**/*.md', '!**/*.snippet.md', '!.vuepress', '!node_modules', '!docs/guide/repl/demo/*'],
|
||||||
|
|
||||||
extendsBundlerOptions(bundlerOptions, app) {
|
extendsBundlerOptions(bundlerOptions, app) {
|
||||||
addViteOptimizeDepsInclude(bundlerOptions, app, '@simonwep/pickr')
|
addViteOptimizeDepsInclude(bundlerOptions, app, '@simonwep/pickr')
|
||||||
|
|||||||
@ -2,13 +2,7 @@ import type { LLMPage, LLMState } from '@vuepress/plugin-llms'
|
|||||||
import type { ThemeSidebarItem } from 'vuepress-theme-plume'
|
import type { ThemeSidebarItem } from 'vuepress-theme-plume'
|
||||||
import { generateTOCLink as rawGenerateTOCLink } from '@vuepress/plugin-llms'
|
import { generateTOCLink as rawGenerateTOCLink } from '@vuepress/plugin-llms'
|
||||||
import { ensureEndingSlash, ensureLeadingSlash } from 'vuepress/shared'
|
import { ensureEndingSlash, ensureLeadingSlash } from 'vuepress/shared'
|
||||||
import { zhNotes } from './notes/zh/index.js'
|
import { zhCollections } from './collections/zh/index.js'
|
||||||
|
|
||||||
const noteNames = {
|
|
||||||
'/guide/': '指南',
|
|
||||||
'/config/': '配置',
|
|
||||||
'/tools/': '工具',
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizePath(prefix: string, path = ''): string {
|
function normalizePath(prefix: string, path = ''): string {
|
||||||
if (path.startsWith('/'))
|
if (path.startsWith('/'))
|
||||||
@ -79,9 +73,9 @@ export function tocGetter(llmPages: LLMPage[], llmState: LLMState): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Notes
|
// Notes
|
||||||
zhNotes.notes.forEach(({ dir, link, sidebar = [] }) => {
|
zhCollections.filter(note => note.type === 'doc').forEach(({ dir, title, sidebar = [] }) => {
|
||||||
tableOfContent += `### ${noteNames[link]}\n\n`
|
tableOfContent += `### ${title}\n\n`
|
||||||
const prefix = normalizePath('/notes/', dir)
|
const prefix = normalizePath(dir)
|
||||||
if (sidebar === 'auto') {
|
if (sidebar === 'auto') {
|
||||||
tableOfContent += `${processAutoSidebar(prefix).join('')}\n`
|
tableOfContent += `${processAutoSidebar(prefix).join('')}\n`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,13 +6,13 @@ export const zhNavbar: ThemeNavItem[] = defineNavbarConfig([
|
|||||||
{
|
{
|
||||||
text: '指南',
|
text: '指南',
|
||||||
icon: 'icon-park-outline:guide-board',
|
icon: 'icon-park-outline:guide-board',
|
||||||
link: '/notes/theme/guide/quick-start/intro.md',
|
link: '/guide/quick-start/intro.md',
|
||||||
activeMatch: '^/guide/',
|
activeMatch: '^/guide/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: '配置',
|
text: '配置',
|
||||||
icon: 'icon-park-outline:setting-two',
|
icon: 'icon-park-outline:setting-two',
|
||||||
link: '/notes/theme/config/intro.md',
|
link: '/config/intro.md',
|
||||||
activeMatch: '^/config/',
|
activeMatch: '^/config/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
import type { ThemeNoteListOptions } from 'vuepress-theme-plume'
|
|
||||||
import { defineNotesConfig } from 'vuepress-theme-plume'
|
|
||||||
import { themeConfig } from './theme-config'
|
|
||||||
import { themeGuide } from './theme-guide'
|
|
||||||
|
|
||||||
export const enNotes: ThemeNoteListOptions = defineNotesConfig({
|
|
||||||
dir: 'en/notes',
|
|
||||||
link: '/',
|
|
||||||
notes: [
|
|
||||||
themeGuide,
|
|
||||||
themeConfig,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
import type { ThemeNoteListOptions } from 'vuepress-theme-plume'
|
|
||||||
import { defineNotesConfig } from 'vuepress-theme-plume'
|
|
||||||
// import { plugins } from './plugins'
|
|
||||||
import { themeConfig } from './theme-config'
|
|
||||||
import { themeGuide } from './theme-guide'
|
|
||||||
import { tools } from './tools'
|
|
||||||
|
|
||||||
export const zhNotes: ThemeNoteListOptions = defineNotesConfig({
|
|
||||||
dir: 'notes',
|
|
||||||
link: '/',
|
|
||||||
notes: [
|
|
||||||
themeGuide,
|
|
||||||
themeConfig,
|
|
||||||
// plugins,
|
|
||||||
tools,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
|
||||||
|
|
||||||
export const plugins: ThemeNote = defineNoteConfig({
|
|
||||||
dir: 'plugins',
|
|
||||||
link: '/plugins/',
|
|
||||||
sidebar: [
|
|
||||||
{
|
|
||||||
text: '插件',
|
|
||||||
link: '/plugins/',
|
|
||||||
items: [
|
|
||||||
// 'caniuse',
|
|
||||||
// 'iconify',
|
|
||||||
'shiki',
|
|
||||||
'md-power',
|
|
||||||
'content-updated',
|
|
||||||
{
|
|
||||||
text: 'plugin-netlify-functions',
|
|
||||||
dir: 'netlify-functions',
|
|
||||||
link: '/plugins/plugin-netlify-functions/',
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
'介绍',
|
|
||||||
'使用',
|
|
||||||
'功能',
|
|
||||||
'api',
|
|
||||||
'functions',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import type { ThemeNote } from 'vuepress-theme-plume'
|
|
||||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
|
||||||
|
|
||||||
export const tools: ThemeNote = defineNoteConfig({
|
|
||||||
dir: 'tools',
|
|
||||||
link: '/tools/',
|
|
||||||
sidebar: [
|
|
||||||
{
|
|
||||||
text: '工具',
|
|
||||||
icon: 'tabler:tools',
|
|
||||||
items: [
|
|
||||||
'custom-theme',
|
|
||||||
'home-hero-tint-plate',
|
|
||||||
'caniuse',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
@ -1,8 +1,8 @@
|
|||||||
import type { ThemeConfig } from 'vuepress-theme-plume'
|
import type { ThemeConfig } from 'vuepress-theme-plume'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
import { enCollections, zhCollections } from './collections/index.js'
|
||||||
import { enNavbar, zhNavbar } from './navbar.js'
|
import { enNavbar, zhNavbar } from './navbar.js'
|
||||||
import { enNotes, zhNotes } from './notes/index.js'
|
|
||||||
|
|
||||||
export default defineThemeConfig({
|
export default defineThemeConfig({
|
||||||
logo: '/plume.png',
|
logo: '/plume.png',
|
||||||
@ -27,12 +27,24 @@ export default defineThemeConfig({
|
|||||||
|
|
||||||
locales: {
|
locales: {
|
||||||
'/': {
|
'/': {
|
||||||
notes: zhNotes,
|
// notes: zhNotes,
|
||||||
navbar: zhNavbar,
|
navbar: zhNavbar,
|
||||||
|
collections: [
|
||||||
|
// 博客
|
||||||
|
{ type: 'post', dir: '/blog/', link: '/blog/', title: '博客' },
|
||||||
|
// 文档
|
||||||
|
...zhCollections,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'/en/': {
|
'/en/': {
|
||||||
notes: enNotes,
|
// notes: enNotes,
|
||||||
navbar: enNavbar,
|
navbar: enNavbar,
|
||||||
|
collections: [
|
||||||
|
// 博客
|
||||||
|
{ type: 'post', dir: '/blog/', link: '/blog/', title: 'Blog' },
|
||||||
|
// 文档
|
||||||
|
...enCollections,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -41,7 +53,6 @@ export default defineThemeConfig({
|
|||||||
'/article/enx7c9s/': '123456',
|
'/article/enx7c9s/': '123456',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
autoFrontmatter: { exclude: ['**/*.snippet.*'] },
|
|
||||||
|
|
||||||
bulletin: {
|
bulletin: {
|
||||||
layout: 'top-right',
|
layout: 'top-right',
|
||||||
|
|||||||
@ -174,6 +174,7 @@ npm run docs:dev
|
|||||||
'Hammuu1112',
|
'Hammuu1112',
|
||||||
'SherkeyXD',
|
'SherkeyXD',
|
||||||
{ github: 'Kinneyzhang', name: 'Geekinney' },
|
{ github: 'Kinneyzhang', name: 'Geekinney' },
|
||||||
|
'huyunan',
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@ -590,7 +590,7 @@ export default config
|
|||||||
|
|
||||||
**输出:**
|
**输出:**
|
||||||
|
|
||||||
@[code](../notes/theme/snippet/snippet-1.js)
|
@[code](../../snippet/snippet-1.js)
|
||||||
|
|
||||||
如果你只想导入这个文件的一部分:
|
如果你只想导入这个文件的一部分:
|
||||||
|
|
||||||
@ -2,7 +2,6 @@
|
|||||||
title: 1.0.0-rc.154 更新说明
|
title: 1.0.0-rc.154 更新说明
|
||||||
createTime: 2025/06/19 18:10:18
|
createTime: 2025/06/19 18:10:18
|
||||||
permalink: /article/yw0dmwcm/
|
permalink: /article/yw0dmwcm/
|
||||||
sticky: true
|
|
||||||
tags:
|
tags:
|
||||||
- 破坏性更新
|
- 破坏性更新
|
||||||
---
|
---
|
||||||
188
docs/blog/3.更新说明/165.md
Normal file
188
docs/blog/3.更新说明/165.md
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
---
|
||||||
|
title: ⚠️ 1.0.0-rc.165 破坏性更新说明:博客与笔记功能迁移至“集合”
|
||||||
|
sticky: true
|
||||||
|
createTime: 2025/09/28 22:18:52
|
||||||
|
permalink: /blog/dk58a4t2/
|
||||||
|
tags:
|
||||||
|
- 破坏性更新
|
||||||
|
- 重要更新
|
||||||
|
---
|
||||||
|
|
||||||
|
:::important ‼️ 本次更新为破坏性更新!博客与笔记功能已整体迁移至全新的“集合”架构。‼️
|
||||||
|
:::
|
||||||
|
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
## 设计动机:为什么引入“集合”?
|
||||||
|
|
||||||
|
[跳转至迁移指南 👇👇👇](#迁移指南){.read-more}
|
||||||
|
|
||||||
|
### 背景与问题分析
|
||||||
|
|
||||||
|
主题最初仅支持**博客**功能,将 `docs` 源目录下的所有 Markdown 文件识别为博客文章。随着版本迭代,我们新增了**笔记/知识库**功能,默认将 `notes` 目录作为笔记根目录,并将其内容从博客列表中排除。
|
||||||
|
|
||||||
|
这种分阶段实现导致了**架构上的不平衡**:博客成为“一等公民”,而笔记功能则显得边缘化。这给用户带来了以下困扰:
|
||||||
|
|
||||||
|
- **路径冗余**:笔记文件必须存放在 `notes/` 目录下,增加了不必要的目录层级
|
||||||
|
- **链接复杂**:未开启 `autoFrontmatter` 时,URL 会强制包含 `/notes/` 前缀
|
||||||
|
- **概念混淆**:用户常困惑于“笔记”与“文档”的功能区别
|
||||||
|
- **配置繁琐**:需要额外调整 `notes.dir` 配置才能实现标准文档站结构
|
||||||
|
|
||||||
|
这些设计缺陷源于历史迭代的遗留问题,我们对此深表歉意。
|
||||||
|
|
||||||
|
### 解决方案:统一的内容抽象
|
||||||
|
|
||||||
|
经过对主流静态站点生成器(如 Hugo、VitePress)和全栈框架(如 Nuxt)的调研,我们从 `@nuxt/content` 的 `collection` 概念中获得灵感。
|
||||||
|
|
||||||
|
我们决定引入**集合**作为统一的内容组织单元。无论是博客、笔记、文档还是知识库,本质上都是 Markdown 文件的特定集合,只是在呈现方式上有所差异。
|
||||||
|
|
||||||
|
:::important 核心洞察:通过“集合”抽象,统一各类内容的组织形式,同时保留各自的展示特性。
|
||||||
|
:::
|
||||||
|
|
||||||
|
基于内容特征,我们定义了两种集合类型:
|
||||||
|
|
||||||
|
- **`post` 类型**:适用于碎片化、关联性弱的内容(如博客、专栏),提供文章列表作为导航入口
|
||||||
|
- **`doc` 类型**:适用于结构化、关联性强的内容(如文档、手册),提供侧边栏进行快速导航
|
||||||
|
|
||||||
|
这一设计既解决了历史架构问题,又为未来扩展更多内容类型奠定了基础。
|
||||||
|
|
||||||
|
## 迁移指南
|
||||||
|
|
||||||
|
### 核心概念
|
||||||
|
|
||||||
|
- **集合**:通过 `collection.dir` 指定目录,该目录下所有 Markdown 文件均归属该集合
|
||||||
|
- **集合类型**:
|
||||||
|
- `post`:碎片化内容,支持文章列表导航
|
||||||
|
- `doc`:结构化内容,支持侧边栏导航
|
||||||
|
|
||||||
|
### 配置迁移
|
||||||
|
|
||||||
|
替换原有的 `blog` 和 `notes` 配置:
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
// @noErrors
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
// [!code --:9]
|
||||||
|
// 移除旧的 blog 和 notes 配置
|
||||||
|
blog: { /* 博客配置 */ },
|
||||||
|
notes: {
|
||||||
|
link: '/',
|
||||||
|
dir: '/notes/',
|
||||||
|
notes: [
|
||||||
|
{ dir: 'typescript', link: '/typescript/', sidebar: 'auto' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
// [!code ++:16]
|
||||||
|
// 使用 collections 配置
|
||||||
|
collections: [
|
||||||
|
{
|
||||||
|
type: 'post', // 替代原博客功能
|
||||||
|
dir: 'blog', // 指向 docs/blog 目录
|
||||||
|
title: '博客' // 集合显示名称
|
||||||
|
// 原博客配置继续保留
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'doc', // 替代原笔记功能
|
||||||
|
dir: 'typescript', // 指向 docs/typescript 目录
|
||||||
|
title: 'TypeScript笔记',
|
||||||
|
sidebar: 'auto', // 自动生成侧边栏
|
||||||
|
},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 目录结构调整
|
||||||
|
|
||||||
|
按照以下步骤迁移文件:
|
||||||
|
|
||||||
|
**操作步骤:**
|
||||||
|
|
||||||
|
1. 将 `notes` 目录下的子目录直接移至 `docs` 根目录
|
||||||
|
2. 创建 `blog` 目录,将原博客文章移入其中
|
||||||
|
3. 移除空的 `notes` 目录
|
||||||
|
|
||||||
|
:::: flex
|
||||||
|
|
||||||
|
<div style="flex:1">
|
||||||
|
|
||||||
|
::: file-tree title="迁移前结构"
|
||||||
|
|
||||||
|
- docs
|
||||||
|
- -- notes
|
||||||
|
- typescript
|
||||||
|
- basic.md
|
||||||
|
- advanced.md
|
||||||
|
- blog-cate-1
|
||||||
|
- post-1.md
|
||||||
|
- blog-cate-2
|
||||||
|
- post-2.md
|
||||||
|
- blog-post.md
|
||||||
|
- README.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="align-self: center"><Icon name="mingcute:arrow-right-fill" /></div>
|
||||||
|
|
||||||
|
<div style="flex:1">
|
||||||
|
|
||||||
|
:::file-tree title="迁移后结构"
|
||||||
|
|
||||||
|
- docs
|
||||||
|
- typescript
|
||||||
|
- basic.md
|
||||||
|
- advanced.md
|
||||||
|
- ++ blog
|
||||||
|
- blog-cate-1
|
||||||
|
- post-1.md
|
||||||
|
- blog-cate-2
|
||||||
|
- post-2.md
|
||||||
|
- blog-post.md
|
||||||
|
- README.md
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
::::
|
||||||
|
|
||||||
|
### 帮助函数
|
||||||
|
|
||||||
|
- `defineCollection`:用于定义单个 collection 配置的帮助函数
|
||||||
|
- `defineCollections`:用于定义多个 collection 配置的帮助函数
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineCollection, defineCollections } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export const blog = defineCollection({
|
||||||
|
type: 'post',
|
||||||
|
dir: 'blog',
|
||||||
|
title: '博客'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const typescript = defineCollection({
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'typescript',
|
||||||
|
title: 'TypeScript笔记',
|
||||||
|
sidebar: 'auto'
|
||||||
|
})
|
||||||
|
|
||||||
|
export const collections = defineCollections([
|
||||||
|
blog,
|
||||||
|
typescript
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
## 详细文档
|
||||||
|
|
||||||
|
[集合文档](../../guide/quick-start/collection.md){.read-more}
|
||||||
|
|
||||||
|
[post 集合](../../guide/quick-start/collection-post.md){.read-more}
|
||||||
|
|
||||||
|
[doc 集合](../../guide/quick-start/collection-doc.md){.read-more}
|
||||||
528
docs/config/collections.md
Normal file
528
docs/config/collections.md
Normal file
@ -0,0 +1,528 @@
|
|||||||
|
---
|
||||||
|
title: 集合配置
|
||||||
|
createTime: 2025/09/28 14:00:06
|
||||||
|
permalink: /config/collections/
|
||||||
|
---
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
**Collections(集合)** 是主题中用于组织和管理文档的核心概念。每个集合指向源目录下的特定文件夹,将其中的所有 Markdown 文件作为一个逻辑单元进行管理。
|
||||||
|
|
||||||
|
通过灵活的集合配置,您可以轻松构建多种内容体系:
|
||||||
|
|
||||||
|
- **博客** - 个人随笔与技术分享
|
||||||
|
- **专栏** - 专题系列文章
|
||||||
|
- **使用手册** - 产品使用文档
|
||||||
|
- **笔记** - 学习笔记与知识整理
|
||||||
|
- **产品文档** - 完整的项目文档
|
||||||
|
- **知识库** - 团队知识管理体系
|
||||||
|
|
||||||
|
集合主要分为两种类型,适应不同的内容组织需求:
|
||||||
|
|
||||||
|
- **`post` 类型**:适用于碎片化内容,文章间关联较弱,如博客、专栏等
|
||||||
|
- **`doc` 类型**:适用于结构化文档,内容关联紧密,如使用手册、产品文档、知识库等
|
||||||
|
|
||||||
|
::: tip 配置位置
|
||||||
|
集合配置支持在 `.vuepress/config.ts` 或独立的 `plume.config.ts` 文件中进行配置。
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 基础配置
|
||||||
|
|
||||||
|
假设您的项目采用以下目录结构:
|
||||||
|
|
||||||
|
::: file-tree title="项目结构"
|
||||||
|
|
||||||
|
- docs
|
||||||
|
- **blog**
|
||||||
|
- post-1.md
|
||||||
|
- post-2.md
|
||||||
|
- **typescript**
|
||||||
|
- basic
|
||||||
|
- intro.md
|
||||||
|
- variable.md
|
||||||
|
- types.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
对应的集合配置示例如下:
|
||||||
|
|
||||||
|
::: code-tabs#configs
|
||||||
|
|
||||||
|
@tab .vuepress/config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
// 集合配置 // [!code focus:7]
|
||||||
|
collections: [
|
||||||
|
// 注册 post 类型集合,实现博客功能
|
||||||
|
{ type: 'post', dir: 'blog', title: '博客' },
|
||||||
|
// 注册 doc 类型集合,实现 TypeScript 文档功能
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
@tab .vuepress/plume.config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
// 独立配置文件中的集合配置 // [!code focus:7]
|
||||||
|
collections: [
|
||||||
|
{ type: 'post', dir: 'blog', title: '博客' },
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 多语言配置
|
||||||
|
|
||||||
|
对于多语言项目,您可以在 `locales` 字段中为每种语言单独配置集合:
|
||||||
|
|
||||||
|
::: file-tree title="多语言项目结构"
|
||||||
|
|
||||||
|
- docs
|
||||||
|
- **blog/**
|
||||||
|
- post-1.md
|
||||||
|
- post-2.md
|
||||||
|
- **typescript/**
|
||||||
|
- basic
|
||||||
|
- intro.md
|
||||||
|
- variable.md
|
||||||
|
- types.md
|
||||||
|
- en
|
||||||
|
- **blog/**
|
||||||
|
- post-1.md
|
||||||
|
- post-2.md
|
||||||
|
- **typescript/**
|
||||||
|
- basic
|
||||||
|
- intro.md
|
||||||
|
- variable.md
|
||||||
|
- types.md
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: code-tabs#configs
|
||||||
|
|
||||||
|
@tab .vuepress/config.ts
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
locales: {
|
||||||
|
'/': {
|
||||||
|
// 中文集合配置 // [!code focus:4]
|
||||||
|
collections: [
|
||||||
|
{ type: 'post', dir: 'blog', title: '博客' },
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'/en/': {
|
||||||
|
// 英文集合配置 // [!code focus:4]
|
||||||
|
collections: [
|
||||||
|
{ type: 'post', dir: 'blog', title: 'Blog' },
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript Note', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
@tab .vuepress/plume.config.ts
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
locales: {
|
||||||
|
'/': {
|
||||||
|
// 中文集合配置 // [!code focus:4]
|
||||||
|
collections: [
|
||||||
|
{ type: 'post', dir: 'blog', title: '博客' },
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'/en/': {
|
||||||
|
// 英文集合配置 // [!code focus:4]
|
||||||
|
collections: [
|
||||||
|
{ type: 'post', dir: 'blog', title: 'Blog' },
|
||||||
|
{ type: 'doc', dir: 'typescript', title: 'TypeScript Note', sidebar: 'auto' }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Post 集合详解
|
||||||
|
|
||||||
|
Post 集合专为博客、专栏等碎片化内容设计,提供完整的文章管理体系:
|
||||||
|
|
||||||
|
### 核心功能
|
||||||
|
|
||||||
|
- **文章列表页** - 支持文章置顶、封面图、摘要显示、个人信息等
|
||||||
|
- **文章分类页** - 基于目录结构自动生成分类
|
||||||
|
- **文章标签页** - 灵活的标签管理
|
||||||
|
- **文章归档页** - 按时间维度组织内容
|
||||||
|
|
||||||
|
### 配置示例
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
collections: [
|
||||||
|
// 博客集合配置
|
||||||
|
{
|
||||||
|
type: 'post',
|
||||||
|
dir: 'blog',
|
||||||
|
title: '博客',
|
||||||
|
link: '/blog/', // 列表页链接
|
||||||
|
linkPrefix: '/article/', // 文章链接前缀
|
||||||
|
postCover: 'top', // 封面图位置
|
||||||
|
autoFrontmatter: { permalink: true }, // 自动 frontmatter
|
||||||
|
},
|
||||||
|
// 面试专栏配置
|
||||||
|
{
|
||||||
|
type: 'post',
|
||||||
|
dir: 'interview',
|
||||||
|
title: '面试专栏',
|
||||||
|
link: '/interview/', // 列表页链接
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Doc 集合详解
|
||||||
|
|
||||||
|
Doc 集合适用于结构化文档,强调内容间的逻辑关系:
|
||||||
|
|
||||||
|
### 核心功能
|
||||||
|
|
||||||
|
- **侧边导航栏** - 提供清晰的文档结构导航
|
||||||
|
- **自动生成目录** - 基于文件结构智能生成侧边栏
|
||||||
|
- **多级嵌套支持** - 支持复杂的文档层次结构
|
||||||
|
|
||||||
|
### 配置示例
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
collections: [
|
||||||
|
// TypeScript 笔记 - 自动生成侧边栏
|
||||||
|
{
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'typescript',
|
||||||
|
title: 'TypeScript笔记',
|
||||||
|
sidebar: 'auto'
|
||||||
|
},
|
||||||
|
// Python 笔记 - 手动配置侧边栏
|
||||||
|
{
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'python',
|
||||||
|
title: 'Python 笔记',
|
||||||
|
sidebar: [
|
||||||
|
{ text: '基础语法', link: 'basic' },
|
||||||
|
{
|
||||||
|
text: 'API 文档',
|
||||||
|
items: [
|
||||||
|
{ text: 'asyncio', link: 'asyncio' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'advanced' // 简写形式
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置类型声明
|
||||||
|
|
||||||
|
### 基础集合配置
|
||||||
|
|
||||||
|
```ts
|
||||||
|
/* 集合配置数组 */
|
||||||
|
type ThemeCollections = ThemeCollectionItem[]
|
||||||
|
|
||||||
|
/* 单个集合项 */
|
||||||
|
type ThemeCollectionItem = ThemePostCollection | ThemeDocCollection
|
||||||
|
|
||||||
|
/* 集合公共配置 */
|
||||||
|
interface ThemeBaseCollection {
|
||||||
|
/**
|
||||||
|
* 集合类型
|
||||||
|
* - `post`: 文章列表(博客、专栏)
|
||||||
|
* - `doc`: 结构化文档(笔记、知识库)
|
||||||
|
*/
|
||||||
|
type: 'post' | 'doc'
|
||||||
|
/**
|
||||||
|
* 文档目录(相对于源目录)
|
||||||
|
*/
|
||||||
|
dir: string
|
||||||
|
/**
|
||||||
|
* 文章链接前缀
|
||||||
|
*/
|
||||||
|
linkPrefix?: string
|
||||||
|
/**
|
||||||
|
* 集合标题(用于面包屑导航)
|
||||||
|
*/
|
||||||
|
title: string
|
||||||
|
/**
|
||||||
|
* 标签颜色主题
|
||||||
|
* @default 'colored'
|
||||||
|
*/
|
||||||
|
tagsTheme?: 'colored' | 'gray' | 'brand'
|
||||||
|
/**
|
||||||
|
* 自动生成 frontmatter
|
||||||
|
*/
|
||||||
|
autoFrontmatter?: AutoFrontmatterOptions | false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Post 集合专用配置
|
||||||
|
|
||||||
|
```ts title="Post 集合配置"
|
||||||
|
interface ThemePostCollection extends ThemeBaseCollection {
|
||||||
|
type: 'post'
|
||||||
|
/**
|
||||||
|
* 包含文件规则(glob 模式)
|
||||||
|
* @default ['**\/*.md']
|
||||||
|
*/
|
||||||
|
include?: string[]
|
||||||
|
/**
|
||||||
|
* 排除文件规则(glob 模式)
|
||||||
|
* @default []
|
||||||
|
*/
|
||||||
|
exclude?: string[]
|
||||||
|
/**
|
||||||
|
* 分页配置
|
||||||
|
*/
|
||||||
|
pagination?: false | number | {
|
||||||
|
/**
|
||||||
|
* 每页文章数量
|
||||||
|
* @default 15
|
||||||
|
*/
|
||||||
|
perPage?: number
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 文章列表页链接
|
||||||
|
* @default '/{dir}/'
|
||||||
|
*/
|
||||||
|
link?: string
|
||||||
|
/**
|
||||||
|
* 是否启用文章列表页
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
postList?: boolean
|
||||||
|
/**
|
||||||
|
* 是否启用标签页
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
tags?: boolean
|
||||||
|
/**
|
||||||
|
* 标签页链接
|
||||||
|
* @default '/{link}/tags/'
|
||||||
|
*/
|
||||||
|
tagsLink?: string
|
||||||
|
/**
|
||||||
|
* 标签页文本
|
||||||
|
*/
|
||||||
|
tagsText?: string
|
||||||
|
/**
|
||||||
|
* 是否启用归档页
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
archives?: boolean
|
||||||
|
/**
|
||||||
|
* 归档页链接
|
||||||
|
* @default '/{link}/archives/'
|
||||||
|
*/
|
||||||
|
archivesLink?: string
|
||||||
|
/**
|
||||||
|
* 归档页文本
|
||||||
|
*/
|
||||||
|
archivesText?: string
|
||||||
|
/**
|
||||||
|
* 是否启用分类功能
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
categories?: boolean
|
||||||
|
/**
|
||||||
|
* 分类页链接
|
||||||
|
* @default '/{link}/categories/'
|
||||||
|
*/
|
||||||
|
categoriesLink?: string
|
||||||
|
/**
|
||||||
|
* 分类页文本
|
||||||
|
*/
|
||||||
|
categoriesText?: string
|
||||||
|
/**
|
||||||
|
* 分类展开深度
|
||||||
|
* @default 'deep'
|
||||||
|
*/
|
||||||
|
categoriesExpand?: number | 'deep'
|
||||||
|
/**
|
||||||
|
* 分类列表转换函数
|
||||||
|
*/
|
||||||
|
categoriesTransform?: (categories: PostsCategoryItem[]) => PostsCategoryItem[]
|
||||||
|
/**
|
||||||
|
* 文章封面图配置
|
||||||
|
* @default 'right'
|
||||||
|
*/
|
||||||
|
postCover?: PostsCoverLayout | PostsCoverStyle
|
||||||
|
/**
|
||||||
|
* 个人信息配置
|
||||||
|
*/
|
||||||
|
profile?: ProfileOptions | false
|
||||||
|
/**
|
||||||
|
* 社交账号配置
|
||||||
|
*/
|
||||||
|
social?: SocialLink[] | false
|
||||||
|
}
|
||||||
|
/* 文章分类项 */
|
||||||
|
interface PostsCategoryItem {
|
||||||
|
id: string
|
||||||
|
sort: number
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
/* 封面图布局 */
|
||||||
|
type PostsCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'
|
||||||
|
/* 封面图样式 */
|
||||||
|
interface PostsCoverStyle {
|
||||||
|
layout?: PostsCoverLayout
|
||||||
|
ratio?: number | `${number}:${number}` | `${number}/${number}`
|
||||||
|
width?: number
|
||||||
|
compact?: boolean
|
||||||
|
}
|
||||||
|
/* 社交链接图标 */
|
||||||
|
type SocialLinkIcon = SocialLinkIconUnion | { svg: string, name?: string }
|
||||||
|
/* 社交链接 */
|
||||||
|
interface SocialLink {
|
||||||
|
icon: SocialLinkIcon
|
||||||
|
link: string
|
||||||
|
ariaLabel?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 个人资料
|
||||||
|
*/
|
||||||
|
export interface ProfileOptions {
|
||||||
|
/**
|
||||||
|
* 头像链接地址
|
||||||
|
*/
|
||||||
|
avatar?: string
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
name?: string
|
||||||
|
/**
|
||||||
|
* 描述 / 简介 / 座右铭 / 签名
|
||||||
|
*/
|
||||||
|
description?: string
|
||||||
|
/**
|
||||||
|
* 是否显示为圆形头像
|
||||||
|
*/
|
||||||
|
circle?: boolean
|
||||||
|
/**
|
||||||
|
* 地理位置
|
||||||
|
*/
|
||||||
|
location?: string
|
||||||
|
/**
|
||||||
|
* 组织,公司
|
||||||
|
*/
|
||||||
|
organization?: string
|
||||||
|
/**
|
||||||
|
* 布局位置,左侧或者右侧
|
||||||
|
* @default 'right'
|
||||||
|
*/
|
||||||
|
layout?: 'left' | 'right'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Doc 集合专用配置
|
||||||
|
|
||||||
|
```ts title="Doc 集合配置"
|
||||||
|
interface ThemeDocCollection extends ThemeBaseCollection {
|
||||||
|
type: 'doc'
|
||||||
|
/**
|
||||||
|
* 侧边栏配置
|
||||||
|
*/
|
||||||
|
sidebar?: 'auto' | (string | ThemeSidebarItem)[]
|
||||||
|
/**
|
||||||
|
* 是否显示侧边栏滚动条
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
sidebarScrollbar?: boolean
|
||||||
|
/**
|
||||||
|
* 侧边栏默认折叠状态
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
sidebarCollapsed?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 侧边栏项配置 */
|
||||||
|
interface ThemeSidebarItem {
|
||||||
|
text?: string
|
||||||
|
link?: string
|
||||||
|
icon?: ThemeIcon
|
||||||
|
badge?: string | ThemeBadge
|
||||||
|
items?: 'auto' | (string | ThemeSidebarItem)[]
|
||||||
|
collapsed?: boolean
|
||||||
|
prefix?: string
|
||||||
|
rel?: string
|
||||||
|
target?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图标类型 */
|
||||||
|
type ThemeIcon = string | { svg: string }
|
||||||
|
|
||||||
|
/* 徽章配置 */
|
||||||
|
export interface ThemeBadge {
|
||||||
|
text?: string
|
||||||
|
type?: string
|
||||||
|
color?: string
|
||||||
|
bgColor?: string
|
||||||
|
borderColor?: string
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自动侧边栏生成
|
||||||
|
|
||||||
|
将 Doc 集合的 `sidebar` 设置为 `'auto'` 时,系统会根据目录结构自动生成侧边栏导航。排序规则遵循[文件夹命名约定](../guide/quick-start/write.md#文件夹命名约定)。
|
||||||
|
|
||||||
|
### 侧边栏图标配置
|
||||||
|
|
||||||
|
主题支持两种方式配置侧边栏图标:
|
||||||
|
|
||||||
|
- **在侧边栏配置中直接定义**:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
sidebar: [
|
||||||
|
{ text: '介绍', link: 'intro', icon: 'mdi:tooltip-text-outline' }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **在文档 frontmatter 中定义**:
|
||||||
|
|
||||||
|
```md
|
||||||
|
---
|
||||||
|
title: 主题介绍
|
||||||
|
icon: mdi:tooltip-text-outline
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
两种方式具有相同的效果,您可以根据具体场景选择使用。
|
||||||
|
|
||||||
|
如需了解侧边栏的完整配置选项和使用技巧,请参阅[侧边栏配置指南](../guide/quick-start/sidebar.md)。
|
||||||
173
docs/config/intro.md
Normal file
173
docs/config/intro.md
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
---
|
||||||
|
title: 配置说明
|
||||||
|
createTime: 2024/03/02 10:48:14
|
||||||
|
permalink: /config/intro/
|
||||||
|
---
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
==vuepress-theme-plume== 是基于 [VuePress](https://v2.vuepress.vuejs.org/) 开发的主题,其配置完全遵循 VuePress 的配置规范。
|
||||||
|
|
||||||
|
**VuePress 提供三种配置类型:**
|
||||||
|
|
||||||
|
- **站点配置**:在配置文件(如 `.vuepress/config.ts`)中直接导出的对象
|
||||||
|
- **主题配置**:传递给 `plumeTheme()` 函数的参数对象
|
||||||
|
- **页面配置**:基于 YAML 语法在页面 Frontmatter 中定义
|
||||||
|
|
||||||
|
## VuePress 配置文件
|
||||||
|
|
||||||
|
VuePress 的基础配置文件通常是 `.vuepress/config.js`,同时也支持 TypeScript 配置文件。使用 `.vuepress/config.ts` 可以获得更完善的类型提示。
|
||||||
|
|
||||||
|
VuePress 按以下优先顺序解析配置文件:
|
||||||
|
|
||||||
|
**当前工作目录 (cwd) 下:**
|
||||||
|
|
||||||
|
- `vuepress.config.ts`
|
||||||
|
- `vuepress.config.js`
|
||||||
|
- `vuepress.config.mjs`
|
||||||
|
|
||||||
|
**源文件目录 (sourceDir) 下:**
|
||||||
|
|
||||||
|
- `.vuepress/config.ts` <Badge type="tip" text="推荐使用" />
|
||||||
|
- `.vuepress/config.js`
|
||||||
|
- `.vuepress/config.mjs`
|
||||||
|
|
||||||
|
**基础配置示例:**
|
||||||
|
|
||||||
|
```ts title=".vuepress/config.ts" twoslash
|
||||||
|
import { viteBundler } from '@vuepress/bundler-vite'
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
// [!code hl:5]
|
||||||
|
// VuePress 基础配置
|
||||||
|
lang: 'zh-CN',
|
||||||
|
title: '你好, VuePress !',
|
||||||
|
description: '这是我的第一个 VuePress 站点',
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// 使用 Vite 作为构建工具
|
||||||
|
bundler: viteBundler(),
|
||||||
|
|
||||||
|
// 启用 Plume 主题
|
||||||
|
theme: plumeTheme({ // [!code ++:4]
|
||||||
|
// 主题配置项
|
||||||
|
// ...
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 主题配置文件
|
||||||
|
|
||||||
|
通常我们在 `.vuepress/config.ts` 中配置主题:
|
||||||
|
|
||||||
|
```ts title=".vuepress/config.ts" twoslash
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
// 主题配置
|
||||||
|
}),
|
||||||
|
// ...
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
然而,修改此文件会导致 VuePress 服务重启并全量刷新。对于小型站点,这个过程很快;但对于内容较多的站点,每次重启都需要较长时间。
|
||||||
|
|
||||||
|
频繁修改配置文件还容易导致 VuePress ==服务崩溃=={.caution} ::twemoji:angry-face::,需要手动重启服务,严重影响内容编写效率。
|
||||||
|
|
||||||
|
**解决方案:主题热更新配置**:
|
||||||
|
|
||||||
|
主题提供了 `plume.config.ts` 配置文件,==对该文件的修改支持热更新,无需重启服务=={.tip} ::twemoji:confetti-ball::。
|
||||||
|
|
||||||
|
你可以在其中配置支持热更新的字段,如 `navbar`、`profile` 等。
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
这些字段仍可在 VuePress 配置文件的 `theme` 中配置,但主题配置文件的设置最终会合并到主配置中。
|
||||||
|
|
||||||
|
为避免数据重复,请勿在两地同时配置同一字段。
|
||||||
|
:::
|
||||||
|
|
||||||
|
::: details 什么是热更新?
|
||||||
|
|
||||||
|
**热更新** 是一种开发技术,在 VuePress 中体现为:
|
||||||
|
|
||||||
|
- 配置修改实时生效,无需重启服务,浏览器不刷新页面
|
||||||
|
- 页面修改实时生效,浏览器无刷新更新内容
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 配置方法
|
||||||
|
|
||||||
|
在 VuePress 配置文件同级目录下创建 `plume.config.ts` 文件:
|
||||||
|
|
||||||
|
::: file-tree
|
||||||
|
|
||||||
|
- docs
|
||||||
|
- .vuepress
|
||||||
|
- config.ts
|
||||||
|
- **plume.config.ts**
|
||||||
|
:::
|
||||||
|
|
||||||
|
```ts title="plume.config.ts" twoslash
|
||||||
|
// @filename: ./navbar.ts
|
||||||
|
export default []
|
||||||
|
// ---cut---
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
import navbar from './navbar'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
// 主题配置
|
||||||
|
profile: {
|
||||||
|
name: 'Your name',
|
||||||
|
},
|
||||||
|
navbar,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
`defineThemeConfig(config)` 函数提供完整的类型提示。除 `plugins` 外,大多数配置都可在此文件中定义。
|
||||||
|
|
||||||
|
::: warning 注意事项
|
||||||
|
|
||||||
|
- 主题配置文件仅支持部分热更新字段
|
||||||
|
- 避免在 VuePress 配置文件中重复配置已在主题配置文件中设置的字段
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 自定义配置文件路径
|
||||||
|
|
||||||
|
如需使用非默认路径,可在 VuePress 配置中指定:
|
||||||
|
|
||||||
|
```ts title=".vuepress/config.ts" twoslash
|
||||||
|
import path from 'node:path'
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
// 自定义配置文件路径
|
||||||
|
configFile: path.join(__dirname, 'custom/config.ts'), // [!code ++]
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
::: warning 新手不建议自定义路径,可能引发意外问题
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 页面配置
|
||||||
|
|
||||||
|
通过页面顶部的 YAML Frontmatter,可为每个页面单独配置主题:
|
||||||
|
|
||||||
|
```md {1,5} title="article.md"
|
||||||
|
---
|
||||||
|
title: 文章标题
|
||||||
|
createTime: 2024/09/08 22:53:34
|
||||||
|
permalink: /article/xxx/
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
在 Markdown 文件顶部,使用 `---` 分隔符包裹的部分即为 Frontmatter,采用 YAML 语法配置。
|
||||||
|
|
||||||
|
:::tip 如需了解 YAML 基础语法,可参考[这篇博客](/article/ecxnxxd0/)
|
||||||
|
:::
|
||||||
@ -19,6 +19,7 @@ permalink: /config/locales/
|
|||||||
- 德语 (`de-DE`) - `/de/`
|
- 德语 (`de-DE`) - `/de/`
|
||||||
- 俄语 (`ru-RU`) - `/ru/`
|
- 俄语 (`ru-RU`) - `/ru/`
|
||||||
- 日语 (`ja-JP`) - `/ja/`
|
- 日语 (`ja-JP`) - `/ja/`
|
||||||
|
- 韩语 (`ko-KR`) - `/ko/`
|
||||||
|
|
||||||
## 配置
|
## 配置
|
||||||
|
|
||||||
@ -110,14 +111,14 @@ export default defineThemeConfig({
|
|||||||
- 主题默认导航栏中的首页链接的文本。
|
- 主题默认导航栏中的首页链接的文本。
|
||||||
- 面包屑导航中的首页链接的文本。
|
- 面包屑导航中的首页链接的文本。
|
||||||
|
|
||||||
### blogText
|
### postsText
|
||||||
|
|
||||||
- 类型: `string`
|
- 类型: `string`
|
||||||
- 默认值: `'Blog'`
|
- 默认值: `'Posts'`
|
||||||
- 详情: 博客链接的文本。
|
- 详情: 文章列表页链接的文本。
|
||||||
|
|
||||||
- 主题默认导航栏中的博客链接的文本。
|
- 主题默认导航栏中的文章列表页链接的文本。
|
||||||
- 面包屑导航中的博客链接的文本。
|
- 面包屑导航中的文章列表页链接的文本。
|
||||||
|
|
||||||
### tagText
|
### tagText
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ permalink: /config/navigation/
|
|||||||
::: tip 导航栏配置支持在 `.vuepress/config.ts` ,或者在 `plume.config.ts` 中进行配置。
|
::: tip 导航栏配置支持在 `.vuepress/config.ts` ,或者在 `plume.config.ts` 中进行配置。
|
||||||
:::
|
:::
|
||||||
|
|
||||||
主题默认会自动生成最简单的导航栏配置,仅包括 **首页** 和 **博客文章列表页** 。
|
主题默认会自动生成最简单的导航栏配置,仅包括 **首页** 和 **文章列表页** 。
|
||||||
|
|
||||||
你也可以自己配置导航栏,覆盖默认的的导航栏配置。
|
你也可以自己配置导航栏,覆盖默认的的导航栏配置。
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ export default defineUserConfig({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
随着站点内容变得越来越丰富,包括了 博客文章列表、notes、友情链接、 外部链接等等,
|
随着站点内容变得越来越丰富,如通过 集合 配置了 博客、笔记、文档、友情链接、 外部链接等等,
|
||||||
默认生成的导航栏配置满足不了您的需求。
|
默认生成的导航栏配置满足不了您的需求。
|
||||||
|
|
||||||
这时候,您可以通过 `navbar` 字段来完全自定义导航栏,它将直接覆盖默认的导航栏配置。
|
这时候,您可以通过 `navbar` 字段来完全自定义导航栏,它将直接覆盖默认的导航栏配置。
|
||||||
115
docs/config/sidebar.md
Normal file
115
docs/config/sidebar.md
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
title: 侧边栏配置
|
||||||
|
createTime: 2024/08/15 21:05:36
|
||||||
|
permalink: /config/sidebar/
|
||||||
|
---
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
侧边栏是主题中位于页面最左侧的核心导航区域,承担着引导用户在不同页面间跳转的重要功能。
|
||||||
|
|
||||||
|
在 VuePress 生态中,默认主题 `@vuepress/theme-default` 通过 `sidebar` 配置项管理侧边栏。本主题在保留这一经典配置方式的基础上,还提供了更为灵活的集合(Collections)级侧边栏配置方案。
|
||||||
|
|
||||||
|
## 集合级侧边栏配置
|
||||||
|
|
||||||
|
集合(Collections)是主题中组织系列文档的核心概念。当集合类型设置为 `doc` 时,您可以在 `collection.sidebar` 中定义专属的侧边栏导航。
|
||||||
|
|
||||||
|
以下示例展示了如何在 `docs` 目录下创建类型为 `doc` 的集合,并配置其侧边栏:
|
||||||
|
|
||||||
|
::: code-tabs#configs
|
||||||
|
|
||||||
|
@tab .vuepress/config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { defineCollection, plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
// 定义文档集合配置 // [!code hl:10]
|
||||||
|
const demo = defineCollection({
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'demo', // 文档目录
|
||||||
|
title: 'Demo', // 集合名称
|
||||||
|
sidebar: [ // 侧边栏配置 // [!code ++:4]
|
||||||
|
{ text: 'one item', link: 'one' },
|
||||||
|
{ text: 'two item', link: 'two' },
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
collections: [demo], // 注册集合 // [!code hl]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
@tab .vuepress/plume.config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineCollection, defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
// 使用独立配置文件定义集合 // [!code hl:10]
|
||||||
|
const demo = defineCollection({
|
||||||
|
type: 'doc',
|
||||||
|
dir: 'demo',
|
||||||
|
title: 'Demo',
|
||||||
|
sidebar: [
|
||||||
|
{ text: 'one item', link: 'one' },
|
||||||
|
{ text: 'two item', link: 'two' },
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
collections: [demo], // [!code hl]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
主题提供的 `defineCollection` 工具函数简化了集合配置过程。如需了解完整的集合配置选项,请参阅[集合配置文档](./collections.md)。
|
||||||
|
|
||||||
|
## 全局侧边栏配置
|
||||||
|
|
||||||
|
如果您希望采用传统的全局配置方式管理侧边栏,可以直接在主题配置中使用 `sidebar` 选项。这种方式适合不需要按集合分组导航的场景。
|
||||||
|
|
||||||
|
::: code-tabs#configs
|
||||||
|
|
||||||
|
@tab .vuepress/config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineUserConfig } from 'vuepress'
|
||||||
|
import { plumeTheme } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineUserConfig({
|
||||||
|
theme: plumeTheme({
|
||||||
|
// 全局侧边栏配置 // [!code hl:7]
|
||||||
|
sidebar: {
|
||||||
|
'/config/': [ // 匹配/config/路径
|
||||||
|
{ text: '侧边栏配置', link: 'sidebar-1' },
|
||||||
|
{ text: '侧边栏配置', link: 'sidebar-2' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
@tab .vuepress/plume.config.ts
|
||||||
|
|
||||||
|
```ts twoslash
|
||||||
|
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||||
|
|
||||||
|
export default defineThemeConfig({
|
||||||
|
// 在独立配置文件中定义全局侧边栏 // [!code hl:7]
|
||||||
|
sidebar: {
|
||||||
|
'/config/': [
|
||||||
|
{ text: '侧边栏配置', link: 'sidebar-1' },
|
||||||
|
{ text: '侧边栏配置', link: 'sidebar-2' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
两种配置方式各有优势:集合级配置适合模块化文档结构,全局配置则便于统一管理简单项目的导航。
|
||||||
|
|
||||||
|
如需了解侧边栏的完整配置选项和使用技巧,请参阅[侧边栏配置指南](../guide/quick-start/sidebar.md)。
|
||||||
@ -177,165 +177,6 @@ export default defineThemeConfig({
|
|||||||
::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。
|
::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。
|
||||||
:::
|
:::
|
||||||
|
|
||||||
### blog
|
|
||||||
|
|
||||||
- **类型:** `false | BlogOptions`
|
|
||||||
- **默认值:** `{ link: '/blog/', include: ['**/*.md'], exclude: [] }`
|
|
||||||
- **详情:**
|
|
||||||
|
|
||||||
博客配置。
|
|
||||||
|
|
||||||
::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。
|
|
||||||
:::
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface BlogOptions {
|
|
||||||
/**
|
|
||||||
* blog list link
|
|
||||||
*
|
|
||||||
* @default '/blog/'
|
|
||||||
*/
|
|
||||||
link?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在 `{sourceDir}` 目录中,通过 glob string 配置包含文件
|
|
||||||
*
|
|
||||||
* @default - ['**\*.md']
|
|
||||||
*/
|
|
||||||
include?: string[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在 `{sourceDir}` 目录中,通过 glob string 配置排除的文件
|
|
||||||
*
|
|
||||||
* @default - ['.vuepress/', 'node_modules/']
|
|
||||||
*/
|
|
||||||
exclude?: string[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页配置
|
|
||||||
*
|
|
||||||
* - `false` - 不启用分页
|
|
||||||
* - `number` - 每页显示的文章数量
|
|
||||||
*/
|
|
||||||
pagination?: false | number | {
|
|
||||||
/**
|
|
||||||
* 每页显示的文章数量
|
|
||||||
* @default 10
|
|
||||||
*/
|
|
||||||
perPage?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否启用标签页
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
tags?: boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义标签页链接
|
|
||||||
*
|
|
||||||
* @default '/blog/tags/'
|
|
||||||
*/
|
|
||||||
tagsLink?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标签颜色主题
|
|
||||||
*
|
|
||||||
* - `colored`: 彩色标签,不同标签颜色不同
|
|
||||||
* - `brand`: 使用主题颜色作为标签颜色
|
|
||||||
* - `gray`: 使用 灰色 作为标签颜色
|
|
||||||
*
|
|
||||||
* @default 'colored'
|
|
||||||
*/
|
|
||||||
tagsTheme?: 'colored' | 'gray' | 'brand'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否启用归档页
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
archives?: boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义归档页链接
|
|
||||||
*
|
|
||||||
* @default '/blog/archives/'
|
|
||||||
*/
|
|
||||||
archivesLink?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否启用分类页
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
categories?: boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义分类页链接
|
|
||||||
*
|
|
||||||
* @default '/blog/categories/'
|
|
||||||
*/
|
|
||||||
categoriesLink?: string
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分类页展开深度
|
|
||||||
*
|
|
||||||
* @default 'deep'
|
|
||||||
*/
|
|
||||||
categoriesExpand?: number | 'deep'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 文章分类列表转换函数,比如排除不需要的一级分类
|
|
||||||
* @param categories 分类列表
|
|
||||||
* @returns 返回一个新的分类列表
|
|
||||||
*/
|
|
||||||
categoriesTransform?: (categories: PageCategoryData[]) => PageCategoryData[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 博客文章封面图
|
|
||||||
*
|
|
||||||
* 配置封面图的位置,支持 `'left'`、`'right'`、`'top'`、`'top-inside'`
|
|
||||||
*
|
|
||||||
* @default 'right'
|
|
||||||
*/
|
|
||||||
postCover?: BlogPostCoverLayout | BlogPostCoverStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
type BlogPostCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'
|
|
||||||
|
|
||||||
interface BlogPostCoverStyle {
|
|
||||||
/**
|
|
||||||
* 博客文章封面图的位置
|
|
||||||
*/
|
|
||||||
layout?: BlogPostCoverLayout
|
|
||||||
/**
|
|
||||||
* 博客文章封面图的比例
|
|
||||||
*
|
|
||||||
* @default '4:3'
|
|
||||||
*/
|
|
||||||
ratio?: number | `${number}:${number}`
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 封面图的宽度, 仅在 layout 为 'left' 或 'right' 时生效
|
|
||||||
*
|
|
||||||
* @default 240
|
|
||||||
*/
|
|
||||||
width?: number
|
|
||||||
/**
|
|
||||||
* 是否使用紧凑模式,紧凑模式下,封面图紧贴容器边缘
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
compact?: boolean
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### article
|
|
||||||
|
|
||||||
- **类型:** `string`
|
|
||||||
- **默认值:** `/article/`
|
|
||||||
- **详情:** 文章链接前缀
|
|
||||||
|
|
||||||
::: warning 该字段不支持在 [主题配置文件 `plume.config.js`](./intro.md#主题配置文件) 中进行配置。
|
|
||||||
:::
|
|
||||||
|
|
||||||
### autoFrontmatter
|
### autoFrontmatter
|
||||||
|
|
||||||
- **类型:** `false | AutoFrontmatterOptions`
|
- **类型:** `false | AutoFrontmatterOptions`
|
||||||
@ -345,18 +186,6 @@ interface BlogPostCoverStyle {
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
interface AutoFrontmatterOptions {
|
interface AutoFrontmatterOptions {
|
||||||
/**
|
|
||||||
* glob 匹配,被匹配的文件将会自动生成 frontmatter
|
|
||||||
*
|
|
||||||
* @default ['**\/*.md']
|
|
||||||
*/
|
|
||||||
include?: string | string[]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* glob 匹配,被匹配的文件将不会自动生成 frontmatter
|
|
||||||
*/
|
|
||||||
exclude?: string | string[]
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否自动生成 permalink
|
* 是否自动生成 permalink
|
||||||
*
|
*
|
||||||
@ -714,27 +543,13 @@ type NavItem = string | {
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
### notes
|
|
||||||
|
|
||||||
- **类型:** `false | NotesOptions`
|
|
||||||
- **默认值:** `{ link: '/note', dir: 'notes', notes: [] }`
|
|
||||||
- **详情:**
|
|
||||||
|
|
||||||
笔记配置, 笔记中的文章默认不会出现在首页文章列表
|
|
||||||
|
|
||||||
你可以将配置的notes 配置到 navbar中,以便浏览查看
|
|
||||||
|
|
||||||
详细配置请查看 [此文档](./notes.md)
|
|
||||||
|
|
||||||
### sidebar
|
### sidebar
|
||||||
|
|
||||||
- **类型:** `false | SidebarMulti`
|
- **类型:** `false | SidebarMulti`
|
||||||
|
|
||||||
- **详情:**
|
- **详情:**
|
||||||
|
|
||||||
侧边栏配置。**主题更推荐在 [notes 配置](./notes.md) 中进行侧边栏配置。**
|
侧边栏配置。**主题更推荐在 [collections 配置](./collections.md) 中进行侧边栏配置。**
|
||||||
|
|
||||||
当你不希望使用 `notes` 功能,但又期望给文档增加侧边栏时,可以使用此配置。
|
|
||||||
|
|
||||||
配置对象的 `key` 为侧边栏公共访问路径前缀。
|
配置对象的 `key` 为侧边栏公共访问路径前缀。
|
||||||
|
|
||||||
@ -775,9 +590,7 @@ interface SidebarItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果未指定,组不可折叠。
|
* 如果未指定,组不可折叠。
|
||||||
*
|
|
||||||
* 如果为`true`,组可折叠,并默认折叠。
|
* 如果为`true`,组可折叠,并默认折叠。
|
||||||
*
|
|
||||||
* 如果为`false`,组可折叠,但默认展开。
|
* 如果为`false`,组可折叠,但默认展开。
|
||||||
*/
|
*/
|
||||||
collapsed?: boolean
|
collapsed?: boolean
|
||||||
@ -909,10 +722,10 @@ interface SidebarItem {
|
|||||||
|
|
||||||
### createTime
|
### createTime
|
||||||
|
|
||||||
- **类型:** `boolean | 'only-blog'`
|
- **类型:** `boolean | 'only-posts'`
|
||||||
- **默认值:** `true`
|
- **默认值:** `true`
|
||||||
- **详情:** 是否显示创建时间
|
- **详情:** 是否显示创建时间
|
||||||
|
|
||||||
- `false` - 不显示
|
- `false` - 不显示
|
||||||
- `'only-blog'` - 只显示在博客文章页面
|
- `'only-posts'` - 只显示在文章列表页面
|
||||||
- `true` - 显示在所有文章页面
|
- `true` - 显示在所有文章页面
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user