Merge branch 'main' into migrate-md-enhance
This commit is contained in:
commit
e05634d3f4
@ -2,6 +2,7 @@ import type { PromptResult, ResolvedData } from './types.js'
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { intro, outro, spinner } from '@clack/prompts'
|
||||
import { sleep } from '@pengzhanbo/utils'
|
||||
import { execaCommand } from 'execa'
|
||||
import colors from 'picocolors'
|
||||
import { Mode } from './constants.js'
|
||||
@ -21,6 +22,10 @@ export async function run(mode: Mode, root?: string) {
|
||||
|
||||
await generate(mode, data)
|
||||
|
||||
// Delay for some time, I/O may not be completed yet,
|
||||
// executing subsequent tasks at this point may cause issues.
|
||||
await sleep(200)
|
||||
|
||||
const cwd = path.join(process.cwd(), data.root)
|
||||
if (data.git) {
|
||||
progress.message(t('spinner.git'))
|
||||
|
||||
@ -23,6 +23,7 @@ jobs:
|
||||
{{#if (equal packageManager "pnpm")}}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
{{/if}}
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@ -36,7 +36,7 @@ const { lightColors, darkColors, css, reset } = useThemeColors()
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<p>复制下方的代码到您的项目中,请参考 <a href="/custom-style/">主题定制</a> </p>
|
||||
<p>复制下方的代码到您的项目中,请参考 <a href="/guide/custom-style/">主题定制</a> </p>
|
||||
<CodeViewer :content="css" lang="css" />
|
||||
</template>
|
||||
|
||||
|
||||
@ -82,6 +82,60 @@ export default defineUserConfig({
|
||||
|
||||
:::
|
||||
|
||||
### 编写notes配置
|
||||
|
||||
由于 `notes` 配置全部写在 `plumeTheme({ })` 中可能会导致 代码层级嵌套过深,因此更推荐使用主题提供的
|
||||
`defineNotesConfig()` 和 `defineNoteConfig()` 将 notes 配置提取到外部,它们还能帮助你获得更好的类型提示,
|
||||
更具可读性和便于维护。
|
||||
|
||||
::: code-tabs
|
||||
|
||||
@tab .vuepress/notes.ts
|
||||
|
||||
```ts
|
||||
import { defineNoteConfig, defineNotesConfig } from 'vuepress-theme-plume'
|
||||
|
||||
/**
|
||||
* 配置 单个 note
|
||||
*/
|
||||
const typescript = defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
'/guide/intro.md',
|
||||
'/guide/getting-start.md',
|
||||
'/config/config-file.md',
|
||||
]
|
||||
})
|
||||
|
||||
/**
|
||||
* 配置 notes
|
||||
*/
|
||||
export default defineNotesConfig({
|
||||
// 声明所有笔记的目录,(默认配置,通常您不需要声明它)
|
||||
dir: '/notes/',
|
||||
link: '/',
|
||||
// 在这里添加 note 配置
|
||||
notes: [typescript] // [!code ++]
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
import notes from './notes' // [!code ++]
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
notes // [!code ++]
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### 侧边栏配置
|
||||
|
||||
以 `typescript` 目录为例,它拥有如下的文件结构:
|
||||
@ -171,21 +225,21 @@ interface SidebarItem {
|
||||
}
|
||||
```
|
||||
|
||||
::: info
|
||||
以下代码块中 `sidebar` 表示传入到 `notes` 中的 `sidebar` 参数。
|
||||
|
||||
这里为了方便演示说明,将其单独使用 `const sidebar: Sidebar = [...]` 进行说明。
|
||||
:::
|
||||
|
||||
当 传入类型为 `string` 时,表示 markdown 文件的路径:
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
'/guide/intro.md',
|
||||
'/guide/getting-start.md',
|
||||
'/config/config-file.md',
|
||||
// ...
|
||||
]
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
'/guide/intro.md',
|
||||
'/guide/getting-start.md',
|
||||
'/config/config-file.md',
|
||||
// ...
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
你也可以省略 `.md` 文件后缀,简写为 `/guide/intro` 。主题会解析 对应的文件,获取 **标题** 和 **页面链接地址**
|
||||
@ -194,32 +248,44 @@ const sidebar: Sidebar = [
|
||||
当传入类型为 `SidebarItem` 时:
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
{ text: '介绍', link: '/guide/intro' },
|
||||
{ text: '快速上手', link: '/guide/getting-start' },
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{ text: '介绍', link: '/guide/intro' },
|
||||
{ text: '快速上手', link: '/guide/getting-start' },
|
||||
// ...
|
||||
]
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
也可以进行多层嵌套:
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide', // 使用 prefix 拼接,可以简写 下面的 items 中的 link 为相对路径
|
||||
items: [
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide', // 使用 prefix 拼接,可以简写 下面的 items 中的 link 为相对路径
|
||||
items: [
|
||||
// 可以混用 string 和 SidebarItem
|
||||
{ text: '介绍', link: 'intro' },
|
||||
'getting-start',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '配置',
|
||||
prefix: '/config',
|
||||
items: 'auto', // items 为 'auto',会根据 prefix 的文件结构自动生成侧边栏
|
||||
},
|
||||
]
|
||||
{ text: '介绍', link: 'intro' },
|
||||
'getting-start',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: '配置',
|
||||
prefix: '/config',
|
||||
items: 'auto', // items 为 'auto',会根据 prefix 的文件结构自动生成侧边栏
|
||||
},
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### 关于 `prefix`
|
||||
@ -230,23 +296,29 @@ const sidebar: Sidebar = [
|
||||
需要注意的是,`items` 中的链接 仅有 相对路径的链接才会与 `prefix` 拼接,而绝对路径则不进行处理。
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
{
|
||||
prefix: '/guide',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/intro
|
||||
'/config/config-file', // 绝对路径,不拼接
|
||||
{
|
||||
text: '博客',
|
||||
link: 'blog', // 相对路径, 最终拼接为 /guide/blog
|
||||
},
|
||||
{
|
||||
text: '配置',
|
||||
link: '/config', // 绝对路径,不拼接
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{
|
||||
prefix: '/guide',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/intro
|
||||
'/config/config-file', // 绝对路径,不拼接
|
||||
{
|
||||
text: '博客',
|
||||
link: 'blog', // 相对路径, 最终拼接为 /guide/blog
|
||||
},
|
||||
{
|
||||
text: '配置',
|
||||
link: '/config', // 绝对路径,不拼接
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
同时,`items` 内还支持 深层嵌套,内部还依然支持 `prefix`,这里也遵循相同的规则,`prefix` 如果是相对路径,
|
||||
@ -254,28 +326,34 @@ const sidebar: Sidebar = [
|
||||
上一层级 `prefix` 拼接。
|
||||
|
||||
```ts
|
||||
const sidebar: sidebar = [
|
||||
{
|
||||
prefix: '/guide',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/intro
|
||||
{
|
||||
prefix: '/config',
|
||||
items: [
|
||||
'config-file', // 相对路径, 最终拼接为 /config/config-file
|
||||
'configuration', // 相对路径, 最终拼接为 /config/configuration
|
||||
]
|
||||
},
|
||||
{
|
||||
prefix: 'blog',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/blog/intro
|
||||
'getting-start', // 相对路径, 最终拼接为 /guide/blog/getting-start
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{
|
||||
prefix: '/guide',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/intro
|
||||
{
|
||||
prefix: '/config',
|
||||
items: [
|
||||
'config-file', // 相对路径, 最终拼接为 /config/config-file
|
||||
'configuration', // 相对路径, 最终拼接为 /config/configuration
|
||||
]
|
||||
},
|
||||
{
|
||||
prefix: 'blog',
|
||||
items: [
|
||||
'intro', // 相对路径, 最终拼接为 /guide/blog/intro
|
||||
'getting-start', // 相对路径, 最终拼接为 /guide/blog/getting-start
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**是否是绝对路径的判断标准是,如果以 `/` 开头,则为绝对路径,否则为相对路径**
|
||||
@ -290,33 +368,45 @@ const sidebar: sidebar = [
|
||||
你可以使用超过 `200k` 的图标,仅需要添加 `icon` 配置即可。
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide',
|
||||
icon: 'ep:guide', // iconify icon name // [!code hl]
|
||||
items: [
|
||||
{ text: '介绍', link: 'intro', icon: 'ph:info-light' }, // [!code hl]
|
||||
],
|
||||
},
|
||||
]
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide',
|
||||
icon: 'ep:guide', // iconify icon name // [!code hl]
|
||||
items: [
|
||||
{ text: '介绍', link: 'intro', icon: 'ph:info-light' }, // [!code hl]
|
||||
],
|
||||
},
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
也可以使用本地图标,或者本地图片:
|
||||
|
||||
```ts
|
||||
const sidebar: Sidebar = [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide',
|
||||
icon: '/images/guide.png', // iconify icon name // [!code hl]
|
||||
items: [
|
||||
{ text: '介绍', link: 'intro', icon: '/images/info.png' }, // [!code hl]
|
||||
// 也可以是一个远程图片
|
||||
{ text: '快速上手', link: 'getting-start', icon: 'https://cn.vuejs.org/images/logo.png' },
|
||||
],
|
||||
},
|
||||
]
|
||||
import { defineNoteConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNoteConfig({
|
||||
dir: 'typescript',
|
||||
link: '/typescript/',
|
||||
sidebar: [
|
||||
{
|
||||
text: '指南',
|
||||
prefix: '/guide',
|
||||
icon: '/images/guide.png', // iconify icon name // [!code hl]
|
||||
items: [
|
||||
{ text: '介绍', link: 'intro', icon: '/images/info.png' }, // [!code hl]
|
||||
// 也可以是一个远程图片
|
||||
{ text: '快速上手', link: 'getting-start', icon: 'https://cn.vuejs.org/images/logo.png' },
|
||||
],
|
||||
},
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**请注意,使用本地图片必须以 `/` 开头,表示为 静态资源路径,它将从 `.vuepress/public/` 目录中加载。**
|
||||
|
||||
@ -20,10 +20,10 @@ permalink: /guide/custom-style/
|
||||
|
||||
@tab .vuepress/client.ts
|
||||
|
||||
```ts {1}
|
||||
```ts
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
import './styles/index.css'
|
||||
import './styles/index.css' // [!code ++]
|
||||
|
||||
export default defineClientConfig({
|
||||
// ...
|
||||
|
||||
@ -179,7 +179,10 @@ function getAllSidebar(localeOptions: PlumeThemeLocaleOptions): Record<string, S
|
||||
for (const [locale, opt] of entries(localeOptions.locales || {})) {
|
||||
const notes = locale === '/' ? (opt.notes || localeOptions.notes) : opt.notes
|
||||
const sidebar = locale === '/' ? (opt.sidebar || localeOptions.sidebar) : opt.sidebar
|
||||
locales[locale] = { ...sidebar }
|
||||
locales[locale] = {}
|
||||
for (const [key, value] of entries(sidebar || {})) {
|
||||
locales[locale][normalizeLink(key)] = value
|
||||
}
|
||||
|
||||
if (notes && notes.notes?.length) {
|
||||
const prefix = notes.link || ''
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user