mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
docs: update en docs (#708)
* docs: update en docs * chore: tweak * chore: tweak * chore: tweak
This commit is contained in:
parent
c6347676cd
commit
385059f214
@ -1,8 +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 enCollections: ThemeCollections = defineCollections([
|
||||
themeGuide,
|
||||
themeConfig,
|
||||
tools,
|
||||
])
|
||||
|
||||
@ -3,27 +3,49 @@ import { defineCollection } from 'vuepress-theme-plume'
|
||||
|
||||
export const themeConfig: ThemeCollectionItem = defineCollection({
|
||||
type: 'doc',
|
||||
dir: 'config',
|
||||
title: 'Config',
|
||||
dir: 'config',
|
||||
linkPrefix: '/config/',
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Config',
|
||||
text: 'Configuration',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'intro',
|
||||
'basic',
|
||||
'theme',
|
||||
'locales',
|
||||
'notes',
|
||||
'navbar',
|
||||
'sidebar',
|
||||
'collections',
|
||||
'markdown',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'frontmatter',
|
||||
text: 'Page Configuration',
|
||||
prefix: 'frontmatter',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'basic',
|
||||
'article',
|
||||
'home',
|
||||
'post',
|
||||
'friend',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Built-in Plugins',
|
||||
prefix: 'plugins',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'',
|
||||
'shiki',
|
||||
'search',
|
||||
'reading-time',
|
||||
'markdown-enhance',
|
||||
'markdown-power',
|
||||
'markdown-image',
|
||||
'markdown-math',
|
||||
'markdown-include',
|
||||
'watermark',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@ -16,10 +16,14 @@ export const themeGuide: ThemeCollectionItem = defineCollection({
|
||||
'intro',
|
||||
'usage',
|
||||
'project-structure',
|
||||
{
|
||||
text: 'Collection',
|
||||
link: 'collection',
|
||||
items: ['collection-post', 'collection-doc'],
|
||||
},
|
||||
'sidebar',
|
||||
'write',
|
||||
// 'blog',
|
||||
// 'document',
|
||||
'international',
|
||||
'locales',
|
||||
'deployment',
|
||||
'optimize-build',
|
||||
],
|
||||
@ -45,15 +49,120 @@ export const themeGuide: ThemeCollectionItem = defineCollection({
|
||||
'card',
|
||||
'steps',
|
||||
'file-tree',
|
||||
'code-tree',
|
||||
'field',
|
||||
'tabs',
|
||||
'timeline',
|
||||
'demo-wrapper',
|
||||
'flex',
|
||||
'collapse',
|
||||
'npm-to',
|
||||
'caniuse',
|
||||
'chat',
|
||||
'include',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'code block',
|
||||
prefix: 'code',
|
||||
icon: 'ph:code-bold',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'intro',
|
||||
'features',
|
||||
'copy-code',
|
||||
'code-tabs',
|
||||
'import',
|
||||
'twoslash',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'code repl',
|
||||
prefix: 'repl',
|
||||
icon: 'carbon:demo',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'frontend',
|
||||
'rust',
|
||||
'golang',
|
||||
'kotlin',
|
||||
'python',
|
||||
'codepen',
|
||||
'jsFiddle',
|
||||
'codeSandbox',
|
||||
'replit',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'charts',
|
||||
icon: 'mdi:chart-line',
|
||||
prefix: 'chart',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'chart',
|
||||
'echarts',
|
||||
'mermaid',
|
||||
'flowchart',
|
||||
'markmap',
|
||||
'plantuml',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'resource embedded',
|
||||
icon: 'dashicons:embed-video',
|
||||
prefix: 'embed',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'pdf',
|
||||
'bilibili',
|
||||
'acfun',
|
||||
'youtube',
|
||||
'artplayer',
|
||||
'audioReader',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Features',
|
||||
icon: 'lucide:box',
|
||||
collapsed: false,
|
||||
prefix: 'features',
|
||||
items: [
|
||||
'icon',
|
||||
'search',
|
||||
'image-preview',
|
||||
'comments',
|
||||
'bulletin',
|
||||
'encryption',
|
||||
'contributors',
|
||||
'changelog',
|
||||
'copyright',
|
||||
'watermark',
|
||||
'friend-links',
|
||||
'replace-assets',
|
||||
'seo',
|
||||
'sitemap',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Component',
|
||||
prefix: 'components',
|
||||
icon: 'uiw:component',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'badge',
|
||||
'icon',
|
||||
'plot',
|
||||
'card',
|
||||
'link-card',
|
||||
'image-card',
|
||||
'card-grid',
|
||||
'card-masonry',
|
||||
'home-box',
|
||||
'repo-card',
|
||||
'npm-badge',
|
||||
'swiper',
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -64,6 +173,18 @@ export const themeGuide: ThemeCollectionItem = defineCollection({
|
||||
items: [
|
||||
'home',
|
||||
'style',
|
||||
'slots',
|
||||
'component-overrides',
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'API',
|
||||
icon: 'mdi:api',
|
||||
prefix: 'api',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'client',
|
||||
'node',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
20
docs/.vuepress/collections/en/tools.ts
Normal file
20
docs/.vuepress/collections/en/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: 'Theme Tools',
|
||||
linkPrefix: '/tools/',
|
||||
sidebar: [
|
||||
{
|
||||
text: 'Tools',
|
||||
icon: 'tabler:tools',
|
||||
items: [
|
||||
'custom-theme',
|
||||
'home-hero-tint-plate',
|
||||
'caniuse',
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
@ -78,11 +78,15 @@ export const enNavbar: ThemeNavItem[] = defineNavbarConfig([
|
||||
text: 'More',
|
||||
icon: 'icon-park-outline:more-three',
|
||||
items: [
|
||||
{ text: 'FAQ', link: '/en/faq/', icon: 'wpf:faq' },
|
||||
{ text: 'Theme Tools', link: '/en/tools/', icon: 'jam:tools' },
|
||||
{ text: 'Friend Links', link: '/en/friends/', icon: 'carbon:friendship' },
|
||||
{
|
||||
text: 'Vuepress',
|
||||
icon: 'logos:vue',
|
||||
items: [
|
||||
{ text: 'Official Docs', link: 'https://v2.vuepress.vuejs.org' },
|
||||
{ text: 'Ecosystem', link: 'https://ecosystem.vuejs.press/' },
|
||||
{ text: 'Official Docs', link: 'https://v2.vuepress.vuejs.org', icon: 'logos:vue' },
|
||||
{ text: 'Ecosystem', link: 'https://ecosystem.vuejs.press/', icon: 'logos:vue' },
|
||||
],
|
||||
},
|
||||
],
|
||||
@ -90,9 +94,10 @@ export const enNavbar: ThemeNavItem[] = defineNavbarConfig([
|
||||
{
|
||||
text: `${version}`,
|
||||
icon: 'codicon:versions',
|
||||
badge: '新',
|
||||
items: [
|
||||
{ text: 'Changelog', link: '/changelog/' },
|
||||
{ text: 'Contributing', link: '/contributing/' },
|
||||
{ text: 'Changelog', link: '/en/changelog/' },
|
||||
{ text: 'Contributing', link: '/en/contributing/' },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
@ -1,11 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import { shallowRef, useId } from 'vue'
|
||||
import type { LocaleConfig } from 'vuepress'
|
||||
import { computed, shallowRef, useId } from 'vue'
|
||||
import { useRouteLocale } from 'vuepress/client'
|
||||
import { useCaniuse, useCaniuseFeaturesSearch, useCaniuseVersionSelect } from '../composables/caniuse.js'
|
||||
import CodeViewer from './CodeViewer.vue'
|
||||
|
||||
const LOCALES: LocaleConfig<
|
||||
Record<'select-feature' | 'placeholder' | 'embed-type' | 'output' | 'browser-version' | 'no-recommend', string>
|
||||
> = {
|
||||
'/': {
|
||||
'select-feature': '选择特性:',
|
||||
'placeholder': '输入特性',
|
||||
'embed-type': '嵌入方式:',
|
||||
'output': '输出:',
|
||||
'browser-version': '浏览器版本:',
|
||||
'no-recommend': '不推荐',
|
||||
},
|
||||
'/en/': {
|
||||
'select-feature': 'Select feature:',
|
||||
'placeholder': 'Input feature',
|
||||
'embed-type': 'Embed type: ',
|
||||
'output': 'Output:',
|
||||
'browser-version': 'Browser version: ',
|
||||
'no-recommend': 'Not recommended',
|
||||
},
|
||||
}
|
||||
|
||||
const listEl = shallowRef<HTMLUListElement | null>(null)
|
||||
const inputEl = shallowRef<HTMLInputElement | null>(null)
|
||||
const id = useId()
|
||||
const routeLocale = useRouteLocale()
|
||||
|
||||
const locale = computed(() => LOCALES[routeLocale.value])
|
||||
|
||||
const { feature, featureList, onSelect, isFocus } = useCaniuseFeaturesSearch(inputEl, listEl)
|
||||
const { past, pastList, future, futureList, embedType, embedTypeList } = useCaniuseVersionSelect()
|
||||
@ -16,7 +42,7 @@ const { output, rendered } = useCaniuse({ feature, embedType, past, future })
|
||||
<div class="caniuse-config-wrapper">
|
||||
<form>
|
||||
<label class="caniuse-form-item" :for="`caniuse-feature-input-${id}`">
|
||||
<span>选择特性:</span>
|
||||
<span>{{ locale['select-feature'] }}</span>
|
||||
<div class="feature-input">
|
||||
<input
|
||||
:id="`caniuse-feature-input-${id}`"
|
||||
@ -24,7 +50,7 @@ const { output, rendered } = useCaniuse({ feature, embedType, past, future })
|
||||
class="feature-input__input"
|
||||
type="text"
|
||||
name="feature"
|
||||
placeholder="输入特性"
|
||||
:placeholder="locale.placeholder"
|
||||
>
|
||||
<span class="vpi-chevron-down" />
|
||||
<ul v-show="isFocus" ref="listEl" class="feature-list">
|
||||
@ -45,7 +71,7 @@ const { output, rendered } = useCaniuse({ feature, embedType, past, future })
|
||||
</div>
|
||||
</label>
|
||||
<div class="caniuse-form-item">
|
||||
<span>嵌入方式:</span>
|
||||
<span>{{ locale['embed-type'] }}</span>
|
||||
<div class="caniuse-embed-type">
|
||||
<label
|
||||
v-for="(item, index) in embedTypeList"
|
||||
@ -54,12 +80,12 @@ const { output, rendered } = useCaniuse({ feature, embedType, past, future })
|
||||
>
|
||||
<input :id="`caniuse-embed-${id}-${index}`" v-model="embedType" type="radio" name="embedType" :value="item.value">
|
||||
<span>{{ item.label }}</span>
|
||||
<Badge v-if="item.value === 'image'" type="warning" text="不推荐" />
|
||||
<Badge v-if="item.value === 'image'" type="warning" :text="locale['no-recommend']" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!embedType" class="caniuse-form-item">
|
||||
<span>浏览器版本:</span>
|
||||
<span>{{ locale['browser-version'] }}</span>
|
||||
<div class="caniuse-browser-version">
|
||||
<label :for="`caniuse-past-${id}`">
|
||||
<select :id="`caniuse-past-${id}`" v-model="past" name="past">
|
||||
@ -80,7 +106,7 @@ const { output, rendered } = useCaniuse({ feature, embedType, past, future })
|
||||
</div>
|
||||
</form>
|
||||
<div class="caniuse-output">
|
||||
<h4>输出:</h4>
|
||||
<h4>{{ locale.output }}</h4>
|
||||
<CodeViewer lang="md" :content="output" />
|
||||
</div>
|
||||
<div v-if="embedType === 'image'" v-html="rendered" />
|
||||
|
||||
@ -1,16 +1,40 @@
|
||||
<script setup lang="ts">
|
||||
import VPButton from '@theme/VPButton.vue'
|
||||
import { computed } from 'vue'
|
||||
import VPButton from 'vuepress-theme-plume/components/VPButton.vue'
|
||||
import { useRouteLocale } from 'vuepress/client'
|
||||
import { useThemeColors } from '../composables/theme-colors.js'
|
||||
import CodeViewer from './CodeViewer.vue'
|
||||
import ColorPick from './ColorPick.vue'
|
||||
|
||||
const locales: LocaleConfig<
|
||||
Record<'reset' | 'light' | 'dark' | 'desc' | 'tip', string>
|
||||
> = {
|
||||
'/': {
|
||||
reset: '重置',
|
||||
light: '浅色主题',
|
||||
dark: '深色主题',
|
||||
desc: '复制下方的代码到您的项目中,请参考',
|
||||
tip: '主题定制',
|
||||
},
|
||||
'/en/': {
|
||||
reset: 'Reset',
|
||||
light: 'Light theme',
|
||||
dark: 'Dark theme',
|
||||
desc: 'Copy the code below and paste it into your project, please refer to',
|
||||
tip: 'Theme customization',
|
||||
},
|
||||
}
|
||||
|
||||
const routeLocale = useRouteLocale()
|
||||
const locale = computed(() => locales[routeLocale.value])
|
||||
|
||||
const { lightColors, darkColors, css, reset } = useThemeColors()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPButton theme="alt" text="重置" @click="reset" />
|
||||
<VPButton theme="alt" :text="locale.reset" @click="reset" />
|
||||
|
||||
<h2>浅色主题</h2>
|
||||
<h2>{{ locale.light }}</h2>
|
||||
<div class="theme-colors-wrapper">
|
||||
<div v-for="({ name, group }, index) in lightColors" :key="index" class="group">
|
||||
<h4>{{ name }}</h4>
|
||||
@ -23,7 +47,7 @@ const { lightColors, darkColors, css, reset } = useThemeColors()
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<h2>深色主题</h2>
|
||||
<h2>{{ locale.dark }}</h2>
|
||||
<div class="theme-colors-wrapper">
|
||||
<div v-for="({ name, group }, index) in darkColors" :key="index" class="group">
|
||||
<h4>{{ name }}</h4>
|
||||
@ -36,7 +60,7 @@ const { lightColors, darkColors, css, reset } = useThemeColors()
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<p>复制下方的代码到您的项目中,请参考 <a href="/guide/custom-style/">主题定制</a> </p>
|
||||
<p>{{ locale.desc }} <a href="/guide/custom-style/">{{ locale.tip }}</a> </p>
|
||||
<CodeViewer :content="css" lang="css" />
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { LocaleConfig } from 'vuepress'
|
||||
import { onClickOutside, useDebounceFn, useEventListener, useLocalStorage } from '@vueuse/core'
|
||||
import { computed, onMounted, readonly, ref, watch } from 'vue'
|
||||
import { useRouteLocale } from 'vuepress/client'
|
||||
|
||||
interface Feature {
|
||||
label: string
|
||||
@ -14,21 +16,22 @@ interface SelectItem {
|
||||
|
||||
const api = 'https://caniuse.pengzhanbo.cn/features.json'
|
||||
|
||||
const pastVersions: SelectItem[] = [
|
||||
{ label: '不显示旧版本', value: '0' },
|
||||
...Array.from({ length: 5 }).fill(0).map((_, i) => ({
|
||||
label: `旧版本(当前版本 - ${i + 1})`,
|
||||
value: `${i + 1}`,
|
||||
})),
|
||||
]
|
||||
|
||||
const futureVersions: SelectItem[] = [
|
||||
{ label: '不显示未来版本', value: '0' },
|
||||
...Array.from({ length: 3 }).fill(0).map((_, i) => ({
|
||||
label: `未来版本(当前版本 + ${i + 1})`,
|
||||
value: `${i + 1}`,
|
||||
})),
|
||||
]
|
||||
const locales: LocaleConfig<
|
||||
Record<'past0' | 'pastIndex' | 'future0' | 'futureIndex', string>
|
||||
> = {
|
||||
'/': {
|
||||
past0: '不显示旧版本',
|
||||
pastIndex: '旧版本(当前版本 - {index})',
|
||||
future0: '不显示未来版本',
|
||||
futureIndex: '未来版本(当前版本 + {index})',
|
||||
},
|
||||
'/en/': {
|
||||
past0: 'Do not show old versions',
|
||||
pastIndex: 'Old version (current version - {index})',
|
||||
future0: 'Do not show future versions',
|
||||
futureIndex: 'Future version (current version + {index})',
|
||||
},
|
||||
}
|
||||
|
||||
const embedTypes: SelectItem[] = [
|
||||
{ label: 'iframe', value: '' },
|
||||
@ -39,16 +42,34 @@ export function useCaniuseVersionSelect(): {
|
||||
past: Ref<string>
|
||||
future: Ref<string>
|
||||
embedType: Ref<string>
|
||||
pastList: Readonly<SelectItem[]>
|
||||
futureList: Readonly<SelectItem[]>
|
||||
pastList: ComputedRef<SelectItem[]>
|
||||
futureList: ComputedRef<SelectItem[]>
|
||||
embedTypeList: Readonly<SelectItem[]>
|
||||
} {
|
||||
const routeLocale = useRouteLocale()
|
||||
|
||||
const past = ref('2')
|
||||
const future = ref('1')
|
||||
const embedType = ref('')
|
||||
|
||||
const pastList = readonly(pastVersions)
|
||||
const futureList = readonly(futureVersions)
|
||||
const pastList = computed(() => {
|
||||
return [
|
||||
{ label: locales[routeLocale.value].past0 || '', value: '0' },
|
||||
...Array.from({ length: 5 }).fill(0).map((_, i) => ({
|
||||
label: locales[routeLocale.value]?.pastIndex?.replace('{index}', `${i + 1}`) ?? '',
|
||||
value: `${i + 1}`,
|
||||
})),
|
||||
]
|
||||
})
|
||||
const futureList = computed(() => {
|
||||
return [
|
||||
{ label: locales[routeLocale.value].future0 || '', value: '0' },
|
||||
...Array.from({ length: 3 }).fill(0).map((_, i) => ({
|
||||
label: locales[routeLocale.value]?.futureIndex?.replace('{index}', `${i + 1}`) ?? '',
|
||||
value: `${i + 1}`,
|
||||
})),
|
||||
]
|
||||
})
|
||||
const embedTypeList = readonly(embedTypes)
|
||||
|
||||
return {
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
---
|
||||
title: 博客文章
|
||||
title: posts文章
|
||||
createTime: 2024/03/03 11:01:03
|
||||
permalink: /config/frontmatter/article/
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
适用于 博客类型的文章。
|
||||
适用于 集合类型为 post 的文章。
|
||||
|
||||
示例:
|
||||
|
||||
@ -68,7 +68,7 @@ tags:
|
||||
封面图配置。
|
||||
|
||||
```ts
|
||||
interface BlogPostCoverStyle {
|
||||
interface PostCoverStyle {
|
||||
/**
|
||||
* 博客文章封面图的位置
|
||||
*/
|
||||
|
||||
195
docs/en/blog/3.Update/165.md
Normal file
195
docs/en/blog/3.Update/165.md
Normal file
@ -0,0 +1,195 @@
|
||||
---
|
||||
title: '⚠️ 1.0.0-rc.165 Breaking Change Notice: Blog & Notes Features Migrated to "Collections"'
|
||||
sticky: true
|
||||
createTime: 2025/10/09 22:18:52
|
||||
permalink: /en/blog/dk58a4t2/
|
||||
tags:
|
||||
- Breaking Change
|
||||
- Important Update
|
||||
---
|
||||
|
||||
:::important
|
||||
‼️ This update is a BREAKING CHANGE! The blog and notes features have been entirely migrated to a new "Collections" architecture. ‼️
|
||||
:::
|
||||
|
||||
<!-- more -->
|
||||
|
||||
## Design Motivation: Why Introduce "Collections"?
|
||||
|
||||
[Jump to Migration Guide 👇👇👇](#migration-guide){.read-more}
|
||||
|
||||
### Background & Problem Analysis
|
||||
|
||||
The theme initially only supported the **blog** feature, treating all Markdown files under the `docs`
|
||||
source directory as blog posts. As the version iterated, we added the **notes/knowledge base** feature,
|
||||
defaulting the `notes` directory as the root for notes and excluding its content from the blog list.
|
||||
|
||||
This phased implementation led to an **architectural imbalance**: the blog became a "first-class citizen,"
|
||||
while the notes feature appeared marginalized. This caused the following issues for users:
|
||||
|
||||
- **Path Redundancy**: Note files had to be stored under the `notes/` directory, adding unnecessary directory levels.
|
||||
- **Complex Links**: When `autoFrontmatter` was not enabled, URLs were forced to include the `/notes/` prefix.
|
||||
- **Conceptual Confusion**: Users were often confused about the functional difference between "notes" and "docs."
|
||||
- **Cumbersome Configuration**: Extra adjustments to the `notes.dir` configuration were needed to achieve a standard documentation site structure.
|
||||
|
||||
These design flaws were legacy issues from historical iterations, and we sincerely apologize for the inconvenience.
|
||||
|
||||
### Solution: Unified Content Abstraction
|
||||
|
||||
After researching mainstream static site generators (like Hugo, VitePress) and full-stack frameworks
|
||||
(like Nuxt), we drew inspiration from the `collection` concept in `@nuxt/content`.
|
||||
|
||||
We decided to introduce **Collections** as a unified unit for content organization. Whether it's a blog,
|
||||
notes, documentation, or a knowledge base, they are essentially specific collections of Markdown files, differing only in their presentation.
|
||||
|
||||
:::important
|
||||
Core Insight: Use the "Collection" abstraction to unify the organization of various content types while preserving their respective display characteristics.
|
||||
:::
|
||||
|
||||
Based on content characteristics, we defined two collection types:
|
||||
|
||||
- **`post` type**: Suitable for fragmented, loosely related content (e.g., blogs, columns), providing an article list as a navigation entry.
|
||||
- **`doc` type**: Suitable for structured, strongly related content (e.g., documentation, manuals), providing a sidebar for quick navigation.
|
||||
|
||||
This design solves the historical architectural problems and lays the foundation for extending more content types in the future.
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### Core Concepts
|
||||
|
||||
- **Collection**: Specified via `collection.dir`; all Markdown files under this directory belong to the collection.
|
||||
- **Collection Type**:
|
||||
- `post`: Fragmented content, supports article list navigation.
|
||||
- `doc`: Structured content, supports sidebar navigation.
|
||||
|
||||
### Configuration Migration
|
||||
|
||||
Replace the original `blog` and `notes` configurations:
|
||||
|
||||
```ts twoslash
|
||||
// @noErrors
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// [!code --:9]
|
||||
// Remove old blog and notes configuration
|
||||
blog: { /* Blog configuration */ },
|
||||
notes: {
|
||||
link: '/',
|
||||
dir: '/notes/',
|
||||
notes: [
|
||||
{ dir: 'typescript', link: '/typescript/', sidebar: 'auto' }
|
||||
]
|
||||
},
|
||||
// [!code ++:16]
|
||||
// Use collections configuration
|
||||
collections: [
|
||||
{
|
||||
type: 'post', // Replaces original blog functionality
|
||||
dir: 'blog', // Points to docs/blog directory
|
||||
title: 'Blog' // Collection display name
|
||||
// Original blog configuration continues here
|
||||
// ...
|
||||
},
|
||||
{
|
||||
type: 'doc', // Replaces original notes functionality
|
||||
dir: 'typescript', // Points to docs/typescript directory
|
||||
title: 'TypeScript Notes',
|
||||
sidebar: 'auto', // Auto-generate sidebar
|
||||
},
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Directory Structure Adjustment
|
||||
|
||||
Migrate files according to the following steps:
|
||||
|
||||
**Procedure:**
|
||||
|
||||
1. Move subdirectories under the `notes` directory directly to the `docs` root directory.
|
||||
2. Create a `blog` directory and move original blog posts into it.
|
||||
3. Remove the now-empty `notes` directory.
|
||||
|
||||
:::: flex
|
||||
|
||||
<div style="flex:1">
|
||||
|
||||
::: file-tree title="Pre-migration Structure"
|
||||
|
||||
- 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="Post-migration Structure"
|
||||
|
||||
- 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>
|
||||
|
||||
::::
|
||||
|
||||
### Helper Functions
|
||||
|
||||
- `defineCollection`: Helper function for defining a single collection configuration.
|
||||
- `defineCollections`: Helper function for defining multiple collection configurations.
|
||||
|
||||
```ts twoslash
|
||||
import { defineCollection, defineCollections } from 'vuepress-theme-plume'
|
||||
|
||||
export const blog = defineCollection({
|
||||
type: 'post',
|
||||
dir: 'blog',
|
||||
title: 'Blog'
|
||||
})
|
||||
|
||||
export const typescript = defineCollection({
|
||||
type: 'doc',
|
||||
dir: 'typescript',
|
||||
title: 'TypeScript Notes',
|
||||
sidebar: 'auto'
|
||||
})
|
||||
|
||||
export const collections = defineCollections([
|
||||
blog,
|
||||
typescript
|
||||
])
|
||||
```
|
||||
|
||||
## Detailed Documentation
|
||||
|
||||
[Collections Documentation](../../guide/quick-start/collection.md){.read-more}
|
||||
|
||||
[Post Collection](../../guide/quick-start/collection-post.md){.read-more}
|
||||
|
||||
[Doc Collection](../../guide/quick-start/collection-doc.md){.read-more}
|
||||
@ -1,7 +1,334 @@
|
||||
---
|
||||
title: How to user frontmatter
|
||||
createTime: 2025/03/03 14:12:59
|
||||
permalink: /en/article/gh9w1jj1/
|
||||
title: How to Use Frontmatter
|
||||
createTime: 2025/10/09 09:19:36
|
||||
permalink: /en/article/ecxnxxd0/
|
||||
---
|
||||
|
||||
todo ...
|
||||
::: info Note
|
||||
This article translates parts of [Introduction to YAML](https://dev.to/paulasantamaria/introduction-to-yaml-125f).
|
||||
It provides a basic explanation of how to use frontmatter in markdown files.
|
||||
|
||||
If you have a good foundation in English reading, to avoid potential content distortion from translation,
|
||||
it is recommended that you read the original article.
|
||||
|
||||
Original article: <https://dev.to/paulasantamaria/introduction-to-yaml-125f>.
|
||||
:::
|
||||
|
||||
## Introduction
|
||||
|
||||
YAML is a data serialization language, commonly used for configuration files, such as the
|
||||
[Open API Specification](https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/api-with-examples.yaml) or [CI/CD pipelines](https://docs.gitlab.com/ee/ci/yaml/).
|
||||
|
||||
::: note Fun Fact! 🤓
|
||||
According to the [YAML 1.0 Specification Document (2001-05-26)](https://yaml.org/spec/history/2001-05-26.html),
|
||||
the acronym "YAML" stood for "Yet Another Markup Language".However,
|
||||
it was later changed to the recursive acronym "YAML Ain't Markup Language" in the [2002-04-07 specification](https://yaml.org/spec/history/2002-04-07.html).
|
||||
:::
|
||||
|
||||
As stated in the latest specification, __YAML__ is designed to be __human-friendly for handling data__
|
||||
and achieves "unique cleanliness" by __minimizing the use of structural characters__,
|
||||
allowing data to be displayed in a natural and meaningful way.
|
||||
|
||||
The latest specification also states that YAML _1.2 is officially a superset of JSON_, meaning most JSON documents can be parsed as YAML.
|
||||
|
||||
YAML makes it easy to inspect data structures by using indentation-based scoping (similar to Python).
|
||||
|
||||
::: note Another Fun Fact! 🤓
|
||||
DEV.to articles use YAML to define custom variables like title, description, tags, etc.
|
||||
:::
|
||||
|
||||
## Basic Syntax
|
||||
|
||||
A YAML document is essentially a __collection of key-value pairs__, where values can be as simple as a string or as complex as a tree.
|
||||
|
||||
Here are some notes on YAML syntax:
|
||||
|
||||
- __Indentation is used to denote structure__. Tabs are not allowed. The number of spaces doesn't matter
|
||||
as long as child nodes are indented more than their parent nodes.
|
||||
- UTF-8, UTF-16, and UTF-32 encodings are permitted.
|
||||
|
||||
### Strings
|
||||
|
||||
```md
|
||||
---
|
||||
# Strings do not require quotes:
|
||||
title: Introduction to YAML
|
||||
|
||||
# But you can still use them:
|
||||
title-w-quotes: 'Introduction to YAML'
|
||||
|
||||
# Multi-line strings start with |
|
||||
execute: |
|
||||
npm ci
|
||||
npm build
|
||||
npm test
|
||||
---
|
||||
```
|
||||
|
||||
The above code converts to JSON as:
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "Introduction to YAML",
|
||||
"title-w-quotes": "Introduction to YAML",
|
||||
"execute": "npm ci\nnpm build\nnpm test\n"
|
||||
}
|
||||
```
|
||||
|
||||
### Numbers
|
||||
|
||||
```md
|
||||
---
|
||||
# Integer:
|
||||
age: 29
|
||||
|
||||
# Float:
|
||||
price: 15.99
|
||||
|
||||
# Scientific notation:
|
||||
population: 2.89e+6
|
||||
---
|
||||
```
|
||||
|
||||
The above code converts to JSON as:
|
||||
|
||||
```json
|
||||
{
|
||||
"age": 29,
|
||||
"price": 15.99,
|
||||
"population": 2890000
|
||||
}
|
||||
```
|
||||
|
||||
### Booleans
|
||||
|
||||
```md
|
||||
---
|
||||
# Booleans can be represented in different ways:
|
||||
published: false
|
||||
published: False
|
||||
published: FALSE
|
||||
---
|
||||
```
|
||||
|
||||
All of the above will convert to JSON as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"published": false
|
||||
}
|
||||
```
|
||||
|
||||
### Null Values
|
||||
|
||||
```md
|
||||
---
|
||||
# Null values can be represented by not setting a value:
|
||||
null-value:
|
||||
|
||||
# Or more explicitly:
|
||||
null-value: null
|
||||
null-value: NULL
|
||||
null-value: Null
|
||||
---
|
||||
```
|
||||
|
||||
All of the above will convert to JSON as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"null-value": null
|
||||
}
|
||||
```
|
||||
|
||||
### Dates and Timestamps
|
||||
|
||||
Dates can be used in ISO format as shown below:
|
||||
|
||||
```md
|
||||
---
|
||||
date: 2002-12-14
|
||||
canonical: 2001-12-15T02:59:43.1Z
|
||||
iso8601: 2001-12-14t21:59:43.10-05:00
|
||||
spaced: 2001-12-14 21:59:43.10 -5
|
||||
---
|
||||
```
|
||||
|
||||
### Sequences
|
||||
|
||||
Sequences allow us to define lists in YAML:
|
||||
|
||||
```md
|
||||
---
|
||||
# Numbered list using hyphens:
|
||||
numbers:
|
||||
- one
|
||||
- two
|
||||
- three
|
||||
|
||||
# Inline version:
|
||||
numbers: [ one, two, three ]
|
||||
---
|
||||
```
|
||||
|
||||
Both sequences above will parse to JSON as follows:
|
||||
|
||||
```json
|
||||
{
|
||||
"numbers": [
|
||||
"one",
|
||||
"two",
|
||||
"three"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Nested Values
|
||||
|
||||
We can use all the types mentioned above to create objects with nested values, as shown below:
|
||||
|
||||
```md
|
||||
---
|
||||
# Data for the novel Nineteen Eighty-Four.
|
||||
nineteen-eighty-four:
|
||||
author: George Orwell
|
||||
published-at: 1949-06-08
|
||||
page-count: 328
|
||||
description: |
|
||||
A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell.
|
||||
It was published in June 1949 by Secker & Warburg as Orwell's ninth and final book.
|
||||
---
|
||||
```
|
||||
|
||||
This converts to JSON as:
|
||||
|
||||
```json
|
||||
{
|
||||
"nineteen-eighty-four": {
|
||||
"author": "George Orwell",
|
||||
"published-at": "1949-06-08T00:00:00.000Z",
|
||||
"page-count": 328,
|
||||
"description": "A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell.\nIt was published in June 1949 by Secker & Warburg as Orwell's ninth and final book.\n"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Lists of Objects
|
||||
|
||||
Combining sequences and nested values, we can create a list of objects.
|
||||
|
||||
```md
|
||||
---
|
||||
# Let's list books:
|
||||
- nineteen-eighty-four:
|
||||
author: George Orwell
|
||||
published-at: 1949-06-08
|
||||
page-count: 328
|
||||
description: |
|
||||
A Novel, often published as 1984, is a dystopian novel by English novelist George Orwell.
|
||||
|
||||
- the-hobbit:
|
||||
author: J. R. R. Tolkien
|
||||
published-at: 1937-09-21
|
||||
page-count: 310
|
||||
description: |
|
||||
The Hobbit, or There and Back Again is a children's fantasy novel by English author J. R. R. Tolkien.
|
||||
---
|
||||
```
|
||||
|
||||
## Unique Features
|
||||
|
||||
Here are some __more complex features__ that caught my attention, which also distinguish YAML from JSON.
|
||||
|
||||
### Comments
|
||||
|
||||
As you may have noticed in my previous examples, YAML allows comments starting with `#`.
|
||||
|
||||
```md
|
||||
---
|
||||
# This is a very useful comment.
|
||||
---
|
||||
```
|
||||
|
||||
### Reusability with Anchors
|
||||
|
||||
Node anchors are used to __mark a node__ for future reference, allowing us to reuse that node.
|
||||
To mark a node, we use the `&` character; to reference it, we use `*`:
|
||||
|
||||
In the following example, we define a list of books and reuse the author data, so we only need to define it once:
|
||||
|
||||
```md
|
||||
---
|
||||
# Author data:
|
||||
author: &gOrwell
|
||||
name: George
|
||||
last-name: Orwell
|
||||
|
||||
# Some books:
|
||||
books:
|
||||
- 1984:
|
||||
author: *gOrwell
|
||||
- animal-farm:
|
||||
author: *gOrwell
|
||||
---
|
||||
```
|
||||
|
||||
When parsed to JSON, the above code will look like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"author": {
|
||||
"name": "George",
|
||||
"last-name": "Orwell"
|
||||
},
|
||||
"books": [
|
||||
{
|
||||
"1984": {
|
||||
"author": {
|
||||
"name": "George",
|
||||
"last-name": "Orwell"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"animal-farm": {
|
||||
"author": {
|
||||
"name": "George",
|
||||
"last-name": "Orwell"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Explicit Data Types with Tags
|
||||
|
||||
As we saw in previous examples, YAML automatically detects the types of our values, but we can also __specify the desired type__.
|
||||
|
||||
We specify it by prefixing the value with `!!` followed by the type.
|
||||
|
||||
Here are some examples:
|
||||
|
||||
```md
|
||||
---
|
||||
# The following value should be an integer, regardless:
|
||||
should-be-int: !!int 3.2
|
||||
|
||||
# Parse any value as a string:
|
||||
should-be-string: !!str 30.25
|
||||
|
||||
# I need the next value to be a boolean:
|
||||
should-be-boolean: !!bool yes
|
||||
---
|
||||
```
|
||||
|
||||
This converts to JSON as:
|
||||
|
||||
```json
|
||||
{
|
||||
"should-be-int": 3,
|
||||
"should-be-string": "30.25",
|
||||
"should-be-boolean": true
|
||||
}
|
||||
```
|
||||
|
||||
16
docs/en/changelog.md
Normal file
16
docs/en/changelog.md
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Changelog
|
||||
createTime: 2024/03/13 21:15:50
|
||||
permalink: /en/changelog/
|
||||
article: false
|
||||
aside: false
|
||||
externalLinkIcon: false
|
||||
readingTime: false
|
||||
comment: false
|
||||
editLink: false
|
||||
contributors: false
|
||||
changelog: false
|
||||
search: false
|
||||
---
|
||||
|
||||
<!-- @include: ../../CHANGELOG.md -->
|
||||
@ -1,17 +0,0 @@
|
||||
---
|
||||
title: Theme Configuration
|
||||
createTime: 2025/03/03 14:27:13
|
||||
permalink: /en/config/basic/
|
||||
---
|
||||
|
||||
todo ...
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
### autoFrontmatter
|
||||
|
||||
### article
|
||||
|
||||
### blog
|
||||
|
||||
## Locales Configuration
|
||||
531
docs/en/config/collections.md
Normal file
531
docs/en/config/collections.md
Normal file
@ -0,0 +1,531 @@
|
||||
---
|
||||
title: Collections Configuration
|
||||
createTime: 2025/10/09 14:00:06
|
||||
permalink: /en/config/collections/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Collections** are the core concept in the theme for organizing and managing documents.
|
||||
Each collection points to a specific folder under the source directory, managing all Markdown files within it as a logical unit.
|
||||
|
||||
Through flexible collection configuration, you can easily build various content systems:
|
||||
|
||||
- **Blog** - Personal essays and technical shares
|
||||
- **Column** - Thematic series articles
|
||||
- **User Manual** - Product usage documentation
|
||||
- **Notes** - Study notes and knowledge organization
|
||||
- **Product Documentation** - Complete project documentation
|
||||
- **Knowledge Base** - Team knowledge management system
|
||||
|
||||
Collections are primarily divided into two types to accommodate different content organization needs:
|
||||
|
||||
- **`post` type**: Suitable for fragmented content with weak inter-article relationships, such as blogs, columns, etc.
|
||||
- **`doc` type**: Suitable for structured documentation with closely related content,
|
||||
such as user manuals, product documentation, knowledge bases, etc.
|
||||
|
||||
::: tip Configuration Location
|
||||
Collection configuration can be done in either `.vuepress/config.ts` or the standalone `plume.config.ts` file.
|
||||
:::
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
Assume your project uses the following directory structure:
|
||||
|
||||
::: file-tree title="Project Structure"
|
||||
|
||||
- docs
|
||||
- **blog**
|
||||
- post-1.md
|
||||
- post-2.md
|
||||
- **typescript**
|
||||
- basic
|
||||
- intro.md
|
||||
- variable.md
|
||||
- types.md
|
||||
:::
|
||||
|
||||
The corresponding collection configuration example is as follows:
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Collection Configuration // [!code focus:7]
|
||||
collections: [
|
||||
// Register post-type collection for blog functionality
|
||||
{ type: 'post', dir: 'blog', title: 'Blog' },
|
||||
// Register doc-type collection for TypeScript documentation functionality
|
||||
{ type: 'doc', dir: 'typescript', title: 'TypeScript Notes', sidebar: 'auto' }
|
||||
],
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
// Collection configuration in standalone config file // [!code focus:7]
|
||||
collections: [
|
||||
{ type: 'post', dir: 'blog', title: 'Blog' },
|
||||
{ type: 'doc', dir: 'typescript', title: 'TypeScript Notes', sidebar: 'auto' }
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Multi-language Configuration
|
||||
|
||||
For multi-language projects, you can configure collections separately for each language within the `locales` field:
|
||||
|
||||
::: file-tree title="Multi-language Project Structure"
|
||||
|
||||
- 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: {
|
||||
'/': {
|
||||
// Chinese collection configuration // [!code focus:4]
|
||||
collections: [
|
||||
{ type: 'post', dir: 'blog', title: '博客' },
|
||||
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||
],
|
||||
},
|
||||
'/en/': {
|
||||
// English collection configuration // [!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: {
|
||||
'/': {
|
||||
// Chinese collection configuration // [!code focus:4]
|
||||
collections: [
|
||||
{ type: 'post', dir: 'blog', title: '博客' },
|
||||
{ type: 'doc', dir: 'typescript', title: 'TypeScript笔记', sidebar: 'auto' }
|
||||
],
|
||||
},
|
||||
'/en/': {
|
||||
// English collection configuration // [!code focus:4]
|
||||
collections: [
|
||||
{ type: 'post', dir: 'blog', title: 'Blog' },
|
||||
{ type: 'doc', dir: 'typescript', title: 'TypeScript Note', sidebar: 'auto' }
|
||||
],
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Post Collection Details
|
||||
|
||||
Post collections are designed specifically for fragmented content like blogs and columns, providing a complete article management system:
|
||||
|
||||
### Core Features
|
||||
|
||||
- **Article List Page** - Supports article pinning, cover images, excerpt display, personal information, etc.
|
||||
- **Article Categories Page** - Automatically generates categories based on directory structure
|
||||
- **Article Tags Page** - Flexible tag management
|
||||
- **Article Archives Page** - Organizes content by time dimension
|
||||
|
||||
### Configuration Example
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
collections: [
|
||||
// Blog collection configuration
|
||||
{
|
||||
type: 'post',
|
||||
dir: 'blog',
|
||||
title: 'Blog',
|
||||
link: '/blog/', // List page link
|
||||
linkPrefix: '/article/', // Article link prefix
|
||||
postCover: 'top', // Cover image position
|
||||
autoFrontmatter: { permalink: true }, // Auto frontmatter
|
||||
},
|
||||
// Interview column configuration
|
||||
{
|
||||
type: 'post',
|
||||
dir: 'interview',
|
||||
title: 'Interview Column',
|
||||
link: '/interview/', // List page link
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
## Doc Collection Details
|
||||
|
||||
Doc collections are suitable for structured documentation, emphasizing logical relationships between content:
|
||||
|
||||
### Core Features
|
||||
|
||||
- **Sidebar Navigation** - Provides clear document structure navigation
|
||||
- **Auto-generated Table of Contents** - Intelligently generates sidebar based on file structure
|
||||
- **Multi-level Nesting Support** - Supports complex document hierarchy structures
|
||||
|
||||
### Configuration Example
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
collections: [
|
||||
// TypeScript Notes - Auto-generated sidebar
|
||||
{
|
||||
type: 'doc',
|
||||
dir: 'typescript',
|
||||
title: 'TypeScript Notes',
|
||||
sidebar: 'auto'
|
||||
},
|
||||
// Python Notes - Manually configured sidebar
|
||||
{
|
||||
type: 'doc',
|
||||
dir: 'python',
|
||||
title: 'Python Notes',
|
||||
sidebar: [
|
||||
{ text: 'Basic Syntax', link: 'basic' },
|
||||
{
|
||||
text: 'API Documentation',
|
||||
items: [
|
||||
{ text: 'asyncio', link: 'asyncio' }
|
||||
]
|
||||
},
|
||||
'advanced' // Shorthand form
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Type Declarations
|
||||
|
||||
### Base Collection Configuration
|
||||
|
||||
```ts
|
||||
/* Collection configuration array */
|
||||
type ThemeCollections = ThemeCollectionItem[]
|
||||
|
||||
/* Single collection item */
|
||||
type ThemeCollectionItem = ThemePostCollection | ThemeDocCollection
|
||||
|
||||
/* Collection common configuration */
|
||||
interface ThemeBaseCollection {
|
||||
/**
|
||||
* Collection type
|
||||
* - `post`: Article list (blog, column)
|
||||
* - `doc`: Structured documentation (notes, knowledge base)
|
||||
*/
|
||||
type: 'post' | 'doc'
|
||||
/**
|
||||
* Document directory (relative to source directory)
|
||||
*/
|
||||
dir: string
|
||||
/**
|
||||
* Article link prefix
|
||||
*/
|
||||
linkPrefix?: string
|
||||
/**
|
||||
* Collection title (used for breadcrumb navigation)
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* Tag color theme
|
||||
* @default 'colored'
|
||||
*/
|
||||
tagsTheme?: 'colored' | 'gray' | 'brand'
|
||||
/**
|
||||
* Auto-generate frontmatter
|
||||
*/
|
||||
autoFrontmatter?: AutoFrontmatterOptions | false
|
||||
}
|
||||
```
|
||||
|
||||
### Post Collection Specific Configuration
|
||||
|
||||
```ts title="Post Collection Configuration"
|
||||
interface ThemePostCollection extends ThemeBaseCollection {
|
||||
type: 'post'
|
||||
/**
|
||||
* Include file patterns (glob pattern)
|
||||
* @default ['**\/*.md']
|
||||
*/
|
||||
include?: string[]
|
||||
/**
|
||||
* Exclude file patterns (glob pattern)
|
||||
* @default []
|
||||
*/
|
||||
exclude?: string[]
|
||||
/**
|
||||
* Pagination configuration
|
||||
*/
|
||||
pagination?: false | number | {
|
||||
/**
|
||||
* Number of articles per page
|
||||
* @default 15
|
||||
*/
|
||||
perPage?: number
|
||||
}
|
||||
/**
|
||||
* Article list page link
|
||||
* @default '/{dir}/'
|
||||
*/
|
||||
link?: string
|
||||
/**
|
||||
* Whether to enable article list page
|
||||
* @default true
|
||||
*/
|
||||
postList?: boolean
|
||||
/**
|
||||
* Whether to enable tags page
|
||||
* @default true
|
||||
*/
|
||||
tags?: boolean
|
||||
/**
|
||||
* Tags page link
|
||||
* @default '/{link}/tags/'
|
||||
*/
|
||||
tagsLink?: string
|
||||
/**
|
||||
* Tags page text
|
||||
*/
|
||||
tagsText?: string
|
||||
/**
|
||||
* Whether to enable archives page
|
||||
* @default true
|
||||
*/
|
||||
archives?: boolean
|
||||
/**
|
||||
* Archives page link
|
||||
* @default '/{link}/archives/'
|
||||
*/
|
||||
archivesLink?: string
|
||||
/**
|
||||
* Archives page text
|
||||
*/
|
||||
archivesText?: string
|
||||
/**
|
||||
* Whether to enable categories feature
|
||||
* @default true
|
||||
*/
|
||||
categories?: boolean
|
||||
/**
|
||||
* Categories page link
|
||||
* @default '/{link}/categories/'
|
||||
*/
|
||||
categoriesLink?: string
|
||||
/**
|
||||
* Categories page text
|
||||
*/
|
||||
categoriesText?: string
|
||||
/**
|
||||
* Categories expand depth
|
||||
* @default 'deep'
|
||||
*/
|
||||
categoriesExpand?: number | 'deep'
|
||||
/**
|
||||
* Categories list transformation function
|
||||
*/
|
||||
categoriesTransform?: (categories: PostsCategoryItem[]) => PostsCategoryItem[]
|
||||
/**
|
||||
* Article cover image configuration
|
||||
* @default 'right'
|
||||
*/
|
||||
postCover?: PostsCoverLayout | PostsCoverStyle
|
||||
/**
|
||||
* Profile configuration
|
||||
*/
|
||||
profile?: ProfileOptions | false
|
||||
/**
|
||||
* Social account configuration
|
||||
*/
|
||||
social?: SocialLink[] | false
|
||||
}
|
||||
/* Article category item */
|
||||
interface PostsCategoryItem {
|
||||
id: string
|
||||
sort: number
|
||||
name: string
|
||||
}
|
||||
/* Cover image layout */
|
||||
type PostsCoverLayout = 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'
|
||||
/* Cover image style */
|
||||
interface PostsCoverStyle {
|
||||
layout?: PostsCoverLayout
|
||||
ratio?: number | `${number}:${number}` | `${number}/${number}`
|
||||
width?: number
|
||||
compact?: boolean
|
||||
}
|
||||
/* Social link icon */
|
||||
type SocialLinkIcon = SocialLinkIconUnion | { svg: string, name?: string }
|
||||
/* Social link */
|
||||
interface SocialLink {
|
||||
icon: SocialLinkIcon
|
||||
link: string
|
||||
ariaLabel?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile
|
||||
*/
|
||||
export interface ProfileOptions {
|
||||
/**
|
||||
* Avatar image URL
|
||||
*/
|
||||
avatar?: string
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* Description / Bio / Motto / Signature
|
||||
*/
|
||||
description?: string
|
||||
/**
|
||||
* Whether to display as circular avatar
|
||||
*/
|
||||
circle?: boolean
|
||||
/**
|
||||
* Location
|
||||
*/
|
||||
location?: string
|
||||
/**
|
||||
* Organization, Company
|
||||
*/
|
||||
organization?: string
|
||||
/**
|
||||
* Layout position, left or right
|
||||
* @default 'right'
|
||||
*/
|
||||
layout?: 'left' | 'right'
|
||||
}
|
||||
```
|
||||
|
||||
### Doc Collection Specific Configuration
|
||||
|
||||
```ts title="Doc Collection Configuration"
|
||||
interface ThemeDocCollection extends ThemeBaseCollection {
|
||||
type: 'doc'
|
||||
/**
|
||||
* Sidebar configuration
|
||||
*/
|
||||
sidebar?: 'auto' | (string | ThemeSidebarItem)[]
|
||||
/**
|
||||
* Whether to show sidebar scrollbar
|
||||
* @default true
|
||||
*/
|
||||
sidebarScrollbar?: boolean
|
||||
/**
|
||||
* Sidebar default collapsed state
|
||||
* @default false
|
||||
*/
|
||||
sidebarCollapsed?: boolean
|
||||
}
|
||||
|
||||
/* Sidebar item configuration */
|
||||
interface ThemeSidebarItem {
|
||||
text?: string
|
||||
link?: string
|
||||
icon?: ThemeIcon
|
||||
badge?: string | ThemeBadge
|
||||
items?: 'auto' | (string | ThemeSidebarItem)[]
|
||||
collapsed?: boolean
|
||||
prefix?: string
|
||||
rel?: string
|
||||
target?: string
|
||||
}
|
||||
|
||||
/* Icon type */
|
||||
type ThemeIcon = string | { svg: string }
|
||||
|
||||
/* Badge configuration */
|
||||
export interface ThemeBadge {
|
||||
text?: string
|
||||
type?: string
|
||||
color?: string
|
||||
bgColor?: string
|
||||
borderColor?: string
|
||||
}
|
||||
```
|
||||
|
||||
### Auto Sidebar Generation
|
||||
|
||||
When the Doc collection's `sidebar` is set to `'auto'`, the system automatically generates sidebar
|
||||
navigation based on the directory structure. The sorting rules follow the [Folder Naming Conventions](../guide/quick-start/write.md#folder-naming-conventions).
|
||||
|
||||
### Sidebar Icon Configuration
|
||||
|
||||
The theme supports two methods for configuring sidebar icons:
|
||||
|
||||
- **Define directly in sidebar configuration**:
|
||||
|
||||
```ts
|
||||
sidebar: [
|
||||
{ text: 'Introduction', link: 'intro', icon: 'mdi:tooltip-text-outline' }
|
||||
]
|
||||
```
|
||||
|
||||
- **Define in document frontmatter**:
|
||||
|
||||
```md
|
||||
---
|
||||
title: Theme Introduction
|
||||
icon: mdi:tooltip-text-outline
|
||||
---
|
||||
```
|
||||
|
||||
Both methods have the same effect, and you can choose which to use based on specific scenarios.
|
||||
|
||||
For complete sidebar configuration options and usage tips, please refer to the [Sidebar Configuration Guide](../guide/quick-start/sidebar.md).
|
||||
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Blog Article
|
||||
createTime: 2025/03/03 19:11:37
|
||||
permalink: /en/config/frontmatter/article/
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### sticky
|
||||
|
||||
todo ...
|
||||
@ -1,8 +1,230 @@
|
||||
---
|
||||
title: General configuration
|
||||
createTime: 2025/03/04 12:30:38
|
||||
title: General Configuration
|
||||
createTime: 2025/10/09 20:01:09
|
||||
permalink: /en/config/frontmatter/basic/
|
||||
badge: badge
|
||||
---
|
||||
|
||||
todo ...
|
||||
## Overview
|
||||
|
||||
General Frontmatter configuration applicable to all articles.
|
||||
|
||||
Example:
|
||||
|
||||
```md
|
||||
---
|
||||
title: Title
|
||||
createTime: 2024/03/02 20:01:09
|
||||
permalink: /config/frontmatter/basic/
|
||||
---
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### pageLayout
|
||||
|
||||
- Type: `false | 'home' | 'doc' | 'custom' | 'page' | 'friends' | string`
|
||||
- Default: `doc`
|
||||
- Details:
|
||||
|
||||
Page layout mode.
|
||||
|
||||
- `'home'`: Homepage layout
|
||||
- `'doc'`: Documentation page layout, including left sidebar, article content, right sidebar, navbar, comments, etc.
|
||||
- `'page'`: Includes only the navbar and MD file content. Use this layout for custom page content.
|
||||
- `'friends'`: Friends link page layout
|
||||
- `'custom'`: Includes only MD file content. Use this layout for fully custom page content.
|
||||
- `false`: Equivalent to `custom`
|
||||
- `string`: A global component name can be passed, which will be applied as the layout component.
|
||||
|
||||
### pageClass
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Additional custom CSS class name for the page.
|
||||
|
||||
### title
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Article title.
|
||||
|
||||
The theme automatically populates the current filename as the article title upon file creation.
|
||||
|
||||
### badge
|
||||
|
||||
- Type: `string | { text: string, type?: 'info' | 'tip' | 'warning' | 'danger' }`
|
||||
|
||||
Display a badge on the right side of the article title.
|
||||
|
||||
### createTime
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Article creation time.
|
||||
|
||||
The theme automatically populates the current time as the article creation time upon file creation.
|
||||
|
||||
### permalink
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Article permanent link.
|
||||
|
||||
Upon file creation, the theme automatically populates:
|
||||
- For blog-type articles: `/article/` + `8-character random string generated by nanoid` as the permanent link.
|
||||
- For articles under the notes directory: The permanent link is automatically populated based on the notes configuration.
|
||||
|
||||
### externalLinkIcon
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the external link icon for external links within the current article.
|
||||
|
||||
### backToTop
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the back-to-top button for the current article.
|
||||
|
||||
### comments
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether the current article is commentable. Only takes effect when the comment feature is enabled.
|
||||
|
||||
### aside
|
||||
|
||||
- Type: `boolean | 'left'`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the right sidebar for the current article.
|
||||
|
||||
When set to `'left'`, the right sidebar will be displayed on the left side.
|
||||
|
||||
### navbar
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the navigation bar for the current article.
|
||||
|
||||
### outline
|
||||
|
||||
- Type: `false | number | [number, number] | 'deep'`
|
||||
- Default: `[2, 3]`
|
||||
- Details:
|
||||
|
||||
The heading levels to display.
|
||||
|
||||
A single number indicates displaying only headings of that level.
|
||||
|
||||
If a tuple is passed, the first number is the minimum level and the second number is the maximum level.
|
||||
|
||||
`'deep'` is the same as `[2, 6]`, which displays all headings from `<h2>` to `<h6>`.
|
||||
|
||||
### prev
|
||||
|
||||
- Type: `string | { text: string, link: string, icon?: string }`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Customize the previous article for the current article.
|
||||
|
||||
- For blog-type articles: The theme automatically populates the title and link of the previous article based on chronological order.
|
||||
- For notes-type articles: The theme automatically populates the title and link of the previous article based on the note sidebar configuration.
|
||||
|
||||
### next
|
||||
|
||||
- Type: `string | { text: string, link: string, icon?: string }`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
Customize the next article for the current article.
|
||||
|
||||
- For blog-type articles: The theme automatically populates the title and link of the next article based on chronological order.
|
||||
- For notes-type articles: The theme automatically populates the title and link of the next article based on the note sidebar configuration.
|
||||
|
||||
### readingTime
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the reading time for the current article.
|
||||
|
||||
### lastUpdated
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the last updated time for the current article.
|
||||
The last updated time is automatically populated based on the git commit time.
|
||||
|
||||
### contributors
|
||||
|
||||
- Type: `boolean | string | string[]`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display contributors for the current article. Contributors are automatically populated based on git committers.
|
||||
|
||||
If your article originates from a third party and git commits cannot fully list all authors, you can supplement contributors here.
|
||||
|
||||
For additional information, please refer to [contributors](../../guide/features/contributors.md#info).
|
||||
|
||||
### changelog
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Details:
|
||||
|
||||
Whether to display the page change history for the current page.
|
||||
|
||||
### copyright
|
||||
|
||||
- Type: `boolean | CopyrightLicense | CopyrightFrontmatter`
|
||||
- Default: `false`
|
||||
- Details:
|
||||
|
||||
Whether to display copyright information for the current article.
|
||||
|
||||
For complete information, please refer to [copyright](../../guide/features/copyright.md).
|
||||
|
||||
### editLink
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details:
|
||||
|
||||
Whether to display the article edit button for the current article.
|
||||
|
||||
### watermark
|
||||
|
||||
- Type: `boolean | WatermarkOptions`
|
||||
- Default: `undefined` (When the theme does not enable watermarks,
|
||||
or when global watermarks are not enabled, the default value is `false`. If global watermarks are enabled, the default is `true`.)
|
||||
- Details:
|
||||
Configure the watermark for the current article.
|
||||
|
||||
When the type is boolean, it indicates whether to enable the watermark.
|
||||
|
||||
When the type is WatermarkOptions, it represents the watermark configuration for the current page.
|
||||
|
||||
You can refer to [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/).
|
||||
|
||||
150
docs/en/config/frontmatter/friend.md
Normal file
150
docs/en/config/frontmatter/friend.md
Normal file
@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Friends Links Page
|
||||
createTime: 2025/10/09 18:00:52
|
||||
permalink: /en/config/frontmatter/friends/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Applicable to friends links pages.
|
||||
|
||||
Example:
|
||||
|
||||
```md
|
||||
---
|
||||
pageLayout: friends
|
||||
title: Friends Links
|
||||
list:
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: Guangzhou, China
|
||||
organization: VuePress
|
||||
desc: Even if slow, never stop. Even if falling behind, even if failing, one must be able to reach the goal they aspire to.
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
---
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### friends <Badge type="warning" text="Deprecated" />
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Details:
|
||||
|
||||
Whether the current page is a friends links page.
|
||||
|
||||
### pageLayout
|
||||
|
||||
- Type: `'friends'`
|
||||
- Details:
|
||||
|
||||
Declares the current page as a friends links page.
|
||||
|
||||
### title
|
||||
|
||||
- Type: `string`
|
||||
- Default: `Friends Links`
|
||||
|
||||
The title of the friends links page.
|
||||
|
||||
### description
|
||||
|
||||
- Type: `string`
|
||||
|
||||
The description of the friends links page.
|
||||
|
||||
### contentPosition <Badge text="New" />
|
||||
|
||||
- Type: `'before' | 'after'`
|
||||
- Default: `'after'`
|
||||
|
||||
Whether the markdown content is placed before or after the friends links list. By default, it is inserted after the list.
|
||||
|
||||
### list
|
||||
|
||||
- Type: `FriendsItem[]`
|
||||
- Default: `[]`
|
||||
|
||||
The friends links list.
|
||||
|
||||
```ts
|
||||
interface FriendsItem {
|
||||
/**
|
||||
* Friends link name
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* Friends link URL
|
||||
*/
|
||||
link: string
|
||||
/**
|
||||
* Friends link avatar
|
||||
*/
|
||||
avatar?: string
|
||||
/**
|
||||
* Friends link description
|
||||
*/
|
||||
desc?: string
|
||||
/**
|
||||
* Geographic location
|
||||
*/
|
||||
location?: string
|
||||
/**
|
||||
* Organization/Company
|
||||
*/
|
||||
organization?: string
|
||||
|
||||
/**
|
||||
* Social links
|
||||
*/
|
||||
socials?: SocialLink[]
|
||||
|
||||
/**
|
||||
* Background color
|
||||
*/
|
||||
backgroundColor?: string | { light: string, dark: string }
|
||||
/**
|
||||
* Font color
|
||||
*/
|
||||
color?: string | { light: string, dark: string }
|
||||
/**
|
||||
* Name color
|
||||
*/
|
||||
nameColor?: string | { light: string, dark: string }
|
||||
}
|
||||
```
|
||||
|
||||
For social link configuration, please refer to [Configuration/Theme Configuration/Social Links](../../config/theme.md#social).
|
||||
|
||||
### groups
|
||||
|
||||
- Type: `FriendsGroup[]`
|
||||
- Default: `[]`
|
||||
|
||||
Friends links grouping.
|
||||
|
||||
```ts
|
||||
interface FriendsGroup {
|
||||
/**
|
||||
* Group title
|
||||
*/
|
||||
title?: string
|
||||
/**
|
||||
* Group description
|
||||
*/
|
||||
desc?: string
|
||||
/**
|
||||
* Friends links list
|
||||
*/
|
||||
list?: FriendsItem[]
|
||||
}
|
||||
```
|
||||
76
docs/en/config/frontmatter/home.md
Normal file
76
docs/en/config/frontmatter/home.md
Normal file
@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Homepage
|
||||
createTime: 2025/10/09 15:00:43
|
||||
permalink: /en/config/frontmatter/home/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Applicable only to the homepage. Configure in `{sourceDir}/README.md`.
|
||||
|
||||
Example:
|
||||
|
||||
```md
|
||||
---
|
||||
pageLayout: home
|
||||
config:
|
||||
- type: banner
|
||||
- type: custom
|
||||
---
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### home <Badge type="warning" text="Deprecated" />
|
||||
|
||||
- Type: `boolean`
|
||||
- Details:
|
||||
|
||||
Declares whether the page is the homepage.
|
||||
|
||||
Deprecated. Please use `pageLayout: 'home'` instead.
|
||||
|
||||
### pageLayout
|
||||
|
||||
- Type: `'home'`
|
||||
- Details:
|
||||
|
||||
Declares the current page as the homepage.
|
||||
|
||||
### config
|
||||
|
||||
- Type: `PlumeHomeConfig[]`
|
||||
|
||||
Defines homepage sections.
|
||||
|
||||
```ts
|
||||
interface PlumeHomeConfigBase {
|
||||
/**
|
||||
* The type of this section, which determines the component to be applied
|
||||
*/
|
||||
type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom' | string
|
||||
/**
|
||||
* Whether this section should be full-screen
|
||||
*/
|
||||
full?: boolean
|
||||
/**
|
||||
* Background image for this section
|
||||
* You can define background images for light/dark modes
|
||||
*/
|
||||
backgroundImage?: string | { light: string, dark: string }
|
||||
/**
|
||||
* Background attachment style for this section
|
||||
*/
|
||||
backgroundAttachment?: 'fixed' | 'local'
|
||||
}
|
||||
```
|
||||
|
||||
For more detailed configuration, please refer to [Custom Homepage](../../guide/custom/home.md).
|
||||
|
||||
### signDown
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
- Details:
|
||||
|
||||
Whether to display the downward arrow indicator.
|
||||
95
docs/en/config/frontmatter/post.md
Normal file
95
docs/en/config/frontmatter/post.md
Normal file
@ -0,0 +1,95 @@
|
||||
---
|
||||
title: Posts Article
|
||||
createTime: 2025/10/09 11:01:03
|
||||
permalink: /en/config/frontmatter/article/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Applicable to articles with collection type set to 'post'.
|
||||
|
||||
Example:
|
||||
|
||||
```md
|
||||
---
|
||||
title: Article Title
|
||||
tags:
|
||||
- tag1
|
||||
- tag2
|
||||
---
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### sticky
|
||||
|
||||
- Type: `boolean | number`
|
||||
- Default: `false`
|
||||
|
||||
Whether to pin the current article to the top in article lists.
|
||||
|
||||
If a `number` is provided, a higher value will position the article closer to the top when pinned.
|
||||
|
||||
### article
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
|
||||
Whether to display the current article in article lists.
|
||||
|
||||
### draft
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `false`
|
||||
|
||||
Marks the article as a draft. Articles marked as drafts **only appear in article lists during development** and are hidden in production environments.
|
||||
|
||||
### tags
|
||||
|
||||
- Type: `string[]`
|
||||
- Default: `[]`
|
||||
|
||||
Article tags.
|
||||
|
||||
### cover
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
|
||||
Article cover image. The cover image is only displayed on the article list page.
|
||||
|
||||
Only absolute paths and remote image URLs are supported.
|
||||
|
||||
### coverStyle
|
||||
|
||||
- Type: `BlogPostCoverStyle`
|
||||
- Default: `null`
|
||||
|
||||
Cover image configuration.
|
||||
|
||||
```ts
|
||||
interface PostCoverStyle {
|
||||
/**
|
||||
* Layout position of the blog post cover image
|
||||
*/
|
||||
layout?: 'left' | 'right' | 'odd-left' | 'odd-right' | 'top'
|
||||
/**
|
||||
* Aspect ratio of the blog post cover image
|
||||
*
|
||||
* @default '4:3'
|
||||
*/
|
||||
ratio?: number | `${number}:${number}`
|
||||
|
||||
/**
|
||||
* Width of the cover image, only effective when layout is 'left' or 'right'
|
||||
*
|
||||
* @default 240
|
||||
*/
|
||||
width?: number
|
||||
/**
|
||||
* Whether to use compact mode. In compact mode, the cover image fits snugly against the container edge.
|
||||
* @default false
|
||||
*/
|
||||
compact?: boolean
|
||||
}
|
||||
```
|
||||
@ -1,7 +1,180 @@
|
||||
---
|
||||
title: Configuration
|
||||
createTime: 2024/03/02 10:48:14
|
||||
title: Configuration Guide
|
||||
createTime: 2025/10/09 10:48:14
|
||||
permalink: /en/config/intro/
|
||||
---
|
||||
|
||||
Todo...
|
||||
## Overview
|
||||
|
||||
==vuepress-theme-plume== is a theme developed based on [VuePress](https://v2.vuepress.vuejs.org/),
|
||||
and its configuration fully adheres to VuePress's configuration specifications.
|
||||
|
||||
**VuePress provides three configuration types:**
|
||||
|
||||
- **Site Configuration**: The object directly exported from the configuration file (e.g., `.vuepress/config.ts`)
|
||||
- **Theme Configuration**: The parameter object passed to the `plumeTheme()` function
|
||||
- **Page Configuration**: Defined in the page Frontmatter using YAML syntax
|
||||
|
||||
## VuePress Configuration File
|
||||
|
||||
The base configuration file for VuePress is typically `.vuepress/config.js`,
|
||||
while TypeScript configuration files are also supported.
|
||||
Using `.vuepress/config.ts` provides more comprehensive type hints.
|
||||
|
||||
VuePress resolves configuration files in the following priority order:
|
||||
|
||||
**In the current working directory (cwd):**
|
||||
|
||||
- `vuepress.config.ts`
|
||||
- `vuepress.config.js`
|
||||
- `vuepress.config.mjs`
|
||||
|
||||
**In the source directory (sourceDir):**
|
||||
|
||||
- `.vuepress/config.ts` <Badge type="tip" text="Recommended" />
|
||||
- `.vuepress/config.js`
|
||||
- `.vuepress/config.mjs`
|
||||
|
||||
**Basic Configuration Example:**
|
||||
|
||||
```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 Base Configuration
|
||||
lang: 'zh-CN',
|
||||
title: 'Hello, VuePress!',
|
||||
description: 'This is my first VuePress site',
|
||||
// ...
|
||||
|
||||
// Use Vite as the bundler
|
||||
bundler: viteBundler(),
|
||||
|
||||
// Enable the Plume theme
|
||||
theme: plumeTheme({ // [!code ++:4]
|
||||
// Theme configuration options
|
||||
// ...
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Theme Configuration File
|
||||
|
||||
Typically, we configure the theme in `.vuepress/config.ts`:
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Theme configuration
|
||||
}),
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
However, modifying this file causes the VuePress service to restart and perform a full refresh.
|
||||
For small sites, this process is quick; but for sites with substantial content, each restart requires considerable time.
|
||||
|
||||
Frequent configuration file modifications can also easily lead to VuePress ==service crashes=={.caution}
|
||||
::twemoji:angry-face::, requiring manual service restarts and severely impacting content writing efficiency.
|
||||
|
||||
**Solution: Theme Hot-Reload Configuration:**
|
||||
|
||||
The theme provides a `plume.config.ts` configuration file. ==Modifications to this file support hot-reload
|
||||
and do not require restarting the service=={.tip} ::twemoji:confetti-ball::.
|
||||
|
||||
You can configure hot-reload supported fields within it, such as `navbar`, `profile`, etc.
|
||||
|
||||
::: tip
|
||||
These fields can still be configured within the `theme` section of the VuePress configuration file,
|
||||
but the settings from the theme configuration file will ultimately be merged into the main configuration.
|
||||
|
||||
To avoid data duplication, please do not configure the same field in both locations.
|
||||
:::
|
||||
|
||||
::: details What is Hot-Reload?
|
||||
|
||||
**Hot-Reload** is a development technique that, in the context of VuePress, manifests as:
|
||||
|
||||
- Configuration changes take effect immediately without restarting the service; the browser does not refresh the page
|
||||
- Page modifications take effect immediately; the browser updates content without a full refresh
|
||||
|
||||
:::
|
||||
|
||||
### Configuration Method
|
||||
|
||||
Create the `plume.config.ts` file in the same directory as the VuePress configuration file:
|
||||
|
||||
::: 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({
|
||||
// Theme configuration
|
||||
profile: {
|
||||
name: 'Your name',
|
||||
},
|
||||
navbar,
|
||||
})
|
||||
```
|
||||
|
||||
The `defineThemeConfig(config)` function provides full type hints. Except for `plugins`, most configurations can be defined in this file.
|
||||
|
||||
::: warning Notes
|
||||
|
||||
- The theme configuration file only supports hot-reload for specific fields.
|
||||
- Avoid reconfiguring fields in the VuePress configuration file that have already been set in the theme configuration file.
|
||||
:::
|
||||
|
||||
### Custom Configuration File Path
|
||||
|
||||
If a non-default path is required, it can be specified in the VuePress configuration:
|
||||
|
||||
```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({
|
||||
// Custom configuration file path
|
||||
configFile: path.join(__dirname, 'custom/config.ts'), // [!code ++]
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
::: warning Not recommended for beginners; custom paths might cause unexpected issues.
|
||||
:::
|
||||
|
||||
## Page Configuration
|
||||
|
||||
Using the YAML Frontmatter at the top of the page, the theme can be configured individually for each page:
|
||||
|
||||
```md {1,5} title="article.md"
|
||||
---
|
||||
title: Article Title
|
||||
createTime: 2024/09/08 22:53:34
|
||||
permalink: /article/xxx/
|
||||
---
|
||||
```
|
||||
|
||||
The section wrapped by the `---` delimiters at the top of a Markdown file is the Frontmatter, which uses YAML syntax for configuration.
|
||||
|
||||
:::tip For an introduction to basic YAML syntax, please refer to [this blog post](/article/ecxnxxd0/)
|
||||
:::
|
||||
|
||||
@ -1,7 +1,283 @@
|
||||
---
|
||||
title: Multilingual Configuration
|
||||
createTime: 2025/03/04 13:23:51
|
||||
title: Locales Configuration
|
||||
createTime: 2025/10/09 10:07:15
|
||||
permalink: /en/config/locales/
|
||||
---
|
||||
|
||||
todo ...
|
||||
These options are used to configure language-related text.
|
||||
|
||||
If your site is served in languages other than the built-in supported languages, you should set these options for each language to provide translations.
|
||||
|
||||
## Built-in Language Support
|
||||
|
||||
The theme has built-in support for the following languages:
|
||||
|
||||
- Simplified Chinese (`zh-CN`) - `/zh/`
|
||||
- Traditional Chinese (`zh-TW`) - `/zh-tw/`
|
||||
- English (`en-US`) - `/en/`
|
||||
- French (`fr-FR`) - `/fr/`
|
||||
- German (`de-DE`) - `/de/`
|
||||
- Russian (`ru-RU`) - `/ru/`
|
||||
- Japanese (`ja-JP`) - `/ja/`
|
||||
- Korean (`ko-KR`) - `/ko/`
|
||||
|
||||
## Configuration
|
||||
|
||||
You should write the configuration in `theme.locales`.
|
||||
|
||||
You can configure it in `.vuepress/config.ts`, or in `.vuepress/plume.config.ts`:
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
locales: {
|
||||
// Language code for non-built-in languages
|
||||
'/xxx/': {
|
||||
// Language configuration
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
locales: {
|
||||
// Language code for non-built-in languages
|
||||
'/xxx/': {
|
||||
// Language configuration
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
For detailed configuration methods, please refer to: [Internationalization](../guide/quick-start/locales.md)
|
||||
|
||||
### appearanceText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Appearance'`
|
||||
- Details: The text for the theme toggle button in the navigation bar.
|
||||
|
||||
### selectLanguageName
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
The language name for the locale.
|
||||
|
||||
This configuration item **only takes effect inside the [locales](./theme.md#locales) of the theme configuration**.
|
||||
It will be used as the language name for the locale, displayed in the _Select Language Menu_.
|
||||
|
||||
### selectLanguageText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
The text for the _Select Language Menu_.
|
||||
|
||||
If you set multiple [locales](./theme.md#locales) in the site configuration,
|
||||
the _Select Language Menu_ will be displayed next to the repository button in the navigation bar.
|
||||
|
||||
### selectLanguageAriaLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `''`
|
||||
- Details:
|
||||
|
||||
The `aria-label` attribute for the _Select language menu_.
|
||||
|
||||
It is primarily for site accessibility (a11y).
|
||||
|
||||
### homeText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Home'`
|
||||
- Details: The text for the home link.
|
||||
|
||||
- The text for the home link in the theme's default navigation bar.
|
||||
- The text for the home link in breadcrumb navigation.
|
||||
|
||||
### postsText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Posts'`
|
||||
- Details: The text for the posts list page link.
|
||||
|
||||
- The text for the posts list page link in the theme's default navigation bar.
|
||||
- The text for the posts list page link in breadcrumb navigation.
|
||||
|
||||
### tagText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Tags'`
|
||||
- Details: The text for the tags link.
|
||||
|
||||
- The text for the tags link in the theme's default navigation bar.
|
||||
- The text for the tags link on blog pages.
|
||||
- The title on the blog tags page.
|
||||
|
||||
### categoryText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Categories'`
|
||||
- Details: The text for the categories link.
|
||||
|
||||
- The text for the categories link in the theme's default navigation bar.
|
||||
- The text for the categories link on blog pages.
|
||||
- The title on the blog categories page.
|
||||
|
||||
### archiveText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Archives'`
|
||||
- Details: The text for the archives link.
|
||||
|
||||
- The text for the archives link in the theme's default navigation bar.
|
||||
- The text for the archives link on blog pages.
|
||||
- The title on the blog archives page.
|
||||
|
||||
### archiveTotalText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'{count} articles'`
|
||||
- Details: The text for the total article count on the archives page.
|
||||
|
||||
### sidebarMenuLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Menu'`
|
||||
- Details:
|
||||
|
||||
The text for the menu option in the navigation bar on mobile devices.
|
||||
|
||||
### returnToTopLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'return to top'`
|
||||
- Details:
|
||||
|
||||
The text for returning to the top in the navigation bar on mobile devices.
|
||||
|
||||
### outlineLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'On this page'`
|
||||
- Details:
|
||||
|
||||
The text for the outline title in the navigation bar on mobile devices.
|
||||
|
||||
### editLinkText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Edit this page'`
|
||||
- Details: The edit link text.
|
||||
|
||||
### latestUpdatedText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Latest Updated'`
|
||||
- Details: The text for "Latest Updated".
|
||||
|
||||
### contributorsText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Contributors'`
|
||||
- Details: The text for contributors.
|
||||
|
||||
### changelogText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Changelog'`
|
||||
- Details: The text for changelog.
|
||||
|
||||
### changelogOnText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'On'`
|
||||
- Details: The time text for a single changelog entry.
|
||||
|
||||
### changelogButtonText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'View All Changelog'`
|
||||
- Details: The button text for changelog.
|
||||
|
||||
### copyrightText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Copyright'`
|
||||
- Details: The text for copyright.
|
||||
|
||||
### copyrightAuthorText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Copyright Ownership:'`
|
||||
- Details: The text for copyright owner.
|
||||
|
||||
### copyrightCreationOriginalText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'This article link:'`
|
||||
- Details: The text for "This article link".
|
||||
|
||||
### copyrightCreationTranslateText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'This article translated from:'`
|
||||
- Details: The text for "This article translated from".
|
||||
|
||||
### copyrightCreationReprintText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'This article reprint from:'`
|
||||
- Details: The text for "This article reprint from".
|
||||
|
||||
### copyrightLicenseText
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'License under:'`
|
||||
- Details: The text for copyright license.
|
||||
|
||||
### prevPageLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Previous Page'`
|
||||
- Details: The text for previous page.
|
||||
|
||||
### nextPageLabel
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'Next Page'`
|
||||
- Details: The text for next page.
|
||||
|
||||
### notFound
|
||||
|
||||
- Type: `NotFound | undefined`
|
||||
- Default: `undefined`
|
||||
- Details: 404 page configuration.
|
||||
|
||||
```ts
|
||||
interface NotFound {
|
||||
code?: string
|
||||
title?: string
|
||||
quote?: string
|
||||
linkLabel?: string
|
||||
linkText?: string
|
||||
}
|
||||
```
|
||||
|
||||
313
docs/en/config/markdown.md
Normal file
313
docs/en/config/markdown.md
Normal file
@ -0,0 +1,313 @@
|
||||
---
|
||||
title: Markdown Configuration
|
||||
createTime: 2025/10/09 14:54:19
|
||||
permalink: /en/config/markdown/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Markdown configuration is used to control the behavior of Markdown.
|
||||
This configuration aggregates various feature configurations provided by the theme for Markdown enhancements.
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// [!code ++:3]
|
||||
markdown: {
|
||||
// Configure markdown here
|
||||
},
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
::: warning
|
||||
Do not confuse this with VuePress's [markdown](https://v2.vuepress.vuejs.org/reference/config.html#markdown) configuration.
|
||||
|
||||
These two are independent. Do not configure the theme's markdown settings
|
||||
within [VuePress > markdown](https://v2.vuepress.vuejs.org/reference/config.html#markdown), and vice versa.
|
||||
:::
|
||||
|
||||
**Default Configuration:**
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// [!code focus:11]
|
||||
markdown: {
|
||||
hint: true,
|
||||
alert: true,
|
||||
fileTree: true,
|
||||
plot: true,
|
||||
icons: true,
|
||||
math: { type: 'katex' },
|
||||
include: {
|
||||
// ...option
|
||||
},
|
||||
},
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
::: tip
|
||||
The `hint` and `alert` features are implemented by
|
||||
the [@vuepress/plugin-markdown-hint](https://ecosystem.vuejs.press/plugins/markdown/markdown-hint.html) plugin.
|
||||
:::
|
||||
|
||||
### hint
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable hint containers.
|
||||
|
||||
### alert
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable GitHub-style alert syntax.
|
||||
|
||||
---
|
||||
|
||||
::: tip
|
||||
The `image` configuration is implemented by the
|
||||
[@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/plugins/markdown/markdown-image.html) plugin.
|
||||
:::
|
||||
|
||||
### image
|
||||
|
||||
- **Type:** `boolean | MarkdownImagePluginOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable image enhancement syntax.
|
||||
|
||||
---
|
||||
|
||||
::: tip
|
||||
The `math` configuration is implemented by the
|
||||
[@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/plugins/markdown/markdown-math.html) plugin.
|
||||
:::
|
||||
|
||||
### math
|
||||
|
||||
- **Type:** `boolean | MarkdownMathPluginOptions`
|
||||
- **Default:** `{ type: 'katex' }`
|
||||
- **Details:** Whether to enable math support.
|
||||
|
||||
---
|
||||
|
||||
### include
|
||||
|
||||
::: tip
|
||||
The `include` configuration is implemented by the
|
||||
[@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/plugins/markdown/markdown-include.html) plugin.
|
||||
:::
|
||||
|
||||
- **Type:** `boolean | MarkdownIncludePluginOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable Markdown file inclusion.
|
||||
|
||||
---
|
||||
|
||||
::: tip The following configuration fields are implemented by the [vuepress-plugin-md-power](./plugins/markdown-power.md) plugin.
|
||||
:::
|
||||
|
||||
### annotation
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable content annotations.
|
||||
|
||||
### abbr
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable abbreviation syntax.
|
||||
|
||||
### codeTabs
|
||||
|
||||
- **Type:** `boolean | CodeTabsOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable code block grouping.
|
||||
|
||||
### tabs
|
||||
|
||||
- **Type:** `boolean | TabsOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable grouping.
|
||||
|
||||
### npmTo
|
||||
|
||||
- **Type:** `boolean | NpmToOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable the `npm-to` container.
|
||||
|
||||
### icon
|
||||
|
||||
- **Type:** `IconOptions`
|
||||
- **Default:** `{ provider: 'iconify' }`
|
||||
- **Details:** Icon configuration.
|
||||
|
||||
[View **icon** usage instructions](../../theme/guide/features/icon.md){.read-more}
|
||||
|
||||
### plot
|
||||
|
||||
- **Type:** `boolean | PlotOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable hidden text syntax.
|
||||
|
||||
### fileTree
|
||||
|
||||
- **Type:** `boolean | FileTreeOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable file tree container syntax.
|
||||
|
||||
### field
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable field containers.
|
||||
|
||||
### table
|
||||
|
||||
- **Type:** `boolean | TableContainerOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable enhanced table containers.
|
||||
|
||||
### timeline
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable timeline container syntax.
|
||||
|
||||
### collapse
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable collapsible panel container syntax.
|
||||
|
||||
### chat
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable chat record containers.
|
||||
|
||||
### demo
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Demo containers.
|
||||
|
||||
### pdf
|
||||
|
||||
- **Type:** `boolean | PdfOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable PDF embedding syntax.
|
||||
|
||||
### bilibili
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Bilibili video embedding syntax.
|
||||
|
||||
### youtube
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable YouTube video embedding syntax.
|
||||
|
||||
### artPlayer
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable ArtPlayer video embedding syntax.
|
||||
|
||||
### audioReader
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Audio Reader audio embedding syntax.
|
||||
|
||||
### codepen
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable CodePen embedding syntax.
|
||||
|
||||
### codeSandbox
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable CodeSandbox embedding syntax.
|
||||
|
||||
### jsfiddle
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable JS Fiddle embedding syntax.
|
||||
|
||||
### repl
|
||||
|
||||
- **Type:** `boolean | ReplOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Repl container syntax.
|
||||
|
||||
### caniuse
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Can I Use embedding syntax.
|
||||
|
||||
### imageSize
|
||||
|
||||
- **Type:** `boolean | 'local' | 'all'`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable automatic filling of image width and height attributes.
|
||||
|
||||
---
|
||||
|
||||
::: tip
|
||||
The following configuration fields are implemented by the
|
||||
[@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) plugin.
|
||||
:::
|
||||
|
||||
### chartjs
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Chart.js chart embedding syntax.
|
||||
|
||||
### echarts
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable ECharts chart embedding syntax.
|
||||
|
||||
### mermaid
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Mermaid diagram embedding syntax.
|
||||
|
||||
### markmap
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Markmap diagram embedding syntax.
|
||||
|
||||
### plantuml
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable PlantUML diagram embedding syntax.
|
||||
|
||||
### flowchart
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to enable Flowchart diagram embedding syntax.
|
||||
251
docs/en/config/navbar.md
Normal file
251
docs/en/config/navbar.md
Normal file
@ -0,0 +1,251 @@
|
||||
---
|
||||
title: Navbar Configuration
|
||||
createTime: 2025/10/09 15:07:33
|
||||
permalink: /en/config/navigation/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
::: tip Navbar configuration can be set in either `.vuepress/config.ts` or `plume.config.ts`.
|
||||
:::
|
||||
|
||||
The theme automatically generates the simplest navbar configuration by default, including only the **Home** and **Blog List** pages.
|
||||
|
||||
You can also configure the navbar yourself to override the default configuration.
|
||||
|
||||
The default configuration is as follows:
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
navbar: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Blog', link: '/blog/' },
|
||||
{ text: 'Tags', link: '/blog/tags/' },
|
||||
{ text: 'Archives', link: '/blog/archives/' }
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
navbar: [
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Blog', link: '/blog/' },
|
||||
{ text: 'Tags', link: '/blog/tags/' },
|
||||
{ text: 'Archives', link: '/blog/archives/' }
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
When multi-language configuration is enabled, the default navbar configuration for the corresponding languages will be generated:
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
lang: 'zh-CN',
|
||||
locales: {
|
||||
'/': { lang: 'zh-CN', title: '博客' }, // Simplified Chinese
|
||||
'/en/': { lang: 'en-US', title: 'Blog' }, // English
|
||||
},
|
||||
theme: plumeTheme({
|
||||
locales: {
|
||||
'/': {
|
||||
navbar: [
|
||||
{ text: '首页', link: '/' },
|
||||
{ text: '博客', link: '/blog/' },
|
||||
{ text: '标签', link: '/blog/tags/' },
|
||||
{ text: '归档', link: '/blog/archives/' }
|
||||
]
|
||||
},
|
||||
'/en/': {
|
||||
navbar: [
|
||||
{ text: 'Home', link: '/en/' },
|
||||
{ text: 'Blog', link: '/en/blog/' },
|
||||
{ text: 'Tags', link: '/en/blog/tags/' },
|
||||
{ text: 'Archives', link: '/en/blog/archives/' }
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
As your site content becomes richer, for example, when configuring collections for blog, notes, documentation,
|
||||
friend links, external links, etc., the default generated navbar configuration may no longer meet your needs.
|
||||
|
||||
At this point, you can fully customize the navbar using the `navbar` field, which will directly override the default navbar configuration.
|
||||
|
||||
## Configuration
|
||||
|
||||
Type: `NavItem[]`
|
||||
|
||||
```ts
|
||||
interface ThemeBadge {
|
||||
/* Badge text */
|
||||
text?: string
|
||||
/* Badge type, built-in: 'info' | 'tip' | 'danger' | 'warning' */
|
||||
type?: string
|
||||
/* Text color */
|
||||
color?: string
|
||||
/* Background color */
|
||||
bgColor?: string
|
||||
/* Border color */
|
||||
borderColor?: string
|
||||
}
|
||||
|
||||
type NavItem = string | {
|
||||
/**
|
||||
* Navbar text
|
||||
*/
|
||||
text: string
|
||||
/**
|
||||
* Navbar link
|
||||
* - Can be an external link
|
||||
* - Can be a permalink from frontmatter
|
||||
* - Can be a relative path to a markdown file (relative to `sourceDir`), must start with `/`
|
||||
*/
|
||||
link: string
|
||||
/**
|
||||
* Icon name, or SVG icon
|
||||
*/
|
||||
icon?: string | { svg: string }
|
||||
|
||||
/**
|
||||
* Badge, supports custom badge styles
|
||||
*/
|
||||
badge?: string | ThemeBadge
|
||||
/**
|
||||
* Controls when the element is activated
|
||||
*/
|
||||
activeMatch?: string
|
||||
/**
|
||||
* Prefix for the current group of page links
|
||||
*/
|
||||
prefix?: string
|
||||
/**
|
||||
* Nested navbar items, maximum depth is 2
|
||||
*/
|
||||
items?: NavItem[]
|
||||
}
|
||||
```
|
||||
|
||||
### Nested Configuration Example
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
navbar: [
|
||||
{ text: 'Home', link: '/', icon: 'material-symbols:home-outline' },
|
||||
{ text: 'Blog', link: '/blog/', icon: 'material-symbols:article-outline' },
|
||||
{
|
||||
text: 'Technical Docs',
|
||||
icon: 'mdi:idea',
|
||||
items: [
|
||||
{
|
||||
text: 'Vuepress Theme',
|
||||
icon: 'icon-park-solid:theme',
|
||||
items: [
|
||||
{
|
||||
text: 'vuepress-theme-plume',
|
||||
link: '/vuepress-theme-plume/',
|
||||
icon: 'mdi:paper-airplane',
|
||||
badge: 'Badge'
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Vuepress Plugin',
|
||||
icon: 'mingcute:plugin-2-fill',
|
||||
badge: { text: 'Badge', type: 'warning' },
|
||||
items: [
|
||||
{
|
||||
text: 'caniuse',
|
||||
link: '/vuepress-plugin/caniuse/',
|
||||
icon: 'pajamas:feature-flag',
|
||||
},
|
||||
{
|
||||
text: 'auto-frontmatter',
|
||||
link: '/vuepress-plugin/auto-frontmatter/',
|
||||
icon: 'material-symbols:move-selection-down-rounded',
|
||||
},
|
||||
{
|
||||
text: 'blog-data',
|
||||
link: '/vuepress-plugin/blog-data/',
|
||||
icon: 'ic:baseline-post-add',
|
||||
},
|
||||
{
|
||||
text: 'notes-data',
|
||||
link: '/vuepress-plugin/notes-data/',
|
||||
icon: 'material-symbols:note-alt-rounded',
|
||||
},
|
||||
{
|
||||
text: 'shiki',
|
||||
link: '/vuepress-plugin/shiki/',
|
||||
icon: 'material-symbols-light:code-blocks-outline-rounded',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### `activeMatch`
|
||||
|
||||
`activeMatch` is used to control when the current link element is activated. Its value is a regex-like string.
|
||||
|
||||
**Example:** `activeMatch: '^/(blog|article)/'`
|
||||
|
||||
This means that for page links starting with `/blog/` or `/article/`, this link element will be activated.
|
||||
|
||||
### Icons
|
||||
|
||||
Supports icons from sources configured via [markdown -> icon](../guide/features/icon.md).
|
||||
|
||||
- When `markdown.icon.provide` is `iconify`, [iconify](https://iconify.design/) icons are supported
|
||||
- When `markdown.icon.provide` is `iconfont`, [iconfont](https://www.iconfont.cn/) icons are supported
|
||||
- When `markdown.icon.provide` is `fontawesome`, [fontawesome](https://fontawesome.com/) icons are supported
|
||||
|
||||
When `markdown.icon.provide` is not `iconify`, you can prefix the icon name with `iconify` to force the
|
||||
use of [iconify](https://iconify.design/) icons.
|
||||
|
||||
```ts
|
||||
const item = { text: 'Home', link: '/', icon: 'iconify carbon:home' }
|
||||
```
|
||||
|
||||
## Configuration Helper Function
|
||||
|
||||
The theme provides the `defineNavbarConfig(config)` function to offer type assistance for the navbar
|
||||
configuration to theme users. This facilitates separating the `navbar` configuration into an independent configuration file.
|
||||
|
||||
```ts title="navbar.ts" twoslash
|
||||
import { defineNavbarConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineNavbarConfig([
|
||||
{ text: 'Home', link: '/' },
|
||||
{ text: 'Blog', link: '/blog/' },
|
||||
// ... more
|
||||
])
|
||||
```
|
||||
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Notes Configuration
|
||||
createTime: 2025/03/03 14:44:18
|
||||
permalink: /en/config/notes/
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Auto Generated Sidebar
|
||||
|
||||
todo ...
|
||||
54
docs/en/config/plugins/README.md
Normal file
54
docs/en/config/plugins/README.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Introduction
|
||||
createTime: 2025/10/09 8:26:44
|
||||
permalink: /en/config/plugins/
|
||||
---
|
||||
|
||||
The theme comes with built-in plugins that extend its numerous functionalities.
|
||||
You can configure these internal plugins through the `plugins` option.
|
||||
|
||||
## Configuration
|
||||
|
||||
All plugins used internally by the theme are configured within the `plugins` field.
|
||||
|
||||
``` js title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: {
|
||||
// more options... // [!code ++]
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Plugin List
|
||||
|
||||
- [@vuepress/plugin-nprogress](https://ecosystem.vuejs.press/zh/plugins/features/nprogress.html) - Page loading progress bar
|
||||
- [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/zh/plugins/features/photo-swipe.html) - Image preview
|
||||
- [@vuepress/plugin-reading-time](https://ecosystem.vuejs.press/zh/plugins/development/reading-time.html) - Article reading time
|
||||
- [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html) - Article watermark
|
||||
- [@vuepress-plume/plugin-search](./search.md) - Local search
|
||||
- [@vuepress/plugin-docsearch](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html) - Algolia documentation search
|
||||
- [@vuepress/plugin-copy-code](https://ecosystem.vuejs.press/zh/plugins/features/copy-code.html) - Code copy
|
||||
- [@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html) - Syntax highlighting
|
||||
- [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) - Article comments
|
||||
- [@vuepress/plugin-markdown-hint](https://ecosystem.vuejs.press/zh/plugins/markdown/hint.html) - Markdown hints
|
||||
- [@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/zh/plugins/markdown/image.html) - Markdown images
|
||||
- [@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/zh/plugins/markdown/math.html) - Markdown mathematical formulas
|
||||
- [@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/zh/plugins/markdown/include.html) - Markdown file inclusion
|
||||
- [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-chart/) - Markdown charts
|
||||
chartjs / echarts / mermaid / flowchart / markmap / plantUML
|
||||
- [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/zh/plugins/tools/replace-assets.html) - Asset link replacement
|
||||
- [vuepress-plugin-md-power](./markdown-power.md) - Markdown Power
|
||||
- [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) - Git commit information
|
||||
- [@vuepress/plugin-cache](https://ecosystem.vuejs.press/zh/plugins/tools/cache.html) - Page compilation cache
|
||||
- [@vuepress/plugin-seo](https://ecosystem.vuejs.press/zh/plugins/seo/seo/) - SEO optimization
|
||||
- [@vuepress/plugin-sitemap](https://ecosystem.vuejs.press/zh/plugins/seo/sitemap/) - Sitemap
|
||||
|
||||
:::tip
|
||||
You don't need to install these built-in plugins separately, nor should you add them to [vuepress config > plugins](https://v2.vuepress.vuejs.org/zh/reference/config.html#plugins).
|
||||
The theme has already handled their integration internally.
|
||||
:::
|
||||
45
docs/en/config/plugins/markdown-enhance.md
Normal file
45
docs/en/config/plugins/markdown-enhance.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Markdown Enhance
|
||||
createTime: 2025/10/09 20:25:36
|
||||
permalink: /en/config/plugins/markdown-enhance/
|
||||
badge:
|
||||
type: danger
|
||||
text: Deprecated
|
||||
---
|
||||
|
||||
::: danger Removed from theme starting from `1.0.0-rc.154`
|
||||
The functionality provided by [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/) that
|
||||
was explicitly supported in the theme has been migrated to other plugins in the
|
||||
`vuepress/ecosystem` repository. Therefore, the theme will safely remove the `vuepress-plugin-md-enhance` plugin starting from `1.0.0-rc.154`.
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
Provides Markdown enhancement features.
|
||||
|
||||
Related plugin: [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/)
|
||||
|
||||
Default configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
// The following options are not enabled by default in the theme,
|
||||
// Please configure them explicitly in the theme if needed
|
||||
// stylize: true, // Style inline syntax to create code snippets
|
||||
// playground: true, // Interactive playgrounds
|
||||
// kotlinPlayground: true, // Kotlin interactive playgrounds
|
||||
// vuePlayground: true, // Vue interactive playgrounds
|
||||
// sandpack: true, // Sandpack interactive playgrounds
|
||||
},
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
For detailed configuration, please refer to [vuepress-plugin-md-enhance](https://plugin-md-enhance.vuejs.press/config.html).
|
||||
44
docs/en/config/plugins/markdown-image.md
Normal file
44
docs/en/config/plugins/markdown-image.md
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Markdown Image
|
||||
createTime: 2025/10/09 12:06:28
|
||||
permalink: /en/config/plugins/markdown-image/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Adds additional features for Markdown images.
|
||||
|
||||
Related plugin: [@vuepress/plugin-markdown-image](https://ecosystem.vuejs.press/plugins/markdown/markdown-image.html)
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin does not enable any features by default; you need to enable them manually.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
image: {
|
||||
// Enable figure
|
||||
// figure: true,
|
||||
|
||||
// Enable image lazy loading
|
||||
// lazyload: true,
|
||||
|
||||
// Enable image marking
|
||||
// mark: true,
|
||||
|
||||
// Enable image dimensions
|
||||
// size: true,
|
||||
}
|
||||
},
|
||||
// Can also be configured in `plugins.markdownImage`, but not recommended
|
||||
plugins: {
|
||||
markdownImage: {}
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
60
docs/en/config/plugins/markdown-include.md
Normal file
60
docs/en/config/plugins/markdown-include.md
Normal file
@ -0,0 +1,60 @@
|
||||
---
|
||||
title: Markdown Include
|
||||
createTime: 2025/10/09 12:01:58
|
||||
permalink: /en/config/plugins/markdown-include/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Import content from other markdown files within Markdown files.
|
||||
|
||||
Related plugin: [@vuepress/plugin-markdown-include](https://ecosystem.vuejs.press/plugins/markdown/markdown-include.html)
|
||||
|
||||
## Configuration
|
||||
|
||||
The theme enables `markdownInclude` by default. You can further customize its behavior through configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
include: {
|
||||
// ... options
|
||||
}
|
||||
},
|
||||
// Can also be configured in `plugins.markdownInclude`, but not recommended
|
||||
plugins: {
|
||||
markdownInclude: {},
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### resolvePath
|
||||
|
||||
- Type: `(path: string, cwd: string | null) => string`
|
||||
- Default: `(path) => path`
|
||||
- Details: Processes the include file path.
|
||||
|
||||
### deep
|
||||
|
||||
- Type: `boolean`
|
||||
- Details: Whether to enable deep include support.
|
||||
|
||||
### useComment
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details: Whether to use `<!-- @include: xxx -->` instead of `@include: xxx` for file inclusion.
|
||||
|
||||
### resolveImagePath
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details: Whether to resolve relative image paths within the included Markdown files.
|
||||
|
||||
### resolveLinkPath
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Details: Whether to resolve relative file paths within the included Markdown files.
|
||||
36
docs/en/config/plugins/markdown-math.md
Normal file
36
docs/en/config/plugins/markdown-math.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Markdown Math
|
||||
createTime: 2025/10/09 13:20:41
|
||||
permalink: /en/config/plugins/markdown-math/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Adds mathematical formula support for Markdown.
|
||||
|
||||
Related plugin: [@vuepress/plugin-markdown-math](https://ecosystem.vuejs.press/plugins/markdown/markdown-math.html)
|
||||
|
||||
This plugin allows you to render $\TeX$ content in Markdown using MathJax or KaTeX.
|
||||
|
||||
## Configuration
|
||||
|
||||
The plugin enables `katex` by default.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
math: {
|
||||
type: 'katex',
|
||||
}
|
||||
},
|
||||
// Can also be configured in `plugins.markdownMath`, but not recommended
|
||||
plugins: {
|
||||
markdownMath: {}
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
272
docs/en/config/plugins/markdown-power.md
Normal file
272
docs/en/config/plugins/markdown-power.md
Normal file
@ -0,0 +1,272 @@
|
||||
---
|
||||
title: Markdown Power
|
||||
createTime: 2025/10/09 06:56:33
|
||||
permalink: /en/config/plugins/markdown-power/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Provides Markdown enhancement features for the theme.
|
||||
|
||||
Related plugin: [vuepress-plugin-md-power](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-md-power)
|
||||
|
||||
## Configuration
|
||||
|
||||
Default configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
fileTree: true, // :::file-tree File tree container
|
||||
plot: true, // !!plot!! Hidden text
|
||||
icons: true, // ::collect:name:: Inline iconify icons
|
||||
// The following features are not enabled by default; you need to enable them manually
|
||||
// npmTo: true, // :::npm-to
|
||||
// demo: true, // :::demo
|
||||
// pdf: true, // @[pdf](url) Embed PDF files
|
||||
// bilibili: true, // @[bilibili](bvid) Embed bilibili videos
|
||||
// acfun: true, // @[acfun](id) Embed AcFun videos
|
||||
// youtube: true, // @[youtube](id) Embed YouTube videos
|
||||
// codepen: true, // @[codepen](user/slash) Embed CodePen
|
||||
// replit: true, // @[replit](user/repl-name) Embed Replit
|
||||
// codeSandbox: true, // @[codesandbox](id) Embed CodeSandbox
|
||||
// jsfiddle: true, // @[jsfiddle](id) Embed JSFiddle
|
||||
// caniuse: true, // @[caniuse](feature) Embed Can I Use
|
||||
// repl: true, // :::go-repl :::kotlin-repl :::rust-repl
|
||||
// imageSize: true, // Add width/height attributes to images during build
|
||||
},
|
||||
// Can also be configured in `plugins.markdownPower`, but not recommended
|
||||
plugins: {
|
||||
markdownPower: {}
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Embed PDF
|
||||
|
||||
This feature is not enabled by default; you need to manually set `pdf` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[pdf](url)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/embed/pdf.md)
|
||||
|
||||
### Iconify Icons
|
||||
|
||||
This feature is not enabled by default; you need to manually set `icons` to `true`.
|
||||
|
||||
Thanks to [iconify](https://iconify.design/), you can use __200k+__ icons from Iconify in Markdown.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
::collect:name::
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/markdown/icons.md)
|
||||
|
||||
### Bilibili Video
|
||||
|
||||
This feature is not enabled by default; you need to manually set `bilibili` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[bilibili](bvid)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/embed/bilibili.md)
|
||||
|
||||
### AcFun Video
|
||||
|
||||
This feature is not enabled by default; you need to manually set `acfun` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[acfun](id)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/embed/video/acfun.md)
|
||||
|
||||
### YouTube Video
|
||||
|
||||
This feature is not enabled by default; you need to manually set `youtube` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[youtube](id)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/embed/youtube.md)
|
||||
|
||||
### CodePen Demo
|
||||
|
||||
This feature is not enabled by default; you need to manually set `codepen` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[codepen](user/slash)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/repl/codepen.md)
|
||||
|
||||
### CodeSandbox Demo
|
||||
|
||||
This feature is not enabled by default; you need to manually set `codeSandbox` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[codesandbox](id)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/repl/codeSandbox.md)
|
||||
|
||||
### JSFiddle Demo
|
||||
|
||||
This feature is not enabled by default; you need to manually set `jsfiddle` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[jsfiddle](id)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/repl/jsFiddle.md)
|
||||
|
||||
### Can I Use Browser Support
|
||||
|
||||
This feature is not enabled by default; you need to manually set `caniuse` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
@[caniuse](feature)
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/markdown/caniuse.md)
|
||||
|
||||
### Repl Code Demo Container
|
||||
|
||||
This feature is not enabled by default; you need to manually set `repl` to `true`.
|
||||
|
||||
Supports online execution of Rust, Golang, and Kotlin code, as well as online editing.
|
||||
|
||||
Alternatively, you can enable specific features, as shown below:
|
||||
|
||||
``` ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: {
|
||||
markdownPower: {
|
||||
repl: {
|
||||
rust: true,
|
||||
go: true,
|
||||
kotlin: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
__Syntax:__
|
||||
|
||||
````md
|
||||
::: rust-repl
|
||||
```rust
|
||||
// rust code
|
||||
```
|
||||
:::
|
||||
|
||||
::: go-repl
|
||||
```go
|
||||
// go code
|
||||
```
|
||||
:::
|
||||
|
||||
::: kotlin-repl
|
||||
```kotlin
|
||||
// kotlin code
|
||||
```
|
||||
:::
|
||||
|
||||
::: python-repl
|
||||
```python
|
||||
// python code
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
Please refer to the complete usage documentation:
|
||||
|
||||
- [Code Demo > Rust](../../guide/repl/rust.md)
|
||||
- [Code Demo > Golang](../../guide/repl/golang.md)
|
||||
- [Code Demo > Kotlin](../../guide/repl/kotlin.md)
|
||||
- [Code Demo > Python](../../guide/repl/python.md)
|
||||
|
||||
### Plot Hidden Text
|
||||
|
||||
This feature is not enabled by default; you need to manually set `plot` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
!!content!!
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/markdown/plot.md)
|
||||
|
||||
### File Tree
|
||||
|
||||
This feature is not enabled by default; you need to manually set `fileTree` to `true`.
|
||||
|
||||
__Syntax:__
|
||||
|
||||
```md
|
||||
::: file-tree
|
||||
|
||||
- folder1
|
||||
- file1.md
|
||||
- file2.ts
|
||||
- folder2
|
||||
- file3.md
|
||||
- folder3
|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
Please refer to the [Complete Usage Documentation](../../guide/markdown/file-tree.md)
|
||||
|
||||
### Image Dimensions
|
||||
|
||||
This feature adds `width` and `height` attributes to image references in markdown files.
|
||||
It reads the original dimensions of the images to set default image sizes and aspect ratios.
|
||||
This resolves layout flickering issues that occur between when an image starts loading and when it completes.
|
||||
|
||||
This feature is not enabled by default; you need to manually configure `imageSize`:
|
||||
|
||||
- If `imageSize` is `true`, the plugin only processes local images, equivalent to the `local` option;
|
||||
- If `imageSize` is `'local'`, the plugin only processes local images;
|
||||
- If `imageSize` is `'all'`, the plugin processes both local and remote images.
|
||||
|
||||
::: important
|
||||
__This feature only takes effect during production builds.__
|
||||
|
||||
Use the `'all'` option with caution, as it will request remote image resources during production builds,
|
||||
which can significantly increase build time.
|
||||
Although the theme optimizes this by loading only __a few KB__ of data from each image to analyze dimensions, it will still impact build performance.
|
||||
:::
|
||||
85
docs/en/config/plugins/reading-time.md
Normal file
85
docs/en/config/plugins/reading-time.md
Normal file
@ -0,0 +1,85 @@
|
||||
---
|
||||
title: Reading Statistics
|
||||
createTime: 2025/10/09 15:23:39
|
||||
permalink: /en/config/plugins/reading-time/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Generates word count and estimated reading time for each page.
|
||||
|
||||
Related plugin: [@vuepress/plugin-reading-time](https://ecosystem.vuejs.press/plugins/search/docsearch.html)
|
||||
|
||||
Default configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
readingTime: {
|
||||
wordPerMinute: 300
|
||||
},
|
||||
// Can also be configured via plugins.readingTime, but not recommended
|
||||
plugins: {
|
||||
readingTime: {}
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### wordPerMinute
|
||||
|
||||
- Type: `number`
|
||||
- Default: `300`
|
||||
|
||||
Words read per minute.
|
||||
|
||||
### locales
|
||||
|
||||
- Type: `ReadingTimePluginLocaleConfig`
|
||||
|
||||
Internationalization configuration for the reading time plugin.
|
||||
|
||||
```ts
|
||||
interface ReadingTimePluginLocaleData {
|
||||
/**
|
||||
* Word count template, where `$word` will be automatically replaced with the actual word count
|
||||
*/
|
||||
word: string
|
||||
|
||||
/**
|
||||
* Text for less than one minute
|
||||
*/
|
||||
less1Minute: string
|
||||
|
||||
/**
|
||||
* Time template
|
||||
*/
|
||||
time: string
|
||||
}
|
||||
|
||||
interface ReadingTimePluginLocaleConfig {
|
||||
[localePath: string]: ReadingTimePluginLocaleData
|
||||
}
|
||||
```
|
||||
|
||||
## Disabling
|
||||
|
||||
You can disable this feature by setting `readingTime` to `false`.
|
||||
|
||||
When disabled, article pages will not display word count and estimated reading time.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
readingTime: false
|
||||
}),
|
||||
})
|
||||
```
|
||||
103
docs/en/config/plugins/search.md
Normal file
103
docs/en/config/plugins/search.md
Normal file
@ -0,0 +1,103 @@
|
||||
---
|
||||
title: Content Search
|
||||
createTime: 2025/10/09 09:19:26
|
||||
permalink: /en/config/plugins/search/
|
||||
---
|
||||
|
||||
## Local Search
|
||||
|
||||
### Overview
|
||||
|
||||
Adds local search functionality to the site.
|
||||
|
||||
Related plugin: [@vuepress-plume/plugin-search](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-search)
|
||||
|
||||
This plugin uses [minisearch](https://github.com/lucaong/minisearch) for content search.
|
||||
|
||||
Default configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
search: {
|
||||
provider: 'local', // [!code hl]
|
||||
// more options...
|
||||
},
|
||||
// Can also be configured via plugins.search, but not recommended
|
||||
plugins: {
|
||||
search: {},
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```ts
|
||||
interface SearchOptions {
|
||||
/**
|
||||
* Local search internationalization
|
||||
*/
|
||||
locales?: {
|
||||
[locale: string]: SearchBoxLocale
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether articles are searchable, defaults to `() => true`
|
||||
*/
|
||||
isSearchable?: (page: Page) => boolean
|
||||
}
|
||||
|
||||
interface SearchBoxLocale {
|
||||
placeholder: string
|
||||
buttonText: string
|
||||
resetButtonTitle: string
|
||||
backButtonTitle: string
|
||||
noResultsText: string
|
||||
footer: {
|
||||
selectText: string
|
||||
selectKeyAriaLabel: string
|
||||
navigateText: string
|
||||
navigateUpKeyAriaLabel: string
|
||||
navigateDownKeyAriaLabel: string
|
||||
closeText: string
|
||||
closeKeyAriaLabel: string
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Algolia DocSearch
|
||||
|
||||
### Overview
|
||||
|
||||
A site content search plugin powered by [Algolia DocSearch](https://docsearch.algolia.com/)
|
||||
|
||||
Related plugin: [@vuepress/plugin-docsearch](https://ecosystem.vuejs.press/zh/plugins/search/docsearch.html)
|
||||
|
||||
Refer to [Algolia DocSearch Reference](/guide/features/content-search/#algolia-docsearch) for more information.
|
||||
|
||||
### Enable
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
search: {
|
||||
provider: 'algolia', // [!code hl]
|
||||
appId: 'YOUR_APP_ID',
|
||||
apiKey: 'YOUR_API_KEY',
|
||||
indexName: 'YOUR_INDEX_NAME',
|
||||
// more options
|
||||
},
|
||||
// Can also be configured via plugins.docsearch, but not recommended
|
||||
plugins: {
|
||||
docsearch: {},
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
125
docs/en/config/plugins/shiki.md
Normal file
125
docs/en/config/plugins/shiki.md
Normal file
@ -0,0 +1,125 @@
|
||||
---
|
||||
title: Code Highlighting
|
||||
createTime: 2025/10/09 10:21:47
|
||||
permalink: /en/config/plugins/code-highlight/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme's built-in code highlighting plugin provides syntax highlighting for code blocks.
|
||||
|
||||
Related plugin: [@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html)
|
||||
|
||||
The theme uses [Shiki](https://github.com/shikijs/shiki) to implement syntax highlighting with colored
|
||||
text in Markdown code blocks. Shiki supports multiple programming languages.
|
||||
|
||||
You can find the [list of supported languages](https://shiki.style/languages) in Shiki's repository.
|
||||
|
||||
## Features
|
||||
|
||||
- [Code Block Titles](../../guide/code/features.md#code-block-titles)
|
||||
- [Line Highlighting](../../guide/code/features.md#line-highlighting-in-code-blocks)
|
||||
- [Code Focus](../../guide/code/features.md#focus-in-code-blocks)
|
||||
- [Code Diff](../../guide/code/features.md#color-differences-in-code-blocks)
|
||||
- [Error and Warning Highlighting](../../guide/code/features.md#highlighting-errors-and-warnings)
|
||||
- [Word Highlighting](../../guide/code/features.md#word-highlighting-in-code-blocks)
|
||||
- [Code Block Folding](../../guide/code/features.md#collapsing-code-blocks)
|
||||
- [twoslash](../../guide/code/twoslash.md#twoslash): Provides inline type hints within code blocks.
|
||||
|
||||
## Configuration
|
||||
|
||||
Default configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
themes: { light: 'vitesse-light', dark: 'vitesse-dark' },
|
||||
notationDiff: true,
|
||||
notationErrorLevel: true,
|
||||
notationFocus: true,
|
||||
notationHighlight: true,
|
||||
notationWordHighlight: true,
|
||||
highlightLines: true,
|
||||
collapsedLines: false,
|
||||
lineNumbers: true,
|
||||
},
|
||||
// Can also be configured via plugins.shiki, but not recommended
|
||||
plugins: {
|
||||
shiki: {}
|
||||
}
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
### themes
|
||||
|
||||
- Type: `{ light: string, dark: string }`
|
||||
- Default: `{ light: 'vitesse-light', dark: 'vitesse-dark' }`
|
||||
|
||||
Code highlighting themes supporting light/dark dual themes.
|
||||
|
||||
You can choose your preferred themes from the [list of supported themes](https://shiki.style/themes).
|
||||
|
||||
### langs
|
||||
|
||||
- Type: `string[]`
|
||||
- Default: `[]`
|
||||
|
||||
Programming languages to be highlighted, such as `javascript`, `typescript`, `python`, `java`, `c++`, `c#`, etc.
|
||||
By default, languages are automatically detected based on code block language identifiers.
|
||||
|
||||
You can find the [list of supported languages](https://shiki.style/languages) in Shiki's repository.
|
||||
|
||||
### defaultLang
|
||||
|
||||
- Type: `string`
|
||||
- Default: `text`
|
||||
|
||||
Fallback language to use when the specified language is not available.
|
||||
|
||||
### lineNumbers
|
||||
|
||||
- Type: `boolean | number`
|
||||
- Default: `true`
|
||||
|
||||
Whether to display line numbers.
|
||||
|
||||
`true`: Display line numbers\
|
||||
`false`: Hide line numbers\
|
||||
`number`: Minimum number of lines required to display line numbers.
|
||||
|
||||
### twoslash
|
||||
|
||||
- Type: `boolean | ShikiTwoslashOptions`
|
||||
- Default: `false`
|
||||
|
||||
Whether to enable type hint support for `typescript` and `vue` languages.
|
||||
|
||||
### whitespace
|
||||
|
||||
- Type: `boolean | 'all' | 'boundary' | 'trailing'`
|
||||
- Default: `false`
|
||||
|
||||
Render whitespace characters (tabs and spaces) as separate spans (with `tab` or `space` class names).
|
||||
|
||||
Effect:
|
||||
|
||||
<!-- @include: ../../snippet/whitespace.snippet.md{17-23} -->
|
||||
|
||||
### collapsedLines
|
||||
|
||||
- Type: `boolean | number`
|
||||
- Default: `false`
|
||||
|
||||
Collapse code blocks to the specified number of lines.
|
||||
|
||||
### transformers
|
||||
|
||||
- Type: `ShikiTransformer[]`
|
||||
- Default: `[]`
|
||||
|
||||
Code transformers. Refer to [shiki transformers](https://shiki.style/guide/transformers) for more information.
|
||||
100
docs/en/config/plugins/watermark.md
Normal file
100
docs/en/config/plugins/watermark.md
Normal file
@ -0,0 +1,100 @@
|
||||
---
|
||||
title: Watermark
|
||||
createTime: 2025/10/09 15:37:18
|
||||
permalink: /en/config/watermark/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme's built-in watermark plugin adds watermarks to the entire site or individual pages.
|
||||
|
||||
Related plugin: [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html)
|
||||
|
||||
## Usage
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// watermark: true,
|
||||
watermark: {
|
||||
// enabled: false, // boolean type controls global enablement
|
||||
enabled: page => true, // function type filters which pages enable watermark
|
||||
|
||||
/**
|
||||
* Whether to enable full-page watermark, defaults to `true`,
|
||||
* When set to `false`, watermark is only displayed in the content area.
|
||||
*/
|
||||
fullPage: true,
|
||||
|
||||
/** @see https://zhensherlock.github.io/watermark-js-plus/zh/config/ */
|
||||
watermarkOptions: {
|
||||
content: 'your watermark',
|
||||
// ...
|
||||
}
|
||||
},
|
||||
// Can also be configured via plugins.watermark, but not recommended
|
||||
plugins: {
|
||||
watermark: {}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### enabled
|
||||
|
||||
- Type: `boolean | ((page: Page) => boolean)`
|
||||
|
||||
- Default: `false`
|
||||
|
||||
- Details:
|
||||
|
||||
Specifies which pages should have watermarks added.
|
||||
|
||||
Pages with a `true` value will have watermarks applied.
|
||||
|
||||
### watermarkOptions
|
||||
|
||||
- Type: `WatermarkOptions`
|
||||
|
||||
- Default: `undefined`
|
||||
|
||||
- Details: Configuration options refer to [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/).
|
||||
|
||||
#### watermarkOptions.parent
|
||||
|
||||
- Type: `string`
|
||||
|
||||
- Default: `body`
|
||||
|
||||
- Details: Parent element selector for adding watermarks.
|
||||
|
||||
By default inserted into the body, can be specified to insert into a specific element on the page.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
### watermark
|
||||
|
||||
- Type: `boolean | WatermarkOptions`
|
||||
|
||||
- Details:
|
||||
|
||||
When type is `boolean`, indicates whether to enable watermark.
|
||||
|
||||
When type is `WatermarkOptions`, indicates current page watermark configuration.
|
||||
|
||||
Refer to [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/) for configuration options.
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
width: 200
|
||||
height: 200
|
||||
content: Your content
|
||||
opacity: 0.5
|
||||
---
|
||||
```
|
||||
123
docs/en/config/sidebar.md
Normal file
123
docs/en/config/sidebar.md
Normal file
@ -0,0 +1,123 @@
|
||||
---
|
||||
title: Sidebar Configuration
|
||||
createTime: 2025/10/09 21:05:36
|
||||
permalink: /en/config/sidebar/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The sidebar is a core navigation area located on the left side of the page in the theme,
|
||||
serving the important function of guiding users to jump between different pages.
|
||||
|
||||
In the VuePress ecosystem, the default theme `@vuepress/theme-default` manages the sidebar through
|
||||
the `sidebar` configuration option. While retaining this classic configuration method,
|
||||
this theme also provides a more flexible collection-level sidebar configuration solution.
|
||||
|
||||
## Collection-Level Sidebar Configuration
|
||||
|
||||
Collections are the core concept for organizing series of documents in the theme.
|
||||
When a collection type is set to `doc`, you can define a dedicated sidebar navigation within `collection.sidebar`.
|
||||
|
||||
The following example demonstrates how to create a collection of type `doc` under the `docs` directory and configure its sidebar:
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { defineCollection, plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
// Define document collection configuration // [!code hl:10]
|
||||
const demo = defineCollection({
|
||||
type: 'doc',
|
||||
dir: 'demo', // Document directory
|
||||
title: 'Demo', // Collection name
|
||||
sidebar: [ // Sidebar configuration // [!code ++:4]
|
||||
{ text: 'one item', link: 'one' },
|
||||
{ text: 'two item', link: 'two' },
|
||||
]
|
||||
})
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
collections: [demo], // Register collection // [!code hl]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineCollection, defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
// Define collection using independent config file // [!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]
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The `defineCollection` utility function provided by the theme simplifies the collection configuration
|
||||
process. For complete collection configuration options, please refer to the [Collections Configuration Documentation](./collections.md).
|
||||
|
||||
## Global Sidebar Configuration
|
||||
|
||||
If you prefer to manage the sidebar using the traditional global configuration approach,
|
||||
you can directly use the `sidebar` option in the theme configuration.
|
||||
This method is suitable for scenarios that do not require navigation grouping by collections.
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Global sidebar configuration // [!code hl:7]
|
||||
sidebar: {
|
||||
'/config/': [ // Matches /config/ path
|
||||
{ text: 'Sidebar Configuration', link: 'sidebar-1' },
|
||||
{ text: 'Sidebar Configuration', link: 'sidebar-2' },
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
// Define global sidebar in independent config file // [!code hl:7]
|
||||
sidebar: {
|
||||
'/config/': [
|
||||
{ text: 'Sidebar Configuration', link: 'sidebar-1' },
|
||||
{ text: 'Sidebar Configuration', link: 'sidebar-2' },
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Both configuration methods have their advantages: collection-level configuration is suitable for
|
||||
modular document structures, while global configuration is convenient for unified navigation management in simple projects.
|
||||
|
||||
For complete sidebar configuration options and usage tips, please refer to the [Sidebar Configuration Guide](../guide/quick-start/sidebar.md).
|
||||
748
docs/en/config/theme.md
Normal file
748
docs/en/config/theme.md
Normal file
@ -0,0 +1,748 @@
|
||||
---
|
||||
title: Theme Configuration
|
||||
createTime: 2025/10/09 18:07:03
|
||||
permalink: /en/config/theme/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Theme configuration is used to customize various features of the theme and control its behavior.
|
||||
You can configure it in either `.vuepress/config.ts` or `.vuepress/plume.config.ts`.
|
||||
|
||||
When a field description includes the following statement, it indicates that the field is not supported for configuration in `.vuepress/plume.config.ts`:
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
For fields without the above declaration, you can configure them in either `.vuepress/config.ts`
|
||||
or `.vuepress/plume.config.ts`. It is generally recommended to configure them in `.vuepress/plume.config.ts`.
|
||||
|
||||
::: warning Avoid reconfiguring a field that has already been configured in one configuration file within another configuration file.
|
||||
:::
|
||||
|
||||
::: code-tabs#configs
|
||||
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Theme configuration
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/plume.config.ts
|
||||
|
||||
```ts twoslash
|
||||
import { defineThemeConfig } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineThemeConfig({
|
||||
// Theme configuration
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
### configFile
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:**
|
||||
|
||||
Custom path to the theme configuration file.
|
||||
|
||||
Refer to [Theme Config File `plume.config.js`](./intro.md#theme-config-file) for more information.
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### plugins
|
||||
|
||||
- **Type:** `PlumeThemePluginOptions`
|
||||
- **Default:** `{}`
|
||||
- **Details:**
|
||||
|
||||
Custom configuration for plugins used internally by the theme.
|
||||
|
||||
The plugins used by the theme are configured by default. In most cases, modification is not required.
|
||||
For detailed customization, please refer to [this documentation](./plugins/README.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### markdown <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `MarkdownOptions`
|
||||
- **Default:** `{}`
|
||||
- **Details:**
|
||||
|
||||
Markdown feature configuration. Refer to [this documentation](./markdown.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### codeHighlighter <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | ShikiPluginOptions`
|
||||
- **Default:** `{}`
|
||||
- **Details:**
|
||||
|
||||
Code highlighting configuration. Refer to [this documentation](../guide/code/intro.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### search <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | SearchOptions`
|
||||
- **Default:** `{ provider: 'local' }`
|
||||
- **Details:**
|
||||
|
||||
Search configuration. Refer to [this documentation](../guide/features/search.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### comment <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | CommentPluginOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:**
|
||||
|
||||
Comment configuration. Refer to [this documentation](../guide/features/comments.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### watermark <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | WatermarkPluginOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:**
|
||||
|
||||
Watermark configuration. Refer to [this documentation](../guide/features/watermark.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### readingTime <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | ReadingTimePluginOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:**
|
||||
|
||||
Reading time configuration. Refer to [this documentation](./plugins/reading-time.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### copyCode <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
- **Type:** `false | CopyCodePluginOptions`
|
||||
- **Default:** `{}`
|
||||
- **Details:**
|
||||
|
||||
Copy code configuration. Refer to [this documentation](../guide/code/copy-code.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### replaceAssets <Badge type="tip" text="1.0.0-rc.139 +" />
|
||||
|
||||
- **Type:** `false | ReplaceAssetsPluginOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:**
|
||||
|
||||
Replace assets configuration. Refer to [this documentation](../guide/features/replace-assets.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### hostname
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:**
|
||||
|
||||
Deployment site domain name.
|
||||
|
||||
When `hostname` is configured to a valid domain, the theme will generate `sitemap` and SEO-related content.
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### autoFrontmatter
|
||||
|
||||
- **Type:** `false | AutoFrontmatterOptions`
|
||||
- **Details:**
|
||||
|
||||
Whether to automatically add frontmatter configuration to markdown files.
|
||||
|
||||
```ts
|
||||
interface AutoFrontmatterOptions {
|
||||
/**
|
||||
* Whether to automatically generate permalink
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
permalink?: boolean
|
||||
|
||||
/**
|
||||
* Whether to automatically generate createTime
|
||||
*
|
||||
* Reads file creation time by default. `createTime` is more precise (to the second) than the default VuePress `date` field.
|
||||
*/
|
||||
createTime?: boolean
|
||||
|
||||
/**
|
||||
* Whether to automatically generate title
|
||||
*
|
||||
* Uses the filename as the title by default.
|
||||
*/
|
||||
title?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
### cache
|
||||
|
||||
- **Type:** `false | 'memory' | 'filesystem'`
|
||||
- **Default:** `filesystem`
|
||||
- **Details:**
|
||||
|
||||
Whether to enable compilation cache, or configure the caching method.
|
||||
|
||||
This configuration item addresses the slow startup speed of VuePress.
|
||||
It caches the compilation results during the first service start.
|
||||
On subsequent starts, it reads the cache directly, skipping compilation to speed up startup.
|
||||
|
||||
- `false`: Disable cache.
|
||||
- `'memory'`: Use memory cache. This method provides faster startup speed but increases memory usage
|
||||
as the number of project files grows. Suitable for projects with fewer articles.
|
||||
- `'filesystem'`: Use filesystem cache. This method provides a relatively fast and stable startup speed,
|
||||
more suitable for projects with substantial content.
|
||||
|
||||
::: warning
|
||||
This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
|
||||
For the cache to take effect, you should **remove** the `--clean-cache` parameter from the
|
||||
`vuepress dev` development server startup script in your `package.json`.
|
||||
:::
|
||||
|
||||
### docsRepo
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:** Documentation repository configuration, used to generate the `Edit this page` link.
|
||||
|
||||
### docsBranch
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:** Documentation repository branch configuration, used to generate the `Edit this page` link.
|
||||
|
||||
### docsDir
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:** Documentation repository directory configuration, used to generate the `Edit this page` link.
|
||||
|
||||
### editLink
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to enable the edit link.
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### lastUpdated
|
||||
|
||||
- **Type:** `false | LastUpdatedOptions`
|
||||
- **Default:** `{ formatOptions: { dateStyle: 'short', timeStyle: 'short' } }`
|
||||
- **Details:** Last updated time.
|
||||
|
||||
```ts
|
||||
interface LastUpdatedOptions {
|
||||
|
||||
/**
|
||||
* Options to set the format of the last updated time.
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat#using_options
|
||||
*
|
||||
* @default
|
||||
* { dateStyle: 'short', timeStyle: 'short' }
|
||||
*/
|
||||
formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean }
|
||||
}
|
||||
```
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### contributors
|
||||
|
||||
- **Type:** `boolean | ContributorsOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to display contributors.
|
||||
|
||||
For more configuration, please refer to [this documentation](../guide/features/contributors.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### changelog
|
||||
|
||||
- **Type:** `boolean | ChangelogOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Whether to display page change history.
|
||||
|
||||
For more configuration, please refer to [this documentation](../guide/features/changelog.md).
|
||||
|
||||
::: warning This field is not supported for configuration in the [Theme Config File `plume.config.js`](./intro.md#theme-config-file).
|
||||
:::
|
||||
|
||||
### locales
|
||||
|
||||
- **Type:** `Record<string, ThemeLocaleData>`
|
||||
- **Default:** `{}`
|
||||
- **Details:** Multi-language configuration.
|
||||
|
||||
Text configuration for different languages. Refer to [this documentation](./locales.md).
|
||||
|
||||
The multi-language configuration supports all configuration options under the following
|
||||
[Locale](#locale-configuration) to control theme behavior in different languages.
|
||||
|
||||
## Locale Configuration
|
||||
|
||||
::: tip All the following fields are also basic configuration fields and can be configured at the same level as fields like `locales`.
|
||||
:::
|
||||
|
||||
### home
|
||||
|
||||
- **Type:** `false | string`
|
||||
- **Default:** `/`
|
||||
- **Details:**
|
||||
The path to the home page. It will be used for:
|
||||
- The logo link in the navbar;
|
||||
- The *Back to Home* link on the 404 page;
|
||||
|
||||
### logo
|
||||
|
||||
- **Type:** `false | string`
|
||||
- **Default:** `false`
|
||||
- **Details:** Logo in the navbar.
|
||||
|
||||
### logoDark
|
||||
|
||||
- **Type:** `false | string`
|
||||
- **Default:** `false`
|
||||
- **Details:** Logo in the navbar for Dark mode.
|
||||
|
||||
### appearance
|
||||
|
||||
- **Type:** `boolean | 'dark' | 'force-dark'`
|
||||
- **Default:** `true`
|
||||
|
||||
Whether to enable dark mode.
|
||||
|
||||
- If this option is set to `true`, the default theme will be determined by the user's preferred color scheme.
|
||||
- If this option is set to `dark`, the theme will be dark by default unless the user manually toggles it.
|
||||
- If this option is set to `false`, the user will not be able to switch themes.
|
||||
- If this option is set to `force-dark`, the user will not be able to switch themes, and the theme will be forced to dark.
|
||||
|
||||
This option injects an inline script that restores user settings from local storage.
|
||||
This ensures `[data-theme="dark"]` is applied before the page is rendered to avoid flashing.
|
||||
|
||||
### profile
|
||||
|
||||
- **Type:** `ProfileOptions`
|
||||
- **Default:** `{}`
|
||||
- **Details:** Configure the site owner's personal information.
|
||||
- `profile.avatar`: Avatar URL, used for displaying blogger information on the right.
|
||||
- `profile.name`: Name, used for displaying blogger information on the right.
|
||||
- `profile.description`: Personal description, used for displaying blogger information on the right.
|
||||
- `profile.circle`: Whether the avatar is circular.
|
||||
- `profile.location`: User's geographical location.
|
||||
- `profile.organization`: User's organization/company.
|
||||
- `profile.layout`: Whether to display personal information on the left or right, `'left' | 'right'`.
|
||||
|
||||
Example:
|
||||
|
||||
``` ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
profile: {
|
||||
avatar: '/avatar.jpg',
|
||||
name: 'Zhang San',
|
||||
description: 'Here is no silver three hundred two, next door Wang Er never stole',
|
||||
circle: true,
|
||||
location: 'Hangzhou, China',
|
||||
organization: 'XXX Company',
|
||||
layout: 'right',
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### social
|
||||
|
||||
- **Type:** `false | SocialLink[]`
|
||||
- **Default:** `false`
|
||||
- **Details:** Personal social information configuration.
|
||||
|
||||
Displayed as icon links on the far right of the navbar.
|
||||
|
||||
Available icon options:
|
||||
- `'github'`
|
||||
- `'gitlab'`
|
||||
- `'npm'`
|
||||
- `'docker'`
|
||||
- `'discord'`
|
||||
- `'telegram'`
|
||||
- `'facebook'`
|
||||
- `'instagram'`
|
||||
- `'linkedin'`
|
||||
- `'mastodon'`
|
||||
- `'slack'`
|
||||
- `'twitter'`
|
||||
- `'x'`
|
||||
- `'youtube'`
|
||||
- `'juejin'`
|
||||
- `'stackoverflow'`
|
||||
- `'qq'`
|
||||
- `'weibo'`
|
||||
- `'bilibili'`
|
||||
- `'zhihu'`
|
||||
- `'douban'`
|
||||
- `'steam'`
|
||||
- `'xbox'`
|
||||
- `{ svg: string, name?: string }`: Custom icon, pass the SVG source string. The optional `name` field is used to configure [`navbarSocialInclude`](#navbarsocialinclude).
|
||||
|
||||
Example:
|
||||
|
||||
``` ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
social: [
|
||||
{ icon: 'github', link: 'https://github.com/zhangsan' },
|
||||
{
|
||||
icon: { svg: '<svg>xxxxx</svg>', name: 'xxx' },
|
||||
link: 'https://xxx.com'
|
||||
},
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### navbarSocialInclude
|
||||
|
||||
- **Type:** `string[]`
|
||||
- **Default:** `['github', 'twitter', 'discord', 'facebook']`
|
||||
- **Details:**
|
||||
|
||||
Social links allowed to be displayed in the navbar.
|
||||
This configuration is only effective on PC.
|
||||
|
||||
If [`social`](#social) is configured as `{ svg: string, name: string}`, then `name` can be used as a value for `navbarSocialInclude`.
|
||||
|
||||
### navbar
|
||||
|
||||
- **Type:** `NavItem[]`
|
||||
- **Default:** `[]`
|
||||
- **Details:** Navbar configuration.
|
||||
|
||||
To configure navbar elements, you can set it to a navbar array, where each element is a `string` or a `NavItem` object.
|
||||
|
||||
- A `NavItem` object should have a `text` field and a `link` field, with an optional `activeMatch` field.
|
||||
- A `string` represents a page file path or a page access path.
|
||||
|
||||
``` ts
|
||||
type NavItem = string | {
|
||||
text: string
|
||||
link: string
|
||||
|
||||
/**
|
||||
* The page prefix for the current group.
|
||||
*/
|
||||
prefix?: string
|
||||
/**
|
||||
* Navigation items under this group.
|
||||
*/
|
||||
items?: NavItem[]
|
||||
/**
|
||||
* Supports iconify icons. Use the iconify name directly and it will be loaded automatically.
|
||||
*
|
||||
* @see https://icon-sets.iconify.design/
|
||||
*/
|
||||
icon: string
|
||||
/**
|
||||
* Controls when the element is active.
|
||||
*/
|
||||
activeMatch?: string
|
||||
}
|
||||
```
|
||||
|
||||
- Example 1:
|
||||
|
||||
``` js
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
navbar: [
|
||||
// NavbarItem
|
||||
{ text: 'Foo', link: '/foo/' },
|
||||
// NavbarGroup
|
||||
{
|
||||
text: 'Group',
|
||||
prefix: '/group/',
|
||||
items: ['foo/', 'bar/'],
|
||||
},
|
||||
// String - page file path
|
||||
'/bar', // The `.md` extension can be omitted directly.
|
||||
],
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
- Example 2:
|
||||
|
||||
``` js
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
navbar: [
|
||||
// Nested Group - maximum depth is 2
|
||||
{
|
||||
text: 'Group',
|
||||
items: [
|
||||
{
|
||||
text: 'SubGroup',
|
||||
items: ['/group/sub/', '/group/sub/bar/'],
|
||||
},
|
||||
],
|
||||
},
|
||||
// Control when the element is active
|
||||
{
|
||||
text: 'Group 2',
|
||||
items: [
|
||||
{
|
||||
text: 'Always active',
|
||||
link: '/',
|
||||
// This element will always be active
|
||||
activeMatch: '/',
|
||||
},
|
||||
{
|
||||
text: 'Active on /foo/',
|
||||
link: '/not-foo/',
|
||||
// This element is active when the current route path starts with /foo/
|
||||
// Supports regular expressions
|
||||
activeMatch: '^/foo/',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
### collections
|
||||
|
||||
- **Type:** `ThemeCollectionItem[]`
|
||||
|
||||
- **Default:** `[]`
|
||||
|
||||
- **Details:** Documentation collections configuration.
|
||||
|
||||
[Check **Collections Guide**](../guide/quick-start/collection.md){.read-more}
|
||||
|
||||
[Check **Collections Configuration** to learn more](./collections.md){.read-more}
|
||||
|
||||
### sidebar
|
||||
|
||||
- **Type:** `false | SidebarMulti`
|
||||
|
||||
- **Details:**
|
||||
|
||||
Sidebar configuration. **The theme recommends configuring the sidebar in [collections configuration](./collections.md).**
|
||||
|
||||
The `key` of the configuration object is the common access path prefix for the sidebar.
|
||||
|
||||
For `value`:
|
||||
- `'auto'` means automatically generate the sidebar based on the directory structure.
|
||||
- `string` represents the page file path corresponding to the sidebar.
|
||||
- `SidebarItem` represents a single sidebar item configuration.
|
||||
|
||||
```ts
|
||||
type ThemeIcon = string | { svg: string }
|
||||
|
||||
type SidebarMulti = Record<
|
||||
string,
|
||||
| 'auto'
|
||||
| (string | SidebarItem)[]
|
||||
| { items: 'auto' | (string | SidebarItem)[], prefix?: string }
|
||||
>
|
||||
interface SidebarItem {
|
||||
/**
|
||||
* Sidebar text.
|
||||
*/
|
||||
text?: string
|
||||
|
||||
/**
|
||||
* Sidebar link.
|
||||
*/
|
||||
link?: string
|
||||
|
||||
/**
|
||||
* Sidebar icon.
|
||||
*/
|
||||
icon?: ThemeIcon
|
||||
|
||||
/**
|
||||
* Nested sidebar group.
|
||||
*/
|
||||
items?: 'auto' | (string | SidebarItem)[]
|
||||
|
||||
/**
|
||||
* If not specified, the group is not collapsible.
|
||||
* If `true`, the group is collapsible and collapsed by default.
|
||||
* If `false`, the group is collapsible but expanded by default.
|
||||
*/
|
||||
collapsed?: boolean
|
||||
|
||||
/**
|
||||
* Link prefix for the current group.
|
||||
*/
|
||||
prefix?: string
|
||||
|
||||
rel?: string
|
||||
target?: string
|
||||
}
|
||||
```
|
||||
|
||||
### sidebarScrollbar
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to show the sidebar scrollbar.
|
||||
|
||||
When set to `false`, only the scrollbar is hidden, but the scrolling behavior remains unchanged.
|
||||
|
||||
### aside
|
||||
|
||||
- **Type:** `boolean | 'left'`
|
||||
- **Default:** `true`
|
||||
- **Details:**
|
||||
|
||||
Whether to display the aside (right sidebar).
|
||||
|
||||
- `false` disables the right aside.
|
||||
- `true` enables the right aside.
|
||||
- `'left'` moves the right aside to the left side of the article content, to the right of the main sidebar.
|
||||
|
||||
Each page can override this global configuration via [frontmatter aside](./frontmatter/basic.md#aside).
|
||||
|
||||
### outline
|
||||
|
||||
- **Type:** `false | number | [number, number] | 'deep'`
|
||||
- **Default:** `[2, 3]`
|
||||
- **Details:**
|
||||
|
||||
The heading levels to display.
|
||||
|
||||
A single number means only display headings of that level.
|
||||
|
||||
If a tuple is passed, the first number is the minimum level and the second is the maximum level.
|
||||
|
||||
`'deep'` is the same as `[2, 6]`, which displays all headings from `<h2>` to `<h6>`.
|
||||
|
||||
When [aside](#aside) is disabled, `outline` is also disabled.
|
||||
|
||||
Each page can override this global configuration via [frontmatter outline](./frontmatter/basic.md#outline).
|
||||
|
||||
### transition
|
||||
|
||||
- **Type:** `boolean | TransitionOptions`
|
||||
- **Default:** `true`
|
||||
- **Details:**
|
||||
|
||||
Whether to enable transition animations.
|
||||
|
||||
When passing a `boolean`, `true` enables and `false` disables.
|
||||
|
||||
An object can also be passed for specific configuration, as shown below.
|
||||
|
||||
```ts
|
||||
interface TransitionOptions {
|
||||
/**
|
||||
* Whether to enable page transition animations.
|
||||
* @default true
|
||||
*/
|
||||
page?: boolean
|
||||
/**
|
||||
* Whether to enable blog post list transition animations.
|
||||
* @default true
|
||||
*/
|
||||
postList?: boolean
|
||||
/**
|
||||
* Whether to enable dark/light mode switch transition animations,
|
||||
* or configure the transition animation type.
|
||||
* @default 'fade'
|
||||
*/
|
||||
appearance?: boolean | 'fade' | 'circle-clip' | 'horizontal-clip' | 'vertical-clip' | 'skew-clip'
|
||||
}
|
||||
```
|
||||
|
||||
### footer
|
||||
|
||||
- **Type:** `false | { message: string; copyright: string }`
|
||||
- **Default:** `false`
|
||||
- **Details:** Footer configuration.
|
||||
|
||||
### bulletin
|
||||
|
||||
- **Type:** `boolean | BulletinOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Bulletin board configuration.
|
||||
|
||||
For details, please refer to [Bulletin Board](../guide/features/bulletin.md).
|
||||
|
||||
### editLinkPattern
|
||||
|
||||
- **Type:** `string`
|
||||
- **Default:** `''`
|
||||
- **Details:** Regular expression for the edit link.
|
||||
|
||||
Example: `':repo/edit/:branch/:path'`
|
||||
|
||||
### copyright
|
||||
|
||||
- **Type:** `boolean | CopyrightLicense | CopyrightOptions`
|
||||
- **Default:** `false`
|
||||
- **Details:** Copyright configuration.
|
||||
|
||||
For details, please refer to [Copyright](../guide/features/copyright.md).
|
||||
|
||||
### prevPage
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to show the previous page link.
|
||||
|
||||
### nextPage
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to show the next page link.
|
||||
|
||||
### createTime
|
||||
|
||||
- **Type:** `boolean | 'only-posts'`
|
||||
- **Default:** `true`
|
||||
- **Details:** Whether to display the creation time.
|
||||
|
||||
- `false` - Do not display.
|
||||
- `'only-posts'` - Only display on blog post list pages.
|
||||
- `true` - Display on all article pages.
|
||||
14
docs/en/contributing.md
Normal file
14
docs/en/contributing.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Contributing
|
||||
createTime: 2024/03/13 21:27:45
|
||||
permalink: /en/contributing/
|
||||
article: false
|
||||
externalLinkIcon: false
|
||||
readingTime: false
|
||||
editLink: false
|
||||
contributors: false
|
||||
changelog: false
|
||||
search: false
|
||||
---
|
||||
|
||||
<!-- @include: ../../CONTRIBUTING.en-US.md{2-} -->
|
||||
164
docs/en/friends.md
Normal file
164
docs/en/friends.md
Normal file
@ -0,0 +1,164 @@
|
||||
---
|
||||
pageLayout: friends
|
||||
title: Friends Links
|
||||
description: Here is the description text for the friend links. This page is for demonstration purposes only.
|
||||
permalink: /en/friends/
|
||||
article: true
|
||||
list:
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
location: GuangZhou
|
||||
organization: PengZhanBo
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
groups:
|
||||
-
|
||||
title: 分组 1
|
||||
desc: 自定义颜色
|
||||
list:
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
backgroundColor: rgb(255,153,0)
|
||||
color: rgb(255,255,153)
|
||||
nameColor: rgb(255,255,170)
|
||||
socials:
|
||||
-
|
||||
icon: github
|
||||
link: https://github.com/pengzhanbo
|
||||
-
|
||||
icon: twitter
|
||||
link: https://twitter.com/pengzhanbo
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
backgroundColor: rgb(255,102,102)
|
||||
color: rgb(255,204,204)
|
||||
nameColor: rgb(255,238,238)
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
backgroundColor: rgb(0,153,204)
|
||||
color: rgb(153,238,255)
|
||||
nameColor: rgb(153,255,255)
|
||||
-
|
||||
title: 分组 2
|
||||
desc: 这里是分组 2 的描述文字
|
||||
list:
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: 即使慢,驰而不息,纵会落后,纵会失败,但必须能够到达他所向的目标。
|
||||
---
|
||||
126
docs/en/guide/api/client.md
Normal file
126
docs/en/guide/api/client.md
Normal file
@ -0,0 +1,126 @@
|
||||
---
|
||||
title: Client
|
||||
icon: nimbus:browser
|
||||
createTime: 2025/10/08 21:58:48
|
||||
permalink: /en/guide/api/client/
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { Layout } from 'vuepress-theme-plume/client'
|
||||
```
|
||||
|
||||
## Layout Components
|
||||
|
||||
- `<Layout />`: Page layout component
|
||||
- `<NotFound />`: 404 page layout component
|
||||
|
||||
```ts
|
||||
import { Layout, NotFound } from 'vuepress-theme-plume/client'
|
||||
```
|
||||
|
||||
## Common Components
|
||||
|
||||
- `<VPLink />`: Link component
|
||||
- `<VPButton />`: Button component
|
||||
- `<VPIcon />`: Icon component
|
||||
- `<VPBadge />`: Badge component
|
||||
- `<VPImage />`: Image component
|
||||
- `<VPHomeBox />`: Home page layout component
|
||||
|
||||
For more components, please check the [source code](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/components).
|
||||
|
||||
```ts
|
||||
import VPButton from 'vuepress-theme-plume/components/VPButton.vue'
|
||||
import VPLink from 'vuepress-theme-plume/components/VPLink.vue'
|
||||
```
|
||||
|
||||
## Composable APIs
|
||||
|
||||
### `useDarkMode()`
|
||||
|
||||
- Type: `() => Ref<boolean>`
|
||||
- Details:
|
||||
|
||||
Returns a reactive reference indicating whether dark mode is enabled.
|
||||
|
||||
```ts
|
||||
import { useDarkMode } from 'vuepress-theme-plume/composables'
|
||||
|
||||
const isDark = useDarkMode()
|
||||
|
||||
// Switch to dark mode
|
||||
isDark.value = true
|
||||
// Switch to light mode
|
||||
isDark.value = false
|
||||
```
|
||||
|
||||
### `useData()`
|
||||
|
||||
- Type: `() => Data`
|
||||
- Details:
|
||||
|
||||
Returns reactive data for various theme properties.
|
||||
|
||||
```ts
|
||||
interface Data {
|
||||
// Theme configuration
|
||||
theme: ThemeLocaleDataRef<PlumeThemeLocaleData>
|
||||
// Current page data
|
||||
page: PageDataRef<PlumeThemePageData>
|
||||
// Current page frontmatter
|
||||
frontmatter: PageFrontmatterRef<Frontmatter<T>>
|
||||
// Current language
|
||||
lang: Ref<string>
|
||||
// Site data
|
||||
site: SiteLocaleDataRef
|
||||
// Whether dark mode is enabled
|
||||
isDark: Ref<boolean>
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { useData } from 'vuepress-theme-plume/composables'
|
||||
|
||||
const { site, page, frontmatter, isDark, lang } = useData()
|
||||
|
||||
// Current page title
|
||||
console.log(frontmatter.value.title)
|
||||
```
|
||||
|
||||
### `useLocalePostList()`
|
||||
|
||||
- Type: `() => Ref<PostItem[]>`
|
||||
- Details:
|
||||
|
||||
Returns a reactive reference to the post list data.
|
||||
|
||||
```ts
|
||||
interface PostItem {
|
||||
path: string
|
||||
title: string
|
||||
excerpt: string
|
||||
tags: string[]
|
||||
sticky: boolean
|
||||
categoryList: CategoryItem[]
|
||||
createTime: string
|
||||
lang: string
|
||||
encrypt?: boolean
|
||||
}
|
||||
|
||||
interface CategoryItem {
|
||||
type: string | number
|
||||
name: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { useLocalePostList } from 'vuepress-theme-plume/composables'
|
||||
|
||||
const postList = useLocalePostList()
|
||||
```
|
||||
|
||||
### More
|
||||
|
||||
For other composable APIs, please check the [source code](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/composables).
|
||||
48
docs/en/guide/api/node.md
Normal file
48
docs/en/guide/api/node.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Node
|
||||
icon: fa6-brands:node
|
||||
createTime: 2025/10/08 21:59:13
|
||||
permalink: /en/guide/api/node/
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
```
|
||||
|
||||
## `plumeTheme(options)`
|
||||
|
||||
__options__ : `PlumeThemeOptions`
|
||||
|
||||
Theme configuration function.
|
||||
|
||||
See [Theme Configuration](../config/theme.md) for more information.
|
||||
|
||||
## `defineThemeConfig(options)`
|
||||
|
||||
Theme configuration helper function for use in separate `plume.config.ts` files.
|
||||
|
||||
See [Theme Configuration File](../config/intro.md#theme-configuration-file) for more information.
|
||||
|
||||
## `defineNavbarConfig(options)`
|
||||
|
||||
Theme navbar configuration type helper function.
|
||||
|
||||
See [Theme Configuration](../config/navbar.md) for more information.
|
||||
|
||||
## `defineCollections(options)`
|
||||
|
||||
__options:__ `(ThemePostCollection | ThemeDocCollection)[]`
|
||||
|
||||
Theme collections configuration type helper function.
|
||||
|
||||
See [Theme Configuration](../config/collection.md) for more information.
|
||||
|
||||
## `defineCollection(options)`
|
||||
|
||||
__options:__ `ThemePostCollection | ThemeDocCollection`
|
||||
|
||||
Theme single collection configuration type helper function.
|
||||
|
||||
See [Theme Configuration](../config/collection.md) for more information.
|
||||
121
docs/en/guide/chart/chart.md
Normal file
121
docs/en/guide/chart/chart.md
Normal file
@ -0,0 +1,121 @@
|
||||
---
|
||||
title: chart.js
|
||||
createTime: 2025/10/08 19:33:49
|
||||
icon: solar:chart-bold
|
||||
permalink: /en/guide/chart/chartjs/
|
||||
---
|
||||
|
||||
[chart.js]: https://www.chartjs.org/docs/latest/
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding [chart.js] charts within articles.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default in the theme.
|
||||
|
||||
You need to install the [chart.js] library in your project.
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm install chart.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, enable the feature in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
chartjs: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
````md
|
||||
::: chartjs Title
|
||||
```json
|
||||
{
|
||||
// Chart configuration goes here
|
||||
}
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
Refer to the [chart.js] documentation for chart configuration details.
|
||||
|
||||
## Examples
|
||||
|
||||
::: note
|
||||
Examples are forked from [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/chartjs.html),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
### Bar Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-1.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-1.snippet.md{2-41} -->
|
||||
|
||||
### Bubble Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-2.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-2.snippet.md{2-20} -->
|
||||
|
||||
### Line Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-3.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-3.snippet.md{2-20} -->
|
||||
|
||||
### Polar Area Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-4.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-4.snippet.md{2-24} -->
|
||||
|
||||
### Radar Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-5.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-5.snippet.md{2-42} -->
|
||||
|
||||
### Scatter Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-6.snippet.md -->
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/chart-6.snippet.md{2-30} -->
|
||||
230
docs/en/guide/chart/echarts.md
Normal file
230
docs/en/guide/chart/echarts.md
Normal file
@ -0,0 +1,230 @@
|
||||
---
|
||||
title: ECharts
|
||||
createTime: 2025/10/08 19:34:03
|
||||
icon: raphael:piechart
|
||||
permalink: /en/guide/chart/echarts/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding [ECharts](https://echarts.apache.org/zh/index.html) charts within articles.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default in the theme.
|
||||
|
||||
You need to install the [ECharts](https://echarts.apache.org/zh/index.html) library in your project.
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm install echarts
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, enable the feature in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
echarts: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: note
|
||||
The following documentation is forked from [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/echarts.html),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
## Syntax
|
||||
|
||||
### JSON Configuration
|
||||
|
||||
If you can easily generate data, you can provide ECharts configuration directly through a JSON code block:
|
||||
|
||||
````md
|
||||
::: echarts Title
|
||||
|
||||
```json
|
||||
{
|
||||
// ECharts chart configuration goes here
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
````
|
||||
|
||||
### JavaScript Configuration
|
||||
|
||||
If you need to fetch data through scripts, you can use js and javascript code blocks.
|
||||
|
||||
The Echarts instance is exposed through the `echarts` variable, and you should assign the Echarts configuration to the `option` variable.
|
||||
You can also assign `width` and `height` to set the chart dimensions.
|
||||
|
||||
````md
|
||||
::: echarts Title
|
||||
```js
|
||||
const option = {
|
||||
// ECharts chart configuration goes here
|
||||
}
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
:::tip
|
||||
You can use top-level `await` and `fetch` to retrieve data from network requests.
|
||||
:::
|
||||
|
||||
Refer to the [ECharts documentation](https://echarts.apache.org/handbook/zh/get-started/) for configuration details.
|
||||
|
||||
## Advanced
|
||||
|
||||
You can import and use `defineEchartsConfig` in the
|
||||
[client configuration file](https://vuejs.press/zh/guide/configuration.html##使用脚本) to customize ECharts:
|
||||
|
||||
```ts
|
||||
import { defineEchartsConfig } from '@vuepress/plugin-markdown-chart/client'
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
defineEchartsConfig({
|
||||
options: {
|
||||
// Global ECharts configuration
|
||||
},
|
||||
setup: async () => {
|
||||
// ECharts setup
|
||||
// Example: await import("echarts-wordcloud")
|
||||
},
|
||||
})
|
||||
|
||||
export default defineClientConfig({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Line Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-1.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-1.snippet.md{2-100} -->
|
||||
|
||||
### Bar Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-2.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-2.snippet.md{2-75} -->
|
||||
|
||||
### Pie Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-3.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-3.snippet.md{2-74} -->
|
||||
|
||||
### Scatter Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-4.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-4.snippet.md{2-39} -->
|
||||
|
||||
### Polar Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-5.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-5.snippet.md{2-40} -->
|
||||
|
||||
### Candlestick Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-6.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-6.snippet.md{2-308} -->
|
||||
|
||||
### Radar Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-7.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-7.snippet.md{2-36} -->
|
||||
|
||||
### Heatmap
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-8.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-8.snippet.md{2-179} -->
|
||||
|
||||
### Tree Chart
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-9.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-9.snippet.md{2-33} -->
|
||||
|
||||
### Multiple Charts
|
||||
|
||||
**Input:**
|
||||
|
||||
:::: details View Code
|
||||
<!-- @include: ../../../snippet/echarts-10.snippet.md -->
|
||||
::::
|
||||
|
||||
**Output:**
|
||||
|
||||
<!-- @include: ../../../snippet/echarts-10.snippet.md{2-69} -->
|
||||
351
docs/en/guide/chart/flowchart.md
Normal file
351
docs/en/guide/chart/flowchart.md
Normal file
@ -0,0 +1,351 @@
|
||||
---
|
||||
title: flowchart
|
||||
createTime: 2025/10/08 19:34:31
|
||||
icon: f7:flowchart
|
||||
permalink: /en/guide/chart/flowchart/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding [flowchart](http://flowchart.js.org/) diagrams within articles.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default in the theme.
|
||||
|
||||
You need to install the [flowchart.ts](http://flowchart.js.org/) library in your project.
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm install flowchart.ts
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, enable the feature in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
flowchart: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: note
|
||||
The following documentation is forked from [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/flowchart.html),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
## Syntax
|
||||
|
||||
````md
|
||||
<!------- ↓ :preset is optional -->
|
||||
```flow:preset
|
||||
|
||||
<!-- Place your flowchart code here -->
|
||||
|
||||
```
|
||||
````
|
||||
|
||||
Currently available presets:
|
||||
|
||||
- vue (default)
|
||||
- ant
|
||||
- pie
|
||||
|
||||
## Demo
|
||||
|
||||
::: demo markdown title="Vue Theme"
|
||||
|
||||
````md
|
||||
```flow
|
||||
st=>start: Start|past:>http://www.google.com[blank]
|
||||
e=>end: End|future:>http://www.google.com
|
||||
op1=>operation: Operation 1|past
|
||||
op2=>operation: Operation 2|current
|
||||
sub1=>subroutine: Subroutine|invalid
|
||||
cond=>condition: Yes/No?|approved:>http://www.google.com
|
||||
c2=>condition: Condition 2|rejected
|
||||
io=>inputoutput: Process input...|future
|
||||
|
||||
st->op1(right)->cond
|
||||
cond(yes, right)->c2
|
||||
cond(no)->sub1(left)->op1
|
||||
c2(yes)->io->e
|
||||
c2(no)->op2->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Ant Theme"
|
||||
|
||||
````md
|
||||
```flow:ant
|
||||
st=>start: Start|past:>http://www.google.com[blank]
|
||||
e=>end: End|future:>http://www.google.com
|
||||
op1=>operation: Operation 1|past
|
||||
op2=>operation: Operation 2|current
|
||||
sub1=>subroutine: Subroutine|invalid
|
||||
cond=>condition: Yes/No?|approved:>http://www.google.com
|
||||
c2=>condition: Condition 2|rejected
|
||||
io=>inputoutput: Process input...|future
|
||||
|
||||
st->op1(right)->cond
|
||||
cond(yes, right)->c2
|
||||
cond(no)->sub1(left)->op1
|
||||
c2(yes)->io->e
|
||||
c2(no)->op2->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Pie Theme"
|
||||
|
||||
````md
|
||||
```flow:pie
|
||||
st=>start: Start|past:>http://www.google.com[blank]
|
||||
e=>end: End|future:>http://www.google.com
|
||||
op1=>operation: Operation 1|past
|
||||
op2=>operation: Operation 2|current
|
||||
sub1=>subroutine: Subroutine|invalid
|
||||
cond=>condition: Yes/No?|approved:>http://www.google.com
|
||||
c2=>condition: Condition 2|rejected
|
||||
io=>inputoutput: Process input...|future
|
||||
|
||||
st->op1(right)->cond
|
||||
cond(yes, right)->c2
|
||||
cond(no)->sub1(left)->op1
|
||||
c2(yes)->io->e
|
||||
c2(no)->op2->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
## Flowchart Introduction
|
||||
|
||||
### Node Types
|
||||
|
||||
Define node shapes.
|
||||
|
||||
#### Start & End
|
||||
|
||||
- `[Variable]->start: [Text]`
|
||||
|
||||
Used for the first node in the flowchart.
|
||||
Default text is `Start`.
|
||||
|
||||
- `[Variable]->end: [Text]`
|
||||
|
||||
Used for the last node in the flowchart.
|
||||
Default text is `End`.
|
||||
|
||||
::: demo markdown title="Start & End"
|
||||
|
||||
````md
|
||||
```flow
|
||||
st=>start: Start
|
||||
e=>end: End
|
||||
|
||||
st->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
#### Operation
|
||||
|
||||
`[Variable]->operation: [Text]`
|
||||
|
||||
::: demo markdown title="Operation"
|
||||
|
||||
````md
|
||||
```flow
|
||||
process=>operation: Operation
|
||||
e=>end: End
|
||||
|
||||
process->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
#### Input/Output
|
||||
|
||||
`[Variable]->inputoutput: [Text]`
|
||||
|
||||
:::demo markdown title="Input/Output"
|
||||
|
||||
````md
|
||||
```flow
|
||||
process=>inputoutput: Input/Output
|
||||
e=>end: End
|
||||
|
||||
process->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
#### Subroutine
|
||||
|
||||
`[Variable]->subroutine: [Text]`
|
||||
|
||||
::: demo markdown title="Subroutine"
|
||||
|
||||
````md
|
||||
```flow
|
||||
process=>subroutine: Subroutine
|
||||
e=>end: End
|
||||
|
||||
process->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
#### Condition
|
||||
|
||||
- `[Variable]->condition: [Text]`
|
||||
|
||||
- `[Variable]([yesText])->[Position]`
|
||||
- `[Variable]([noText])->[Position]`
|
||||
|
||||
::: demo markdown title="Condition"
|
||||
|
||||
````md
|
||||
```flow
|
||||
cond=>condition: Execute operation?
|
||||
process=>operation: Operation
|
||||
e=>end: End
|
||||
|
||||
cond(yes)->process->e
|
||||
cond(no)->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
#### Parallel
|
||||
|
||||
Define multiple processes that start simultaneously.
|
||||
|
||||
- `[Variable]->parallel: [Text]`
|
||||
- `[Variable](path1, direction)->[Position]`
|
||||
- `[Variable](path1, direction)->[Position]`
|
||||
|
||||
::: demo markdown title="Parallel"
|
||||
|
||||
````md
|
||||
```flow
|
||||
para=>parallel: Parallel tasks
|
||||
process=>operation: Operation
|
||||
e=>end: End
|
||||
|
||||
para(path1, bottom)->process->e
|
||||
para(path2)->e
|
||||
```
|
||||
````
|
||||
|
||||
:::
|
||||
|
||||
### Connections
|
||||
|
||||
Connections are described after node definitions in the flowchart, using `->` to specify links between nodes, e.g., `nodeVar1->nodeVar2->nodeVar3`
|
||||
|
||||
Flows can be split:
|
||||
|
||||
```md
|
||||
nodeVar1->nodeVar2
|
||||
nodeVar2->nodeVar3
|
||||
```
|
||||
|
||||
Connection format is defined as:
|
||||
|
||||
`<node variable name>[(<specification1>[, <specification2])]-><node variable name>[[(<specification1>[, <specification2])]-><node variable name>]`
|
||||
|
||||
Items in `[]` are optional.
|
||||
|
||||
### Directions
|
||||
|
||||
The following directions are available and define which direction the connection will leave the node.
|
||||
If more than one specifier is present, the last one takes precedence.
|
||||
All nodes have default directions, making this an optional specification. Available values for `<direction>` are:
|
||||
|
||||
- `left`
|
||||
- `right`
|
||||
- `top`
|
||||
- `bottom`
|
||||
|
||||
### Node-specific Specifiers
|
||||
|
||||
Each node variable has optional specifiers, such as direction, and some variables have special specifiers
|
||||
depending on the node type defined below. Add specifiers after the variable name in `()` separated by `,`,
|
||||
e.g., `nodeVar (spec1, spec2)`.
|
||||
|
||||
- **start**
|
||||
**operation**
|
||||
**inputoutput**
|
||||
**subroutine**
|
||||
|
||||
Optional direction
|
||||
|
||||
`startVar(<direction>)->nextNode`
|
||||
|
||||
`operationVar(<direction>)->nextNode`
|
||||
|
||||
`inputoutputVar(<direction>)->nextNode`
|
||||
|
||||
`subroutineVar(<direction>)->nextNode`
|
||||
|
||||
- **condition**
|
||||
|
||||
Must specify `yes` or `no`
|
||||
|
||||
Optional direction
|
||||
|
||||
```md
|
||||
conditionalVar(yes, <direction>)->nextNode1
|
||||
conditionalVar(no, <direction>)->nextNode2
|
||||
```
|
||||
|
||||
- **parallel**
|
||||
|
||||
Must specify path direction `path1`, `path2`, or `path3`
|
||||
|
||||
Optional direction
|
||||
|
||||
```md
|
||||
parallelVar(path1, <direction>)->nextNode1
|
||||
parallelVar(path2, <direction>)->nextNode2
|
||||
parallelVar(path3, <direction>)->nextNode3
|
||||
```
|
||||
|
||||
### URLs
|
||||
|
||||
External links can be added to nodes using the `:>` operator.
|
||||
|
||||
`[blank]` specifies opening in a new page
|
||||
|
||||
```md
|
||||
st=>start: Start:>http://www.google.com[blank]
|
||||
e=>end: End:>http://www.yahoo.com
|
||||
```
|
||||
|
||||
### Recommendations
|
||||
|
||||
Symbols that should probably not be used in text: `=>`, `->`, `:>`, `|`, `@>`, and `:$`
|
||||
|
||||
To emphasize a specific path in the flowchart, you can additionally define it as follows:
|
||||
|
||||
```
|
||||
st@>op1({"stroke":"Red"})@>cond({"stroke":"Red","stroke-width":6,"arrow-end":"classic-wide-long"})@>c2({"stroke":"Red"})@>op2({"stroke":"Red"})@>e({"stroke":"Red"})
|
||||
```
|
||||
90
docs/en/guide/chart/markmap.md
Normal file
90
docs/en/guide/chart/markmap.md
Normal file
@ -0,0 +1,90 @@
|
||||
---
|
||||
title: markmap
|
||||
icon: ri:mind-map
|
||||
createTime: 2025/10/08 14:35:59
|
||||
permalink: /en/guide/chart/markmap/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding [markmap](https://markmap.js.org/) mind maps within articles.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default in the theme.
|
||||
|
||||
You need to install `markmap-lib`, `markmap-toolbar` and `markmap-view` in your project:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i markmap-lib markmap-toolbar markmap-view
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, enable the feature in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
markmap: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: note
|
||||
The following documentation is forked from [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/markmap.html),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
## Syntax
|
||||
|
||||
````md
|
||||
```markmap
|
||||
<!-- Place content here -->
|
||||
```
|
||||
````
|
||||
|
||||
Configuration via Frontmatter syntax is supported.
|
||||
|
||||
## Example
|
||||
|
||||
::: demo markdown title="markmap"
|
||||
|
||||
`````md
|
||||
````markmap
|
||||
---
|
||||
markmap:
|
||||
colorFreezeLevel: 2
|
||||
---
|
||||
|
||||
# markmap
|
||||
|
||||
## Links
|
||||
|
||||
- <https://markmap.js.org/>
|
||||
- [GitHub](https://github.com/markmap/markmap)
|
||||
|
||||
## Features
|
||||
|
||||
- Links
|
||||
- **Strong** ~~Strikethrough~~ *Italic* ==Highlight==
|
||||
- Multi-line
|
||||
text
|
||||
- `Inline code`
|
||||
-
|
||||
```js
|
||||
console.log('code block');
|
||||
```
|
||||
- Katex
|
||||
- $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
|
||||
- Now we can wrap very very very very very very very very very very long text automatically with `maxWidth` option
|
||||
````
|
||||
`````
|
||||
|
||||
:::
|
||||
306
docs/en/guide/chart/mermaid.md
Normal file
306
docs/en/guide/chart/mermaid.md
Normal file
@ -0,0 +1,306 @@
|
||||
---
|
||||
title: mermaid
|
||||
createTime: 2025/10/08 19:34:16
|
||||
icon: file-icons:mermaid
|
||||
permalink: /en/guide/chart/mermaid/
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
主题支持在 文章中 嵌入由 [Mermaid](https://mermaid.js.org/) 。
|
||||
|
||||
该功能由 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/) 提供支持。
|
||||
|
||||
## 配置
|
||||
|
||||
主题默认不启用该功能。
|
||||
|
||||
你需要在你的项目中安装 [mermaid](https://mermaid.js.org/) 库。
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm install mermaid
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
然后在 `.vuepress/config.ts` 配置文件中,启用该功能:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
mermaid: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: note
|
||||
以下文档 Fork 自 [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/mermaid.html),
|
||||
遵循 [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) 许可证。
|
||||
:::
|
||||
|
||||
## 语法
|
||||
|
||||
````md
|
||||
```mermaid
|
||||
|
||||
<!-- 在此处放置 mermaid 代码 -->
|
||||
|
||||
```
|
||||
````
|
||||
|
||||
除了使用 mermaid 代码块,你也可以直接使用以下代码块:
|
||||
|
||||
- class: `classDiagram`
|
||||
- c4c: `C4Context`
|
||||
- er: `erDiagram`
|
||||
- gantt: `gantt`
|
||||
- git-graph: `gitGraph`
|
||||
- journey: `journey`
|
||||
- mindmap: `mindmap`
|
||||
- pie: `pie`
|
||||
- quadrant: `quadrantChart`
|
||||
- requirement: `requirementDiagram`
|
||||
- sankey: `sankey-beta`
|
||||
- sequence: `sequenceDiagram`
|
||||
- state: `stateDiagram-v2`
|
||||
- timeline: `timeline`
|
||||
- xy: `xychart-beta`
|
||||
|
||||
你不需要再声明图表类型,也不需要缩进图表代码。
|
||||
|
||||
当图表支持设置标题时,你可以直接在代码块信息后添加标题:
|
||||
|
||||
````md
|
||||
```sequence 代码标题
|
||||
<!-- 顺序图代码内容
|
||||
... -->
|
||||
```
|
||||
````
|
||||
|
||||
配置文档详见 [Mermaid 文档](https://mermaid.js.org/)
|
||||
|
||||
## 高级
|
||||
|
||||
你可以在 [客户端配置文件](https://vuejs.press/zh/guide/configuration.html#%E5%AE%A2%E6%88%B7%E7%AB%AF%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6)
|
||||
中导入并使用 `defineMermaidConfig` 来自定义 Mermaid 配置:
|
||||
|
||||
```ts
|
||||
import { defineMermaidConfig } from '@vuepress/plugin-markdown-chart/client'
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
defineMermaidConfig({
|
||||
// 在此设置 mermaid 选项
|
||||
})
|
||||
|
||||
export default defineClientConfig({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
## 示例
|
||||
|
||||
### 流程图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-1.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-1.snippet.md{2-20} -->
|
||||
|
||||
### 循序图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-2.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-2.snippet.md{2-11} -->
|
||||
|
||||
### 类图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-3.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-3.snippet.md{2-25} -->
|
||||
|
||||
### 状态图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-4.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-4.snippet.md{2-9} -->
|
||||
|
||||
### 关系图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-5.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-5.snippet.md{2-15} -->
|
||||
|
||||
### 用户日记图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-6.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-6.snippet.md{2-11} -->
|
||||
|
||||
### 甘特图
|
||||
|
||||
**输入:**
|
||||
|
||||
:::: details 查看代码
|
||||
<!-- @include: ../../snippet/mermaid-7.snippet.md -->
|
||||
::::
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-7.snippet.md{2-31} -->
|
||||
|
||||
### 饼图
|
||||
|
||||
**输入:**
|
||||
|
||||
````md
|
||||
```pie
|
||||
title What Voldemort doesn't have?
|
||||
"FRIENDS" : 2
|
||||
"FAMILY" : 3
|
||||
"NOSE" : 45
|
||||
```
|
||||
````
|
||||
|
||||
**输出:**
|
||||
|
||||
```pie
|
||||
title What Voldemort doesn't have?
|
||||
"FRIENDS" : 2
|
||||
"FAMILY" : 3
|
||||
"NOSE" : 45
|
||||
```
|
||||
|
||||
### Git 图表
|
||||
|
||||
**输入:**
|
||||
|
||||
:::: details 查看代码
|
||||
<!-- @include: ../../snippet/mermaid-8.snippet.md-->
|
||||
::::
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-8.snippet.md{2-44} -->
|
||||
|
||||
### C4C 图表
|
||||
|
||||
**输入:**
|
||||
|
||||
:::: details 查看代码
|
||||
<!-- @include: ../../snippet/mermaid-9.snippet.md -->
|
||||
::::
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-9.snippet.md{2-34} -->
|
||||
|
||||
### 思维导图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-10.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-10.snippet.md{2-19} -->
|
||||
|
||||
### 时序图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-11.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-11.snippet.md{2-11} -->
|
||||
|
||||
### 桑基图
|
||||
|
||||
**输入:**
|
||||
|
||||
:::: details 查看代码
|
||||
<!-- @include: ../../snippet/mermaid-12.snippet.md -->
|
||||
::::
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-12.snippet.md{2-71} -->
|
||||
|
||||
### 依赖图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-13.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-13.snippet.md{2-15} -->
|
||||
|
||||
### 象限图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-14.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-14.snippet.md{2-16} -->
|
||||
|
||||
### XY图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-15.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-15.snippet.md{2-8} -->
|
||||
|
||||
### 块图
|
||||
|
||||
**输入:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-16.snippet.md -->
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-16.snippet.md{2-12} -->
|
||||
|
||||
### 复杂例子
|
||||
|
||||
**输入:**
|
||||
|
||||
:::: details 查看代码
|
||||
<!-- @include: ../../snippet/mermaid-17.snippet.md -->
|
||||
::::
|
||||
|
||||
**输出:**
|
||||
|
||||
<!-- @include: ../../snippet/mermaid-17.snippet.md{2-24} -->
|
||||
690
docs/en/guide/chart/plantuml.md
Normal file
690
docs/en/guide/chart/plantuml.md
Normal file
@ -0,0 +1,690 @@
|
||||
---
|
||||
title: PlantUML
|
||||
icon: arcticons:uml-class-editor
|
||||
createTime: 2025/10/08 15:02:08
|
||||
permalink: /en/guide/chart/plantuml/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding [PlantUML](https://plantuml.com/) diagrams within articles.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default in the theme.
|
||||
|
||||
Enable the feature in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
plantuml: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: note
|
||||
The following documentation is forked from [@vuepress/plugin-markdown-chart](https://ecosystem.vuejs.press/plugins/markdown/markdown-chart/plantuml.html),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
## Format
|
||||
|
||||
You can insert the same content supported by [plantuml](https://plantuml.com/), for example:
|
||||
|
||||
```md
|
||||
@startuml
|
||||
content
|
||||
@enduml
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
::: demo markdown title="Sequence Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
Alice -> Bob: Authentication Request
|
||||
|
||||
alt successful case
|
||||
|
||||
Bob -> Alice: Authentication Accepted
|
||||
|
||||
else some failure case
|
||||
|
||||
Bob -> Alice: Authentication Failed
|
||||
group My own label
|
||||
Alice -> Log : Log attack start
|
||||
loop 1000 times
|
||||
Alice -> Bob: DNS Attack
|
||||
end
|
||||
Alice -> Log : Log attack end
|
||||
end
|
||||
|
||||
else Another failure
|
||||
|
||||
Bob -> Alice: Please repeat
|
||||
|
||||
end
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Use Case Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
:Main Admin: as Admin
|
||||
(Use the application) as (Use)
|
||||
|
||||
User -> (Start)
|
||||
User --> (Use)
|
||||
|
||||
Admin ---> (Use)
|
||||
|
||||
note right of Admin : This is an example.
|
||||
|
||||
note right of (Use)
|
||||
A note can also
|
||||
be on several lines
|
||||
end note
|
||||
|
||||
note "This note is connected\nto several objects." as N2
|
||||
(Start) .. N2
|
||||
N2 .. (Use)
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Class Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
abstract class AbstractList
|
||||
abstract AbstractCollection
|
||||
interface List
|
||||
interface Collection
|
||||
|
||||
List <|-- AbstractList
|
||||
Collection <|-- AbstractCollection
|
||||
|
||||
Collection <|- List
|
||||
AbstractCollection <|- AbstractList
|
||||
AbstractList <|-- ArrayList
|
||||
|
||||
class ArrayList {
|
||||
Object[] elementData
|
||||
size()
|
||||
}
|
||||
|
||||
enum TimeUnit {
|
||||
DAYS
|
||||
HOURS
|
||||
MINUTES
|
||||
}
|
||||
|
||||
annotation SuppressWarnings
|
||||
|
||||
annotation Annotation {
|
||||
annotation with members
|
||||
String foo()
|
||||
String bar()
|
||||
}
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Activity Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
|
||||
start
|
||||
:ClickServlet.handleRequest();
|
||||
:new page;
|
||||
if (Page.onSecurityCheck) then (true)
|
||||
:Page.onInit();
|
||||
if (isForward?) then (no)
|
||||
:Process controls;
|
||||
if (continue processing?) then (no)
|
||||
stop
|
||||
endif
|
||||
|
||||
if (isPost?) then (yes)
|
||||
:Page.onPost();
|
||||
else (no)
|
||||
:Page.onGet();
|
||||
endif
|
||||
:Page.onRender();
|
||||
endif
|
||||
else (false)
|
||||
endif
|
||||
|
||||
if (do redirect?) then (yes)
|
||||
:redirect process;
|
||||
else
|
||||
if (do forward?) then (yes)
|
||||
:Forward request;
|
||||
else (no)
|
||||
:Render page template;
|
||||
endif
|
||||
endif
|
||||
|
||||
stop
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Component Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
package "Some Group" {
|
||||
HTTP - [First Component]
|
||||
[Another Component]
|
||||
}
|
||||
|
||||
node "Other Groups" {
|
||||
FTP - [Second Component]
|
||||
[First Component] --> FTP
|
||||
}
|
||||
|
||||
cloud {
|
||||
[Example 1]
|
||||
}
|
||||
|
||||
database "MySql" {
|
||||
folder "This is my folder" {
|
||||
[Folder 3]
|
||||
}
|
||||
frame "Foo" {
|
||||
[Frame 4]
|
||||
}
|
||||
}
|
||||
|
||||
[Another Component] --> [Example 1]
|
||||
[Example 1] --> [Folder 3]
|
||||
[Folder 3] --> [Frame 4]
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="State Diagram"
|
||||
|
||||
``` md
|
||||
@startuml
|
||||
state start1 <<start>>
|
||||
state choice1 <<choice>>
|
||||
state fork1 <<fork>>
|
||||
state join2 <<join>>
|
||||
state end3 <<end>>
|
||||
|
||||
[*] --> choice1 : from start\nto choice
|
||||
start1 --> choice1 : from start stereo\nto choice
|
||||
|
||||
choice1 --> fork1 : from choice\nto fork
|
||||
choice1 --> join2 : from choice\nto join
|
||||
choice1 --> end3 : from choice\nto end stereo
|
||||
|
||||
fork1 ---> State1 : from fork\nto state
|
||||
fork1 --> State2 : from fork\nto state
|
||||
|
||||
State2 --> join2 : from state\nto join
|
||||
State1 --> [*] : from state\nto end
|
||||
|
||||
join2 --> [*] : from join\nto end
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Object Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
object London
|
||||
object Washington
|
||||
object Berlin
|
||||
object NewYork
|
||||
|
||||
map CapitalCity {
|
||||
UK *-> London
|
||||
USA *--> Washington
|
||||
Germany *---> Berlin
|
||||
}
|
||||
|
||||
NewYork --> CapitalCity::USA
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Deployment Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
|
||||
node node1
|
||||
node node2
|
||||
node node3
|
||||
node node4
|
||||
node node5
|
||||
node1 -- node2 : label1
|
||||
node1 .. node3 : label2
|
||||
node1 ~~ node4 : label3
|
||||
node1 == node5
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Timing Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
scale 5 as 150 pixels
|
||||
|
||||
clock clk with period 1
|
||||
binary "Enable" as en
|
||||
binary "Read/Write" as rw
|
||||
binary "Data Valid" as dv
|
||||
concise "Data Bus" as db
|
||||
concise "Address Bus" as addr
|
||||
|
||||
@6 as :write_beg
|
||||
@10 as :write_end
|
||||
|
||||
@15 as :read_beg
|
||||
@19 as :read_end
|
||||
|
||||
@0
|
||||
en is low
|
||||
db is "0x0"
|
||||
addr is "0x03f"
|
||||
rw is low
|
||||
dv is 0
|
||||
|
||||
@:write_beg-3
|
||||
en is high
|
||||
@:write_beg-2
|
||||
db is "0xDEADBEEF"
|
||||
@:write_beg-1
|
||||
dv is 1
|
||||
@:write_beg
|
||||
rw is high
|
||||
|
||||
@:write_end
|
||||
rw is low
|
||||
dv is low
|
||||
@:write_end+1
|
||||
rw is low
|
||||
db is "0x0"
|
||||
addr is "0x23"
|
||||
|
||||
@12
|
||||
dv is high
|
||||
@13
|
||||
db is "0xFFFF"
|
||||
|
||||
@20
|
||||
en is low
|
||||
dv is low
|
||||
@21
|
||||
db is "0x0"
|
||||
|
||||
highlight :write_beg to :write_end #Gold:Write
|
||||
highlight :read_beg to :read_end #lightBlue:Read
|
||||
|
||||
db@:write_beg-1 <-> @:write_end : Setup Time
|
||||
db@:write_beg-1 -> addr@:write_end+1 : Hold
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Regex Diagram"
|
||||
|
||||
```md
|
||||
@startregex
|
||||
/<style(\s*lang=(['"])(.*?)\2)?\s*(?:scoped)?>([\s\S]+)<\/style>
|
||||
@endregex
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Network Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
nwdiag {
|
||||
network dmz {
|
||||
address = "210.x.x.x/24"
|
||||
|
||||
web01 [address = "210.x.x.1"];
|
||||
web02 [address = "210.x.x.2"];
|
||||
}
|
||||
network internal {
|
||||
address = "172.x.x.x/24";
|
||||
|
||||
web01 [address = "172.x.x.1"];
|
||||
web02 [address = "172.x.x.2"];
|
||||
db01;
|
||||
db02;
|
||||
}
|
||||
}
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Salt (GUI) Diagram"
|
||||
|
||||
```md
|
||||
@startsalt
|
||||
{+
|
||||
{/ <b>General | Full Screen | Behavior | Saving }
|
||||
{
|
||||
{ Image opening mode: | ^Smart Mode^ }
|
||||
[X] Smooth images when zooming
|
||||
[X] Confirm image deletion
|
||||
[ ] Show hidden images
|
||||
}
|
||||
[Close]
|
||||
}
|
||||
@endsalt
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Archimate Diagram"
|
||||
|
||||
```md
|
||||
@startuml
|
||||
skinparam rectangle<<behavior>> {
|
||||
roundCorner 25
|
||||
}
|
||||
sprite $bProcess jar:archimate/business-process
|
||||
sprite $aService jar:archimate/application-service
|
||||
sprite $aComponent jar:archimate/application-component
|
||||
|
||||
rectangle "Handle claim" as HC <<$bProcess>><<behavior>> #Business
|
||||
rectangle "Capture Information" as CI <<$bProcess>><<behavior>> #Business
|
||||
rectangle "Notify\nAdditional Stakeholders" as NAS <<$bProcess>><<behavior>> #Business
|
||||
rectangle "Validate" as V <<$bProcess>><<behavior>> #Business
|
||||
rectangle "Investigate" as I <<$bProcess>><<behavior>> #Business
|
||||
rectangle "Pay" as P <<$bProcess>><<behavior>> #Business
|
||||
|
||||
HC *-down- CI
|
||||
HC *-down- NAS
|
||||
HC *-down- V
|
||||
HC *-down- I
|
||||
HC *-down- P
|
||||
|
||||
CI -right->> NAS
|
||||
NAS -right->> V
|
||||
V -right->> I
|
||||
I -right->> P
|
||||
|
||||
rectangle "Scanning" as scanning <<$aService>><<behavior>> #Application
|
||||
rectangle "Customer admnistration" as customerAdministration <<$aService>><<behavior>> #Application
|
||||
rectangle "Claims admnistration" as claimsAdministration <<$aService>><<behavior>> #Application
|
||||
rectangle Printing <<$aService>><<behavior>> #Application
|
||||
rectangle Payment <<$aService>><<behavior>> #Application
|
||||
|
||||
scanning -up-> CI
|
||||
customerAdministration -up-> CI
|
||||
claimsAdministration -up-> NAS
|
||||
claimsAdministration -up-> V
|
||||
claimsAdministration -up-> I
|
||||
Payment -up-> P
|
||||
|
||||
Printing -up-> V
|
||||
Printing -up-> P
|
||||
|
||||
rectangle "Document\nManagement\nSystem" as DMS <<$aComponent>> #Application
|
||||
rectangle "General\nCRM\nSystem" as CRM <<$aComponent>> #Application
|
||||
rectangle "Home & Away\nPolicy\nAdministration" as HAPA <<$aComponent>> #Application
|
||||
rectangle "Home & Away\nFinancial\nAdministration" as HFPA <<$aComponent>> #Application
|
||||
|
||||
DMS .up.|> scanning
|
||||
DMS .up.|> Printing
|
||||
CRM .up.|> customerAdministration
|
||||
HAPA .up.|> claimsAdministration
|
||||
HFPA .up.|> Payment
|
||||
|
||||
legend left
|
||||
Example from the "Archisurance case study" (OpenGroup).
|
||||
See
|
||||
====
|
||||
<$bProcess> :business process
|
||||
====
|
||||
<$aService> : application service
|
||||
====
|
||||
<$aComponent> : application component
|
||||
endlegend
|
||||
@enduml
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Gantt Chart"
|
||||
|
||||
```md
|
||||
@startgantt
|
||||
<style>
|
||||
ganttDiagram {
|
||||
task {
|
||||
FontName Helvetica
|
||||
FontColor red
|
||||
FontSize 18
|
||||
FontStyle bold
|
||||
BackGroundColor GreenYellow
|
||||
LineColor blue
|
||||
}
|
||||
milestone {
|
||||
FontColor blue
|
||||
FontSize 25
|
||||
FontStyle italic
|
||||
BackGroundColor yellow
|
||||
LineColor red
|
||||
}
|
||||
note {
|
||||
FontColor DarkGreen
|
||||
FontSize 10
|
||||
LineColor OrangeRed
|
||||
}
|
||||
arrow {
|
||||
FontName Helvetica
|
||||
FontColor red
|
||||
FontSize 18
|
||||
FontStyle bold
|
||||
BackGroundColor GreenYellow
|
||||
LineColor blue
|
||||
LineStyle 8.0;13.0
|
||||
LineThickness 3.0
|
||||
}
|
||||
separator {
|
||||
BackgroundColor lightGreen
|
||||
LineStyle 8.0;3.0
|
||||
LineColor red
|
||||
LineThickness 1.0
|
||||
FontSize 16
|
||||
FontStyle bold
|
||||
FontColor purple
|
||||
Margin 5
|
||||
Padding 20
|
||||
}
|
||||
timeline {
|
||||
BackgroundColor Bisque
|
||||
}
|
||||
closed {
|
||||
BackgroundColor pink
|
||||
FontColor red
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Project starts the 2020-12-01
|
||||
|
||||
[Task1] requires 10 days
|
||||
sunday are closed
|
||||
|
||||
note bottom
|
||||
memo1 ...
|
||||
memo2 ...
|
||||
explanations1 ...
|
||||
explanations2 ...
|
||||
end note
|
||||
|
||||
[Task2] requires 20 days
|
||||
[Task2] starts 10 days after [Task1]'s end
|
||||
-- Separator title --
|
||||
[M1] happens on 5 days after [Task1]'s end
|
||||
|
||||
<style>
|
||||
separator {
|
||||
LineColor black
|
||||
Margin 0
|
||||
Padding 0
|
||||
}
|
||||
</style>
|
||||
|
||||
-- end --
|
||||
@endgantt
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Mind Map"
|
||||
|
||||
```md
|
||||
@startmindmap
|
||||
caption figure 1
|
||||
title My super title
|
||||
|
||||
* <&flag>Debian
|
||||
** <&globe>Ubuntu
|
||||
*** Linux Mint
|
||||
*** Kubuntu
|
||||
*** Lubuntu
|
||||
*** KDE Neon
|
||||
** <&graph>LMDE
|
||||
** <&pulse>SolydXK
|
||||
** <&people>SteamOS
|
||||
** <&star>Raspbian with a very long name
|
||||
*** <s>Raspmbc</s> => OSMC
|
||||
*** <s>Raspyfi</s> => Volumio
|
||||
|
||||
header
|
||||
My super header
|
||||
endheader
|
||||
|
||||
center footer My super footer
|
||||
|
||||
legend right
|
||||
Short
|
||||
legend
|
||||
endlegend
|
||||
@endmindmap
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="Work Breakdown Structure"
|
||||
|
||||
```md
|
||||
@startwbs
|
||||
+ New Job
|
||||
++ Decide on Job Requirements
|
||||
+++ Identity gaps
|
||||
+++ Review JDs
|
||||
++++ Sign-Up for courses
|
||||
++++ Volunteer
|
||||
++++ Reading
|
||||
++- Checklist
|
||||
+++- Responsibilities
|
||||
+++- Location
|
||||
++ CV Upload Done
|
||||
+++ CV Updated
|
||||
++++ Spelling & Grammar
|
||||
++++ Check dates
|
||||
---- Skills
|
||||
+++ Recruitment sites chosen
|
||||
@endwbs
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="JSON"
|
||||
|
||||
```md
|
||||
@startjson
|
||||
#highlight "lastName"
|
||||
#highlight "address" / "city"
|
||||
#highlight "phoneNumbers" / "0" / "number"
|
||||
{
|
||||
"firstName": "John",
|
||||
"lastName": "Smith",
|
||||
"isAlive": true,
|
||||
"age": 28,
|
||||
"address": {
|
||||
"streetAddress": "21 2nd Street",
|
||||
"city": "New York",
|
||||
"state": "NY",
|
||||
"postalCode": "10021-3100"
|
||||
},
|
||||
"phoneNumbers": [
|
||||
{
|
||||
"type": "home",
|
||||
"number": "212 555-1234"
|
||||
},
|
||||
{
|
||||
"type": "office",
|
||||
"number": "646 555-4567"
|
||||
}
|
||||
],
|
||||
"children": [],
|
||||
"spouse": null
|
||||
}
|
||||
@endjson
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: demo markdown title="YAML"
|
||||
|
||||
```md
|
||||
@startyaml
|
||||
doe: "a deer, a female deer"
|
||||
ray: "a drop of golden sun"
|
||||
pi: 3.14159
|
||||
xmas: true
|
||||
french-hens: 3
|
||||
calling-birds:
|
||||
- huey
|
||||
- dewey
|
||||
- louie
|
||||
- fred
|
||||
xmas-fifth-day:
|
||||
calling-birds: four
|
||||
french-hens: 3
|
||||
golden-rings: 5
|
||||
partridges:
|
||||
count: 1
|
||||
location: "a pear tree"
|
||||
turtle-doves: two
|
||||
@endyaml
|
||||
```
|
||||
|
||||
:::
|
||||
295
docs/en/guide/code/code-tabs.md
Normal file
295
docs/en/guide/code/code-tabs.md
Normal file
@ -0,0 +1,295 @@
|
||||
---
|
||||
title: Code Grouping
|
||||
icon: fluent:group-list-20-filled
|
||||
createTime: 2025/10/08 10:36:59
|
||||
permalink: /en/guide/code/group/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Code Tabs are a powerful feature in the theme for displaying multiple related code snippets side by side.
|
||||
By organizing code in tabbed interfaces, you can clearly compare implementation differences across
|
||||
various tech stacks, configuration approaches, or language versions.
|
||||
|
||||
## Basic Syntax
|
||||
|
||||
### Multiple Code Block Grouping
|
||||
|
||||
Use code tab syntax to organize multiple code blocks within the same tab container:
|
||||
|
||||
**Input:**
|
||||
|
||||
````md
|
||||
::: code-tabs
|
||||
@tab config.js
|
||||
```js
|
||||
/**
|
||||
* @type {import('vuepress').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
@tab config.ts
|
||||
```ts
|
||||
import type { UserConfig } from 'vuepress'
|
||||
|
||||
const config: UserConfig = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
::: code-tabs
|
||||
@tab config.js
|
||||
|
||||
```js
|
||||
/**
|
||||
* @type {import('vuepress').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
@tab config.ts
|
||||
|
||||
```ts
|
||||
import type { UserConfig } from 'vuepress'
|
||||
|
||||
const config: UserConfig = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Setting Default Active Tab
|
||||
|
||||
Specify the default displayed code tab using the `@tab:active` syntax:
|
||||
|
||||
**Input:**
|
||||
|
||||
````md
|
||||
::: code-tabs
|
||||
@tab config.js
|
||||
```js
|
||||
/**
|
||||
* @type {import('vuepress').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
@tab:active config.ts <!-- [!code hl] -->
|
||||
```ts
|
||||
import type { UserConfig } from 'vuepress'
|
||||
|
||||
const config: UserConfig = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
::: code-tabs
|
||||
@tab config.js
|
||||
|
||||
```js
|
||||
/**
|
||||
* @type {import('vuepress').UserConfig}
|
||||
*/
|
||||
const config = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
@tab:active config.ts
|
||||
|
||||
```ts
|
||||
import type { UserConfig } from 'vuepress'
|
||||
|
||||
const config: UserConfig = {
|
||||
// ..
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Tab Icon Support <Badge type="tip" text="v1.0.0-rc.103 +" />
|
||||
|
||||
The theme provides intelligent icon display functionality for code tab labels,
|
||||
automatically matching relevant technology icons based on tab titles.
|
||||
|
||||
### Automatic Icon Recognition
|
||||
|
||||
The theme includes built-in icon mappings for mainstream technologies and languages:
|
||||
|
||||
**Input:**
|
||||
|
||||
````md
|
||||
::: code-tabs
|
||||
@tab pnpm
|
||||
|
||||
```sh
|
||||
pnpm i
|
||||
```
|
||||
|
||||
@tab yarn
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
@tab npm
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
:::
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
::: code-tabs
|
||||
@tab pnpm
|
||||
|
||||
```sh
|
||||
pnpm i
|
||||
```
|
||||
|
||||
@tab yarn
|
||||
|
||||
```sh
|
||||
yarn
|
||||
```
|
||||
|
||||
@tab npm
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Supported Icon Categories
|
||||
|
||||
The theme automatically adapts icons for the following tech stacks:
|
||||
|
||||
- **Runtime Environments**: Node.js, Deno, Bun
|
||||
- **Package Managers**: pnpm, yarn, npm
|
||||
- **Frontend Frameworks**: Vue, React, Angular, Svelte, Solid, Next.js, Nuxt
|
||||
- **Programming Languages**: TypeScript, JavaScript, C, C++, Java, Python, Rust, Kotlin, Swift, Go
|
||||
|
||||
::: info Icon Support Feedback
|
||||
If the technology stack you're using doesn't display icons correctly, please submit an
|
||||
[issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new) to let us know, and we'll add the relevant icon support as soon as possible.
|
||||
:::
|
||||
|
||||
## Icon Configuration Options
|
||||
|
||||
Precisely control icon display behavior through the `markdown.codeTabs` configuration option:
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
codeTabs: {
|
||||
icon: true, // Enable icon functionality
|
||||
}
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Configuration interface definition:
|
||||
|
||||
```ts
|
||||
export interface CodeTabsOptions {
|
||||
icon?: boolean | {
|
||||
named?: false | string[]
|
||||
extensions?: false | string[]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Examples
|
||||
|
||||
**Disable All Icons**:
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
codeTabs: {
|
||||
icon: false
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Display Only Specified Technology Stack Icons**:
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
codeTabs: {
|
||||
icon: {
|
||||
named: ['pnpm', 'yarn', 'npm'], // Only match these technology names
|
||||
extensions: false // Disable file extension matching
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Configuration Notes**:
|
||||
|
||||
- `named`: Exact match for technology names (e.g., `pnpm`, `vue`, `react`)
|
||||
- `extensions`: Match file extensions (e.g., `.ts`, `.js`, `.py`)
|
||||
- Set to `false` to disable the corresponding matching method
|
||||
- Empty arrays use default matching rules
|
||||
- String matching is case-sensitive
|
||||
|
||||
## Performance Optimization Notes
|
||||
|
||||
::: tip Icon Volume Optimization
|
||||
You don't need to worry about the impact of icon resources on build size.
|
||||
Code tab icons are implemented based on the Iconify system, and with the locally installed `@iconify/json` package, the theme automatically:
|
||||
|
||||
- Parses and extracts actually used icon data
|
||||
- Generates optimized local icon resources
|
||||
- Ensures the same icon is bundled only once
|
||||
|
||||
The average size of each colored icon is only 1-2KB. Even with extensive use of different icons, the impact on the final build size is minimal.
|
||||
:::
|
||||
|
||||
Through reasonable configuration and usage, the code tabs feature can significantly improve the readability
|
||||
of technical documentation and user experience, helping readers more efficiently understand differences between various technical solutions.
|
||||
102
docs/en/guide/code/copy-code.md
Normal file
102
docs/en/guide/code/copy-code.md
Normal file
@ -0,0 +1,102 @@
|
||||
---
|
||||
title: Copy Code
|
||||
icon: ph:code
|
||||
createTime: 2025/10/08 09:59:29
|
||||
permalink: /en/guide/code/copy-code/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This feature is powered by [@vuepress/plugin-copy-code](https://ecosystem.vuejs.press/zh/plugins/features/copy-code.html).
|
||||
|
||||
The code copying feature is enabled by default in the theme. It supports one-click copying of code displayed in articles.
|
||||
|
||||
By default, the theme adds a copy button to every code block. This button is only displayed on desktop.
|
||||
|
||||
When hovering over a code block, a copy button appears in the top-right corner.
|
||||
|
||||
## Configuration
|
||||
|
||||
Modify the behavior of code copying in the `.vuepress/config.ts` configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// copyCode: false // Disable code copying
|
||||
copyCode: {
|
||||
// ...More configurations
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### showInMobile
|
||||
|
||||
- **Type:** `boolean`
|
||||
- **Default:** `false`
|
||||
|
||||
Whether to show the copy button on mobile devices.
|
||||
|
||||
### ignoreSelector
|
||||
|
||||
- **Type:** `string | string[]`
|
||||
- **Default:** `[]`
|
||||
|
||||
CSS selector for elements within code blocks to be ignored during copying.
|
||||
|
||||
Example: `['.token.comment']` will ignore nodes with the class `.token.comment` in code blocks (this would ignore comments in prismjs).
|
||||
|
||||
### inlineSelector
|
||||
|
||||
- **Type:** `string | string[] | boolean`
|
||||
- **Default:** `false`
|
||||
|
||||
Whether to copy inline code content on double-click.
|
||||
|
||||
`boolean`: Whether to copy inline code content on double-click.
|
||||
|
||||
`string[] | string`: Selector indicating which inline code content should be copyable.
|
||||
|
||||
### transform <Badge type="tip" text="Composition API Only" />
|
||||
|
||||
- **Type:** `(preElement: HTMLPreElement) => void`
|
||||
- **Default:** `null`
|
||||
|
||||
A transformer function to modify the code block content within `<pre>` before copying. This option is only effective when using `useCopyCode()`.
|
||||
|
||||
## Composition API
|
||||
|
||||
The Composition API for this feature can be configured in `.vuepress/client.ts`:
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import { defineClientConfig } from '@vuepress/client'
|
||||
import { useCopyCode } from '@vuepress/plugin-copy-code/client'
|
||||
|
||||
export default defineClientConfig({
|
||||
setup() {
|
||||
useCopyCode({
|
||||
// ...
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Add copyright information when copying code:
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import { defineClientConfig } from '@vuepress/client'
|
||||
import { useCopyCode } from '@vuepress/plugin-copy-code/client'
|
||||
|
||||
export default defineClientConfig({
|
||||
setup() {
|
||||
useCopyCode({
|
||||
transform: (preElement) => {
|
||||
// Insert copyright information
|
||||
pre.innerHTML += `\n Copied by vuepress-theme-plume`
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
567
docs/en/guide/code/features.md
Normal file
567
docs/en/guide/code/features.md
Normal file
@ -0,0 +1,567 @@
|
||||
---
|
||||
title: Feature Support
|
||||
icon: majesticons:code-block-line
|
||||
createTime: 2025/10/08 10:41:28
|
||||
permalink: /en/guide/code/features/
|
||||
---
|
||||
|
||||
The theme provides additional features beyond basic code highlighting, enhancing the expressiveness of your code blocks.
|
||||
|
||||
## Code Block Title <Badge type="tip" text="1.0.0-rc.136 +" />
|
||||
|
||||
Add `title="xxxx"` after <code>\`\`\` [lang]</code> to add a title to the current code block.
|
||||
|
||||
**Input:**
|
||||
|
||||
````md {1}
|
||||
```json title="package.json"
|
||||
{
|
||||
"name": "vuepress-theme-plume"
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```json title="package.json"
|
||||
{
|
||||
"name": "vuepress-theme-plume"
|
||||
}
|
||||
```
|
||||
|
||||
## Line Numbers
|
||||
|
||||
Line numbers are displayed by default in the theme, controlled by `codeHighlighter.line-numbers`.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
lineNumbers: true, // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also control whether to display line numbers for the current code block using `:line-numbers` / `:no-line-numbers`.
|
||||
Additionally, you can customize the starting line number by adding `=` after `:line-numbers`,
|
||||
for example `:line-numbers=2` indicates that line numbers in the code block start from `2`.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```ts:line-numbers
|
||||
// Line numbers enabled
|
||||
const line2 = 'This is line 2'
|
||||
const line3 = 'This is line 3'
|
||||
```
|
||||
|
||||
```ts:no-line-numbers
|
||||
// Line numbers disabled
|
||||
const line3 = 'This is line 3'
|
||||
const line4 = 'This is line 4'
|
||||
```
|
||||
|
||||
```ts:line-numbers=2
|
||||
// Line numbers enabled, starting from 2
|
||||
const line3 = 'This is line 3'
|
||||
const line4 = 'This is line 4'
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```ts:line-numbers
|
||||
// Line numbers enabled
|
||||
const line2 = 'This is line 2'
|
||||
const line3 = 'This is line 3'
|
||||
```
|
||||
|
||||
```ts:no-line-numbers
|
||||
// Line numbers disabled
|
||||
const line3 = 'This is line 3'
|
||||
const line4 = 'This is line 4'
|
||||
```
|
||||
|
||||
```ts:line-numbers=2
|
||||
// Line numbers enabled, starting from 2
|
||||
const line3 = 'This is line 3'
|
||||
const line4 = 'This is line 4'
|
||||
```
|
||||
|
||||
## Line Highlighting in Code Blocks
|
||||
|
||||
Add `{xxxx}` immediately after `[lang]` to enable line highlighting, where `xxx` represents the line numbers to be highlighted.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js{4}
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Highlighted!'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js{4}
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Highlighted!'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In addition to single lines, you can specify multiple single lines, line ranges, or both:
|
||||
|
||||
- Line ranges: e.g., `{5-8}`, `{3-10}`, `{10-17}`
|
||||
- Multiple single lines: e.g., `{4,7,9}`
|
||||
- Mixed single lines and ranges: e.g., `{4,7-13,16,23-27,40}`
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js{1,4,6-8}
|
||||
export default { // Highlighted
|
||||
data () {
|
||||
return {
|
||||
msg: `Highlighted!
|
||||
This line isn't highlighted,
|
||||
but this and the next 2 are.`,
|
||||
motd: 'VitePress is awesome',
|
||||
lorem: 'ipsum'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js{1,4,6-8}
|
||||
export default { // Highlighted
|
||||
data () {
|
||||
return {
|
||||
msg: `Highlighted!
|
||||
This line isn't highlighted,
|
||||
but this and the next 2 are.`,
|
||||
motd: 'VitePress is awesome',
|
||||
lorem: 'ipsum'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also use the `// [!code highlight]` comment to enable line highlighting.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Highlighted!' // [\!code highlight]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
msg: 'Highlighted!' // [!code highlight]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Focus in Code Blocks
|
||||
|
||||
Adding the `// [!code focus]` comment on a specific line will focus it and blur the rest of the code.
|
||||
|
||||
Additionally, you can use `// [!code focus:<lines>]` to define the number of lines to focus.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
msg: 'Focused!' // [\!code focus]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
msg: 'Focused!' // [!code focus]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip Use the valid line comment syntax for the language in different code blocks
|
||||
For example, in bash code blocks, use `# [!code focus]`
|
||||
|
||||
````md
|
||||
```bash
|
||||
mkdir hello && cd hello # [\!code focus]
|
||||
pnpm install
|
||||
```
|
||||
````
|
||||
|
||||
```bash
|
||||
mkdir hello && cd hello # [!code focus]
|
||||
pnpm install
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Diff in Code Blocks
|
||||
|
||||
Adding `// [!code --]` or `// [!code ++]` comments to a line will create a diff for that line while preserving the code block's syntax highlighting.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
error: 'Removed', // [\!code --]
|
||||
warning: 'Added' // [\!code ++]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
error: 'Removed', // [!code --]
|
||||
warning: 'Added' // [!code ++]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip Use the valid line comment syntax for the language in different code blocks
|
||||
For example, in bash code blocks, use `# [!code ++]`
|
||||
|
||||
````md
|
||||
```bash
|
||||
mkdir hello && cd hello # [\!code ++]
|
||||
```
|
||||
````
|
||||
|
||||
```bash
|
||||
mkdir hello && cd hello # [!code ++]
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Highlight "Errors" and "Warnings"
|
||||
|
||||
Adding `// [!code warning]` or `// [!code error]` comments to a line will apply corresponding coloring to that line.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```js
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
error: 'Error', // [\!code error]
|
||||
warning: 'Warning' // [\!code warning]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```js
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
error: 'Error', // [!code error]
|
||||
warning: 'Warning' // [!code warning]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip Use the valid line comment syntax for the language in different code blocks
|
||||
For example, in bash code blocks, use `# [!code warning]`
|
||||
|
||||
````md
|
||||
```bash
|
||||
mkdir hello && cd hello # [\!code warning]
|
||||
```
|
||||
````
|
||||
|
||||
```bash
|
||||
mkdir hello && cd hello # [!code warning]
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Word Highlighting in Code Blocks
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```ts
|
||||
export function foo() { // [\!code word:Hello]
|
||||
const msg = 'Hello World'
|
||||
console.log(msg) // prints Hello World
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```ts
|
||||
export function foo() { // [!code word:Hello]
|
||||
const msg = 'Hello World'
|
||||
console.log(msg) // prints Hello World
|
||||
}
|
||||
```
|
||||
|
||||
You can also specify the number of occurrences to highlight, for example `[!code word:options:2]`
|
||||
will highlight only the first two occurrences of `options`.
|
||||
|
||||
**Input:**
|
||||
|
||||
````
|
||||
```ts
|
||||
// [\!code word:options:2]
|
||||
const options = { foo: 'bar' }
|
||||
options.foo = 'baz'
|
||||
console.log(options.foo) // This won't be highlighted
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```ts
|
||||
// [!code word:options:2]
|
||||
const options = { foo: 'bar' }
|
||||
options.foo = 'baz'
|
||||
console.log(options.foo) // This won't be highlighted
|
||||
```
|
||||
|
||||
:::tip Use the valid line comment syntax for the language in different code blocks
|
||||
For example, in bash code blocks, use `# [!code word:hello]`
|
||||
|
||||
````md
|
||||
```bash
|
||||
mkdir hello && cd hello # [\!code word:hello]
|
||||
```
|
||||
````
|
||||
|
||||
```bash
|
||||
mkdir hello && cd hello # [!code word:hello]
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Whitespace in Code Blocks
|
||||
|
||||
Render whitespace characters (tabs and spaces) as visible.
|
||||
|
||||
Add `:whitespace` after the code block.
|
||||
|
||||
<!-- @include: ../../../snippet/whitespace.snippet.md -->
|
||||
|
||||
You can also globally enable the `whitespace` feature in `codeHighlighter`:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
whitespace: true, // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
When globally enabled, you can use `:no-whitespace` to disable the `whitespace` feature for a specific code block.
|
||||
|
||||
## Collapsed Code Blocks
|
||||
|
||||
Sometimes code blocks can be very long, which can be cumbersome when reading other content and
|
||||
affect the reading experience. In such cases, you can collapse code blocks.
|
||||
|
||||
Add `:collapsed-lines` after the code block to collapse it, starting from line 15 by default.
|
||||
|
||||
**Input:**
|
||||
|
||||
````txt
|
||||
```css :collapsed-lines
|
||||
html {
|
||||
margin: 0;
|
||||
background: black;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
... more code
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```css :collapsed-lines
|
||||
html {
|
||||
margin: 0;
|
||||
background: black;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
/* the three main rows going down the page */
|
||||
|
||||
body > div {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
float: left;
|
||||
width: 25%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.blowup {
|
||||
display: block;
|
||||
position: absolute;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.darken {
|
||||
opacity: 0.4;
|
||||
}
|
||||
```
|
||||
|
||||
You can also specify the starting line for collapsing. `:collapsed-lines=10` indicates collapsing starts from the tenth line.
|
||||
|
||||
**Input:**
|
||||
|
||||
````txt
|
||||
```css :collapsed-lines=10
|
||||
html {
|
||||
margin: 0;
|
||||
background: black;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
... more code
|
||||
```
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
```css :collapsed-lines=10
|
||||
html {
|
||||
margin: 0;
|
||||
background: black;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
/* the three main rows going down the page */
|
||||
|
||||
body > div {
|
||||
height: 25%;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
float: left;
|
||||
width: 25%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.main {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.blowup {
|
||||
display: block;
|
||||
position: absolute;
|
||||
object-fit: contain;
|
||||
object-position: center;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.darken {
|
||||
opacity: 0.4;
|
||||
}
|
||||
```
|
||||
|
||||
You can also globally enable the `collapsed-lines` feature in `codeHighlighter`:
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
collapsedLines: true // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
When globally enabled, you can use `:no-collapsed-lines` to disable the `collapsed-lines` feature for a specific code block.
|
||||
43
docs/en/guide/code/import.md
Normal file
43
docs/en/guide/code/import.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Import Code
|
||||
icon: mdi:import
|
||||
createTime: 2025/10/08 10:39:22
|
||||
permalink: /en/guide/code/import/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Importing code allows you to include code from another file in your markdown file and have it highlighted.
|
||||
|
||||
It helps you reference code from other files in your articles, avoiding duplicate code writing.
|
||||
|
||||
## Syntax
|
||||
|
||||
You can use the following syntax to import code blocks from files:
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
@[code](../snippet/snippet-1.js)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
@[code](../../../snippet/snippet-1.js)
|
||||
|
||||
If you only want to import a specific portion of the file:
|
||||
|
||||
```md
|
||||
<!-- Import only lines 1 to 10 -->
|
||||
@[code{1-10}](../snippet/snippet-1.js)
|
||||
```
|
||||
|
||||
The code language is inferred from the file extension, but we recommend explicitly specifying it:
|
||||
|
||||
```md
|
||||
<!-- Specify code language -->
|
||||
@[code js](../snippet/snippet-1.js)
|
||||
|
||||
<!-- Line highlighting -->
|
||||
@[code js{2,4-5}](../foo.js)
|
||||
```
|
||||
94
docs/en/guide/code/intro.md
Normal file
94
docs/en/guide/code/intro.md
Normal file
@ -0,0 +1,94 @@
|
||||
---
|
||||
title: Introduction
|
||||
icon: ic:outline-code
|
||||
createTime: 2025/10/08 10:35:45
|
||||
permalink: /en/guide/code/intro/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme uses [Shiki](https://shiki.style/) to implement syntax highlighting in Markdown code blocks.
|
||||
|
||||
::: important Important Changes <Badge type="danger" text="1.0.0-rc.136" />
|
||||
|
||||
Starting from version ==1.0.0-rc.136==, the theme has migrated the code highlighting plugin from the
|
||||
internally implemented `@vuepress-plume/plugin-shikiji` to
|
||||
[@vuepress/plugin-shiki](https://ecosystem.vuejs.press/zh/plugins/markdown/shiki.html)
|
||||
provided by the [vuepress ecosystem](https://github.com/vuepress/ecosystem).
|
||||
|
||||
_(No need to worry about significant changes - I am also one of the main developers of_
|
||||
_`@vuepress/plugin-shiki`, which implements functionality consistent with the theme's original plugin.)_
|
||||
|
||||
Some configuration items require adjustments:
|
||||
|
||||
- The `languages` configuration has been changed to the `langs` option. You no longer need to manually
|
||||
add the languages you use; the plugin will automatically recognize and load language packages as needed.
|
||||
- The `themes` configuration has been changed to:
|
||||
- When using a single theme configuration, use the `theme` option to configure the code block theme
|
||||
- When using dual theme configuration, use the `themes` option to configure the code block themes.
|
||||
|
||||
:::
|
||||
|
||||
## Languages
|
||||
|
||||
[Shiki](https://shiki.style/) supports over 190+ languages.
|
||||
You can view the complete list of supported languages at [languages](https://shiki.style/languages).
|
||||
|
||||
You can use the following syntax to enable highlighting for code written in your chosen language:
|
||||
|
||||
````md
|
||||
``` [lang]
|
||||
<!-- Your code content -->
|
||||
```
|
||||
````
|
||||
|
||||
Where `[lang]` represents the programming language you are using.
|
||||
|
||||
Example:
|
||||
|
||||
````md
|
||||
// [!code word:js]
|
||||
``` js
|
||||
const a = 1
|
||||
console.log(a)
|
||||
```
|
||||
````
|
||||
|
||||
```js
|
||||
const a = 1
|
||||
console.log(a)
|
||||
```
|
||||
|
||||
## Highlighting Themes
|
||||
|
||||
[Shiki](https://shiki.style/) supports over 40+ highlighting themes.
|
||||
|
||||
You can find the complete list of supported themes at [Themes](https://shiki.style/themes) and
|
||||
customize the highlighting theme according to your preference.
|
||||
|
||||
Theme Plume's default configuration for code block themes:
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
themes: { light: 'vitesse-light', dark: 'vitesse-dark' }, // [!code highlight]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
The default configuration supports using the `vitesse-light`/`vitesse-dark` themes for light/dark modes respectively.
|
||||
|
||||
## Additional Features
|
||||
|
||||
Thanks to the powerful capabilities of [Shiki](https://shiki.style/), Theme Plume provides additional
|
||||
[feature support](./features.md) for code blocks, enhancing their expressive power.
|
||||
|
||||
Additionally, to facilitate better code demonstrations, Theme Plume provides syntax support for embedding
|
||||
[CodePen](../repl/codepen.md), [Js Fiddle](../repl/jsFiddle.md), [Code Sandbox](../repl/codeSandbox.md),
|
||||
and [Replit](../repl/replit.md), allowing you to easily embed code demonstrations.
|
||||
|
||||
## Examples
|
||||
|
||||
<!-- @include: ../../../snippet/code-block.snippet.md -->
|
||||
767
docs/en/guide/code/twoslash.md
Normal file
767
docs/en/guide/code/twoslash.md
Normal file
@ -0,0 +1,767 @@
|
||||
---
|
||||
title: Two Slash
|
||||
icon: material-symbols:experiment-outline
|
||||
createTime: 2025/10/08 11:46:49
|
||||
permalink: /en/guide/markdown/twoslash/
|
||||
outline: [2, 4]
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Adds support for [TypeScript TwoSlash](https://www.typescriptlang.org/dev/twoslash/) in code blocks. Provides inline type hints within code blocks.
|
||||
|
||||
This feature is powered by [shiki](https://shiki.style/) and [@shikijs/twoslash](https://shiki.style/packages/twoslash), and integrated in [@vuepress-plume/plugin-shikiji](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-shikiji).
|
||||
|
||||
::: important __twoslash__ is an advanced feature that requires proficiency in
|
||||
[TypeScript](https://www.typescriptlang.org/) and understanding of [twoslash syntax](https://twoslash.netlify.app/).
|
||||
:::
|
||||
|
||||
::: warning
|
||||
`twoslash` is a relatively time-consuming feature. Since it requires type compilation of code,
|
||||
if the code imports large packages, it can take considerable time.
|
||||
|
||||
Specifically, since VuePress pre-compiles all markdown files on startup, this directly affects VuePress startup time.
|
||||
If you include many `twoslash` code blocks, this may significantly increase VuePress startup time.
|
||||
|
||||
For example, without `twoslash`, VuePress startup time typically ranges from `300ms ~ 1000ms`.
|
||||
With `twoslash`, compiling a single `twoslash` code block may require an additional `500ms` or more.
|
||||
|
||||
However, don't worry about compilation time during markdown file hot updates.
|
||||
The theme optimizes code highlighting compilation time - even if a single markdown file contains
|
||||
multiple code blocks, the theme only compiles __modified code blocks__, so hot updates remain fast.
|
||||
:::
|
||||
|
||||
[twoslash](https://twoslash.netlify.app/) is a `JavaScript` and `TypeScript` markup language.
|
||||
You can write code examples that describe entire `JavaScript` projects.
|
||||
|
||||
`twoslash` treats __double-slash comments__ (`//`) as preprocessor directives for code examples.
|
||||
|
||||
`twoslash` uses the same compiler APIs as text editors to provide type-driven hover information, accurate errors, and type annotations.
|
||||
|
||||
## Feature Preview
|
||||
|
||||
Hover over __variables__ or __functions__ to see the effect:
|
||||
|
||||
```ts twoslash
|
||||
import { createHighlighter } from 'shiki'
|
||||
|
||||
const highlighter = await createHighlighter({ themes: ['nord'], langs: ['javascript'] })
|
||||
// ^?
|
||||
//
|
||||
|
||||
// @log: Custom log message
|
||||
const a = 1
|
||||
// @error: Custom error message
|
||||
const b = 1
|
||||
// @warn: Custom warning message
|
||||
const c = 1
|
||||
// @annotate: Custom annotation message
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Enabling the Feature
|
||||
|
||||
Before enabling this feature, you need to install the `@vuepress/shiki-twoslash` package:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i @vuepress/shiki-twoslash
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Enable the `twoslash` option in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
twoslash: true,
|
||||
},
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
::: important
|
||||
For most users, `twoslash` is not a necessary feature, and `twoslash`-related dependencies have large
|
||||
package sizes. Therefore, all `twoslash` implementations have been moved to `@vuepress/shiki-twoslash`,
|
||||
which effectively reduces the initial installation size of the theme.
|
||||
|
||||
You only need to install `@vuepress/shiki-twoslash` when you require the `twoslash` feature.
|
||||
:::
|
||||
|
||||
### Importing Type Files from `node_modules`
|
||||
|
||||
The main feature of __twoslash__ is type compilation of code blocks, which natively supports importing type files from your project's `node_modules`.
|
||||
|
||||
For example, if you need type hints for `express`, you need to install the `@types/express` dependency in your project:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i -D @types/express
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, you can use `express` types in code blocks as follows:
|
||||
|
||||
```` md
|
||||
```ts twoslash
|
||||
import express from 'express'
|
||||
|
||||
const app = express()
|
||||
```
|
||||
````
|
||||
|
||||
### Importing Local Type Files
|
||||
|
||||
For importing local type files, since it's difficult to determine the real path of code in code blocks
|
||||
during compilation, it's not intuitive to import type files via __relative paths__ in code blocks.
|
||||
|
||||
#### Reading Path Mappings from `tsconfig.json`
|
||||
|
||||
The theme supports reading path mappings from `compilerOptions.paths` in `tsconfig.json` at the project root to solve this issue.
|
||||
|
||||
Assume your project's `tsconfig.json` is configured as follows:
|
||||
|
||||
```json title="tsconfig.json"
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can directly use paths starting with `@/` in code blocks to import type files from the `src` directory:
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
import type { Foo } from '@/foo'
|
||||
|
||||
const foo: Foo = 1
|
||||
```
|
||||
````
|
||||
|
||||
#### Reading Path Mappings from `shiki.twoslash`
|
||||
|
||||
You can configure `compilerOptions` in `shiki.twoslash` to solve this issue:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import path from 'node:path'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
codeHighlighter: {
|
||||
twoslash: {
|
||||
compilerOptions: { // [!code hl:8]
|
||||
paths: {
|
||||
// Relative to working directory `process.cwd()`
|
||||
'@/*': ['./src/*'],
|
||||
// Using absolute paths
|
||||
'@@/*': [path.resolve(process.cwd(), './src/*')],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
You can directly use paths starting with `@/` in code blocks to import type files from the `src` directory:
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
import type { Foo } from '@/foo'
|
||||
|
||||
const foo: Foo = 1
|
||||
```
|
||||
````
|
||||
|
||||
::: important
|
||||
Using `plugins.shiki.twoslash.compilerOptions` allows more flexible configuration of type compilation.
|
||||
You can modify `baseUrl` and other configuration options here.
|
||||
|
||||
[Refer to CompilerOptions](https://www.typescriptlang.org/tsconfig/#compilerOptions)
|
||||
|
||||
Usually you only need to configure the `paths` option, keeping other options default unless you understand what you're configuring.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
::: warning `twoslash` only supports `typescript` and `vue` code blocks.
|
||||
:::
|
||||
|
||||
After enabling this feature, simply add the `twoslash` keyword after the code language declaration in your existing markdown code block syntax:
|
||||
|
||||
````md{1}
|
||||
```ts twoslash
|
||||
const a = 1
|
||||
```
|
||||
````
|
||||
|
||||
The theme only processes code blocks with the `twoslash` keyword.
|
||||
|
||||
## Syntax Reference
|
||||
|
||||
Complete syntax reference: [ts-twoslasher](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher) and [shikijs-twoslash](https://twoslash.netlify.app/)
|
||||
|
||||
`twoslash` treats __double slashes__ as preprocessor directives for code examples. Therefore, all annotations are added after `//`.
|
||||
|
||||
### Symbol Annotations
|
||||
|
||||
Common `twoslash` annotations:
|
||||
|
||||
#### `^?` {#extract-type}
|
||||
|
||||
Use `^?` to extract type information for specific identifiers on the code line above it.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
const hi = 'Hello'
|
||||
const msg = `${hi}, world`
|
||||
// ^?
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
const hi = 'Hello'
|
||||
const msg = `${hi}, world`
|
||||
// ^?
|
||||
//
|
||||
```
|
||||
|
||||
::: important The symbol `^` must correctly point to the variable whose type you want to highlight.
|
||||
:::
|
||||
|
||||
#### `^|` {#completions}
|
||||
|
||||
Use `^|` to extract autocompletion information at a specific position.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @noErrors
|
||||
console.e
|
||||
// ^|
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @noErrors
|
||||
console.e
|
||||
// ^|
|
||||
//
|
||||
```
|
||||
|
||||
::: important The symbol `^` must correctly point to the position where you want content prediction.
|
||||
:::
|
||||
|
||||
Twoslash requests TypeScript for autocompletion suggestions at the `^` position,
|
||||
then filters possible outputs based on letters after the `.`. Up to 5 inline results are displayed,
|
||||
and if a completion item is marked as deprecated, the output reflects this.
|
||||
|
||||
In this case, Twoslash requests completion suggestions for `console` from TypeScript,
|
||||
then filters for items starting with `e`. Note the `// @noErrors` compiler flag is set because `console.e`
|
||||
is a failing TypeScript code example, but we don't care about that.
|
||||
|
||||
#### `^^^` {#highlighting}
|
||||
|
||||
Use `^^^` to highlight specific ranges on the line above it.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
function add(a: number, b: number) {
|
||||
// ^^^
|
||||
return a + b
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
function add(a: number, b: number) {
|
||||
// ^^^
|
||||
return a + b
|
||||
}
|
||||
```
|
||||
|
||||
::: important Use consecutive `^` symbols to correctly point to the range you want to highlight.
|
||||
:::
|
||||
|
||||
### `@filename` {#import-files}
|
||||
|
||||
`@filename: <filename>` declares which file subsequent code will come from. You can import this file via `import` in other parts of the code.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @filename: sum.ts
|
||||
export function sum(a: number, b: number): number {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// @filename: ok.ts
|
||||
import { sum } from './sum'
|
||||
sum(1, 2)
|
||||
|
||||
// @filename: error.ts
|
||||
// @errors: 2345
|
||||
import { sum } from './sum'
|
||||
sum(4, 'woops')
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @filename: sum.ts
|
||||
export function sum(a: number, b: number): number {
|
||||
return a + b
|
||||
}
|
||||
|
||||
// @filename: ok.ts
|
||||
import { sum } from './sum'
|
||||
sum(1, 2)
|
||||
|
||||
// @filename: error.ts
|
||||
// @errors: 2345
|
||||
import { sum } from './sum'
|
||||
sum(4, 'woops')
|
||||
```
|
||||
|
||||
### Code Cutting
|
||||
|
||||
#### `---cut-before---` {#cut-before}
|
||||
|
||||
After TypeScript generates the project and extracts all editor information (like identifiers,
|
||||
queries, highlights, etc.), cutting operations adjust all offsets and line numbers to fit the smaller output.
|
||||
|
||||
Users see content below `// ---cut-before---`. The shorthand `// ---cut---` is also supported.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut---
|
||||
console.log(level)
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut---
|
||||
console.log(level)
|
||||
```
|
||||
|
||||
Show only a single file:
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @filename: a.ts
|
||||
export const helloWorld: string = 'Hi'
|
||||
// ---cut---
|
||||
// @filename: b.ts
|
||||
import { helloWorld } from './a'
|
||||
|
||||
console.log(helloWorld)
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @filename: a.ts
|
||||
export const helloWorld: string = 'Hi'
|
||||
// ---cut---
|
||||
// @filename: b.ts
|
||||
import { helloWorld } from './a'
|
||||
|
||||
console.log(helloWorld)
|
||||
```
|
||||
|
||||
Only the last two lines are displayed, but to TypeScript, this is a program with two files,
|
||||
and all IDE information is correctly connected between files. This is why `// @filename: [file]`
|
||||
is the only Twoslash command not removed, as it can be `---cut---` if irrelevant.
|
||||
|
||||
#### `---cut-after---` {#cut-after}
|
||||
|
||||
The sibling of `---cut-before---`, used to trim everything after the symbol:
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut-before---
|
||||
console.log(level)
|
||||
// ---cut-after---
|
||||
console.log('This is not shown')
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut-before---
|
||||
console.log(level)
|
||||
// ---cut-after---
|
||||
console.log('This is not shown')
|
||||
```
|
||||
|
||||
#### `---cut-start---` and `---cut-end---` {#cut-start-end}
|
||||
|
||||
You can also use the `---cut-start---` and `---cut-end---` pair to cut code segments between two symbols.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut-start---
|
||||
console.log(level) // This part is cut
|
||||
// ---cut-end---
|
||||
console.log('This is shown')
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
const level: string = 'Danger'
|
||||
// ---cut-start---
|
||||
console.log(level) // This part is cut
|
||||
// ---cut-end---
|
||||
console.log('This is shown')
|
||||
```
|
||||
|
||||
Multiple instances are supported to cut multiple sections, but symbols must appear in pairs.
|
||||
|
||||
### Custom Output Messages {id=twoslash-custom-message}
|
||||
|
||||
`@log`, `@error`, `@warn`, and `@annotate` output custom messages at different levels to users.
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @log: Custom log message
|
||||
const a = 1
|
||||
// @error: Custom error message
|
||||
const b = 1
|
||||
// @warn: Custom warning message
|
||||
const c = 1
|
||||
// @annotate: Custom annotation message
|
||||
```
|
||||
````
|
||||
|
||||
```ts twoslash
|
||||
// @log: Custom log message
|
||||
const a = 1
|
||||
// @error: Custom error message
|
||||
const b = 1
|
||||
// @warn: Custom warning message
|
||||
const c = 1
|
||||
// @annotate: Custom annotation message
|
||||
```
|
||||
|
||||
### Output Compiled Files
|
||||
|
||||
Running Twoslash code examples triggers full TypeScript compilation runs that create files in a virtual
|
||||
file system. You can replace code example content with results from running TypeScript on the project.
|
||||
|
||||
#### `@showEmit`
|
||||
|
||||
`// @showEmit` is the primary command to tell Twoslash you want to replace the code example output with the equivalent `.js` file.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @showEmit
|
||||
const level: string = 'Danger'
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @showEmit
|
||||
const level: string = 'Danger'
|
||||
```
|
||||
|
||||
The result shows the `.js` file corresponding to this `.ts` file. You can see TypeScript output removes `: string` and adds `export {}`.
|
||||
|
||||
#### `@showEmittedFile: [file]`
|
||||
|
||||
While `.js` files may be the most useful out of the box, TypeScript does emit other files (`.d.ts` and `.map`)
|
||||
when proper flags are enabled, and with multi-file code examples, you may need to tell Twoslash which file to
|
||||
display. For all these cases, you can also add `@showEmittedFile: [file]` to tell Twoslash which file you want to display.
|
||||
|
||||
__Display `.d.ts` file for TypeScript code example:__
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @declaration
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.d.ts
|
||||
export const hello = 'world'
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @declaration
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.d.ts
|
||||
export const hello = 'world'
|
||||
```
|
||||
|
||||
__Display `.map` file from JavaScript to TypeScript:__
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @sourceMap
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.js.map
|
||||
export const hello = 'world'
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @sourceMap
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.js.map
|
||||
export const hello = 'world'
|
||||
```
|
||||
|
||||
__Display `.map` for `.d.ts` files (mainly for project references):__
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @declaration
|
||||
// @declarationMap
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.d.ts.map
|
||||
export const hello: string = 'world'
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @declaration
|
||||
// @declarationMap
|
||||
// @showEmit
|
||||
// @showEmittedFile: index.d.ts.map
|
||||
export const hello: string = 'world'
|
||||
```
|
||||
|
||||
__Generate `.js` file for `b.ts`:__
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @showEmit
|
||||
// @showEmittedFile: b.js
|
||||
// @filename: a.ts
|
||||
export const helloWorld: string = 'Hi'
|
||||
|
||||
// @filename: b.ts
|
||||
import { helloWorld } from './a'
|
||||
console.log(helloWorld)
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @showEmit
|
||||
// @showEmittedFile: b.js
|
||||
// @filename: a.ts
|
||||
export const helloWorld: string = 'Hi'
|
||||
|
||||
// @filename: b.ts
|
||||
import { helloWorld } from './a'
|
||||
console.log(helloWorld)
|
||||
```
|
||||
|
||||
### `@errors`
|
||||
|
||||
`@errors: <error code>` shows how code produces errors:
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @errors: 2322 2588
|
||||
const str: string = 1
|
||||
str = 'Hello'
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @errors: 2322 2588
|
||||
const str: string = 1
|
||||
str = 'Hello'
|
||||
```
|
||||
|
||||
You need to declare corresponding TypeScript error codes after `@errors`. Separate multiple error codes with spaces.
|
||||
|
||||
::: note
|
||||
If you don't know which error code to add, try writing the code first and wait for compilation to fail.
|
||||
You should see relevant error information in the console, then find the corresponding error code in the
|
||||
error message's `description`. Then add the error code to `@errors`.
|
||||
|
||||
Don't worry about compilation failures terminating the process - the theme displays error information
|
||||
when compilation fails while outputting uncompiled code in the code block.
|
||||
:::
|
||||
|
||||
### `@noErrors`
|
||||
|
||||
Suppresses all errors in code. You can also provide error codes to suppress specific errors.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @noErrors
|
||||
const str: string = 1
|
||||
str = 'Hello'
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @noErrors
|
||||
const str: string = 1
|
||||
str = 'Hello'
|
||||
```
|
||||
|
||||
### `@noErrorsCutted`
|
||||
|
||||
Ignores errors occurring in cut code.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @noErrorsCutted
|
||||
const hello = 'world'
|
||||
// ---cut-after---
|
||||
hello = 'hi' // Should be an error but ignored because it's cut.
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @noErrorsCutted
|
||||
const hello = 'world'
|
||||
// ---cut-after---
|
||||
hello = 'hi' // Should be an error but ignored because it's cut.
|
||||
```
|
||||
|
||||
### `@noErrorValidation`
|
||||
|
||||
Disables error validation. Error messages will still render, but Twoslash won't throw errors from compile-time code.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @noErrorValidation
|
||||
const str: string = 1
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @noErrorValidation
|
||||
const str: string = 1
|
||||
```
|
||||
|
||||
### `@keepNotations`
|
||||
|
||||
Tells Twoslash not to remove any comments and keep original code unchanged. Nodes will contain position information of original code.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @keepNotations
|
||||
// @module: esnext
|
||||
// @errors: 2322
|
||||
const str: string = 1
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @keepNotations
|
||||
// @module: esnext
|
||||
// @errors: 2322
|
||||
const str: string = 1
|
||||
```
|
||||
|
||||
### Overriding Compiler Options
|
||||
|
||||
Use `// @name` and `// @name: value` comments to override TypeScript's
|
||||
[compiler options](https://www.typescriptlang.org/tsconfig#compilerOptions). These comments will be removed from output.
|
||||
|
||||
__Input:__
|
||||
|
||||
````md
|
||||
```ts twoslash
|
||||
// @noImplicitAny: false
|
||||
// @target: esnext
|
||||
// @lib: esnext
|
||||
// This should throw an error,
|
||||
// but since we disabled noImplicitAny, it won't.
|
||||
const fn = a => a + 1
|
||||
```
|
||||
````
|
||||
|
||||
__Output:__
|
||||
|
||||
```ts twoslash
|
||||
// @noImplicitAny: false
|
||||
// @target: esnext
|
||||
// @lib: esnext
|
||||
// This should throw an error,
|
||||
// but since we disabled noImplicitAny, it won't.
|
||||
const fn = a => a + 1
|
||||
```
|
||||
110
docs/en/guide/components/badge.md
Normal file
110
docs/en/guide/components/badge.md
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
title: Badge
|
||||
icon: iconamoon:badge-light
|
||||
createTime: 2025/10/08 22:45:50
|
||||
permalink: /en/guide/components/badge/
|
||||
---
|
||||
|
||||
## Overview <Badge type="tip" text="badge" />
|
||||
|
||||
Use the `<Badge>` component to display inline information such as status or labels.
|
||||
|
||||
Pass the content you want to display to the `text` prop of the `<Badge>` component.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="type" type="'info' | 'tip' | 'warning' | 'danger' | string" default="'tip'" optional
|
||||
Badge type. Different types use different color schemes. Custom types are supported.
|
||||
:::
|
||||
|
||||
::: field name="text" type="string" default="''" optional
|
||||
Badge text content.
|
||||
:::
|
||||
|
||||
::: field name="color" type="string" optional
|
||||
Custom badge text color.
|
||||
:::
|
||||
|
||||
::: field name="bgColor" type="string" optional
|
||||
Custom badge background color.
|
||||
:::
|
||||
|
||||
::: field name="borderColor" type="string" optional
|
||||
Custom badge border color.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
- VuePress - <Badge type="info" text="v2" />
|
||||
- VuePress - <Badge type="tip" text="v2" />
|
||||
- VuePress - <Badge type="warning" text="v2" />
|
||||
- VuePress - <Badge type="danger" text="v2" />
|
||||
- VuePress - <Badge text="v2" color="#8e5cd9" bg-color="rgba(159, 122, 234, 0.16)" />
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
- VuePress - <Badge type="info" text="v2" />
|
||||
- VuePress - <Badge type="tip" text="v2" />
|
||||
- VuePress - <Badge type="warning" text="v2" />
|
||||
- VuePress - <Badge type="danger" text="v2" />
|
||||
- VuePress - <Badge text="v2" color="#8e5cd9" bg-color="rgba(159, 122, 234, 0.16)" />
|
||||
|
||||
Using custom `type` enables richer visual presentations.
|
||||
|
||||
**Input:**
|
||||
|
||||
1. Add predefined styles in the theme's [custom style file](../custom/style.md.md):
|
||||
|
||||
```css
|
||||
/* Light theme */
|
||||
.vp-badge.important {
|
||||
color: #8e5cd9;
|
||||
background-color: rgba(159, 122, 234, 0.14);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Dark theme */
|
||||
[data-theme="dark"] .vp-badge.important {
|
||||
color: #8e5cd9;
|
||||
background-color: rgba(159, 122, 234, 0.16);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
'important' is a custom type
|
||||
*/
|
||||
```
|
||||
|
||||
2. Use the custom `type`:
|
||||
|
||||
```md :no-line-numbers
|
||||
VuePress - <Badge type="important" text="v2" />
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
VuePress - <Badge type="important" text="v2" />
|
||||
|
||||
<style>
|
||||
/* Light theme */
|
||||
.vp-badge.important {
|
||||
color: #8e5cd9;
|
||||
background-color: rgba(159, 122, 234, 0.14);
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Dark theme */
|
||||
[data-theme="dark"] .vp-badge.important {
|
||||
color: #8e5cd9;
|
||||
background-color: rgba(159, 122, 234, 0.16);
|
||||
border-color: transparent;
|
||||
}
|
||||
</style>
|
||||
69
docs/en/guide/components/card-grid.md
Normal file
69
docs/en/guide/components/card-grid.md
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Card Grid
|
||||
icon: vaadin:grid-h
|
||||
createTime: 2025/10/08 23:38:33
|
||||
permalink: /en/guide/components/card-grid/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `<CardGrid>` component is used when multiple cards need to be arranged. Cards are automatically arranged when sufficient space is available.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
::: field name="cols" type="number | { sm: number, md: number, lg: number }" default="2"
|
||||
|
||||
Number of columns for card arrangement.
|
||||
|
||||
The component automatically adjusts the number of columns based on screen width by default.
|
||||
Two columns are displayed when space permits, while a single column is shown on smaller screens.
|
||||
|
||||
The `cols` prop configures the number of columns. When a `number` is provided,
|
||||
all screen sizes display `number` columns. When `{ sm: number, md: number, lg: number }` is provided,
|
||||
the number of columns adjusts automatically based on screen width.
|
||||
|
||||
- `sm` : `< 768px`
|
||||
- `md` : `>= 768px < 960px`
|
||||
- `lg` : `>= 960px`
|
||||
|
||||
It is recommended that the provided `number` does not exceed `3`.
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<CardGrid>
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
<CardGrid>
|
||||
<LinkCard title="Card Title" href="/" />
|
||||
<LinkCard icon="twemoji:astonished-face" title="Card Title" href="/" />
|
||||
</CardGrid>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<CardGrid>
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
</CardGrid>
|
||||
|
||||
<CardGrid>
|
||||
<LinkCard title="Link Card" href="/" />
|
||||
<LinkCard icon="twemoji:astonished-face" title="Link Card" href="/" />
|
||||
</CardGrid>
|
||||
273
docs/en/guide/components/card-masonry.md
Normal file
273
docs/en/guide/components/card-masonry.md
Normal file
@ -0,0 +1,273 @@
|
||||
---
|
||||
title: Masonry Card
|
||||
icon: ri:layout-masonry-line
|
||||
createTime: 2025/10/08 17:17:06
|
||||
permalink: /en/guide/components/card-masonry/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Masonry Card is a versatile container component that automatically calculates the height of
|
||||
each **item** and arranges them in a masonry layout. Any content can be placed within `<CardMasonry>`.
|
||||
|
||||
::: details What is an item?
|
||||
|
||||
An item represents individual content such as an image, text, video, etc.
|
||||
|
||||
- In Markdown syntax, any content occupying its own line (with blank lines before and after) is considered an item.
|
||||
- In HTML structure, each direct child element of the container is considered an item.
|
||||
|
||||
:::
|
||||
|
||||
```md
|
||||
<CardMasonry>
|
||||
|
||||
<img src="..." alt="...">
|
||||
|
||||
<!-- More content -->
|
||||
|
||||
</CardMasonry>
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="cols" type="number | { sm: number, md: number, lg: number }" optional
|
||||
Number of columns.
|
||||
|
||||
The component automatically adjusts the number of columns based on screen width by default.
|
||||
Three columns are displayed when space permits, while two columns are shown on smaller screens.
|
||||
|
||||
The `cols` prop configures the number of columns. When a `number` is provided,
|
||||
all screen sizes display `number` columns. When `{ sm: number, md: number, lg: number }` is provided,
|
||||
the number of columns adjusts automatically based on screen width.
|
||||
|
||||
- `sm` : `< 640px`
|
||||
- `md` : `>= 640px < 960px`
|
||||
- `lg` : `>= 960px`
|
||||
:::
|
||||
|
||||
::: field name="gap" type="number" optional default="16"
|
||||
Gap between columns.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Markdown Syntax Support
|
||||
|
||||
In Markdown, the `::: card-masonry` container can be used instead of `<CardMasonry>`.
|
||||
|
||||
``` md
|
||||
::: card-masonry cols="3" gap="16" <!-- [!code hl]-->
|
||||
|
||||

|
||||
|
||||
<!-- More content -->
|
||||
|
||||
::: <!-- [!code hl]-->
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Image Masonry
|
||||
|
||||
Masonry layout is particularly suitable for displaying images. You can directly place `` within `::: card-masonry`.
|
||||
|
||||
**Input:**
|
||||
|
||||
``` md
|
||||
::: card-masonry
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
::: card-masonry
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
:::
|
||||
|
||||
### Card Masonry
|
||||
|
||||
Masonry layout is also suitable for displaying cards. You can place `::: card` containers within `::: card-masonry`.
|
||||
|
||||
**Input:**
|
||||
|
||||
``` md :collapsed-lines
|
||||
:::: card-masonry
|
||||
|
||||
::: card title="Card 1"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 2"
|
||||
Card content
|
||||
|
||||
Additional card content
|
||||
:::
|
||||
|
||||
::: card title="Card 3"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 4"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 5"
|
||||
Card content
|
||||
|
||||
Additional card content
|
||||
:::
|
||||
|
||||
::: card title="Card 6"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
:::: card-masonry
|
||||
|
||||
::: card title="Card 1"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 2"
|
||||
Card content
|
||||
|
||||
Additional card content
|
||||
:::
|
||||
|
||||
::: card title="Card 3"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 4"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::: card title="Card 5"
|
||||
Card content
|
||||
|
||||
Additional card content
|
||||
:::
|
||||
|
||||
::: card title="Card 6"
|
||||
Card content
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
### Code Block Masonry
|
||||
|
||||
**Input:**
|
||||
|
||||
````md :collapsed-lines
|
||||
:::card-masonry
|
||||
|
||||
```ts
|
||||
const a = 1
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "John"
|
||||
}
|
||||
```
|
||||
|
||||
```css
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello world</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```ts
|
||||
const a = 12
|
||||
const b = 1
|
||||
```
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
:::card-masonry
|
||||
|
||||
```ts
|
||||
const a = 1
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "John"
|
||||
}
|
||||
```
|
||||
|
||||
```css
|
||||
p {
|
||||
color: red;
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello world</h1>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```ts
|
||||
const a = 12
|
||||
const b = 1
|
||||
```
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
68
docs/en/guide/components/card.md
Normal file
68
docs/en/guide/components/card.md
Normal file
@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Card
|
||||
icon: solar:card-broken
|
||||
createTime: 2025/10/08 23:09:07
|
||||
permalink: /en/guide/components/card/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Use the `<Card>` component to display cards within a page.
|
||||
|
||||
Alternatively, the markdown [card container](../markdown/card.md) syntax can be used as a substitute for the `<Card>` component.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="title" type="string" default="''" optional
|
||||
Card title.
|
||||
:::
|
||||
|
||||
::: field name="icon" type="string | { svg: string }" default="''" optional
|
||||
Icon displayed to the left of the title. Supports all icons from iconify, or an image URL can be used.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Slots
|
||||
|
||||
| Name | Description |
|
||||
| ------- | -------------------- |
|
||||
| default | Card content. |
|
||||
| title | Custom title content.|
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<template #title>
|
||||
<p style="color: red">Card Title</p>
|
||||
</template>
|
||||
This is the card content.
|
||||
</Card>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<Card title="Card Title" icon="twemoji:astonished-face">
|
||||
This is the card content.
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<template #title>
|
||||
<p style="color: red;margin:0">Card Title</p>
|
||||
</template>
|
||||
This is the card content.
|
||||
</Card>
|
||||
|
||||
:::info
|
||||
Markdown syntax can also be used inside slots. However,
|
||||
please note that an empty line is required between the markdown syntax and the tags. Otherwise, it will be interpreted as plain text.
|
||||
:::
|
||||
32
docs/en/guide/components/home-box.md
Normal file
32
docs/en/guide/components/home-box.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Home Layout Container
|
||||
icon: tabler:container
|
||||
createTime: 2025/10/08 23:49:40
|
||||
permalink: /en/guide/components/home-box/
|
||||
---
|
||||
|
||||
## Home Layout Container
|
||||
|
||||
The `<HomeBox>` component provides a wrapper container for areas when customizing the homepage layout.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="type" type="string" default="''" optional
|
||||
Area type.
|
||||
:::
|
||||
|
||||
::: field name="full" type="boolean" default="false" optional
|
||||
Whether to enable fullscreen mode.
|
||||
:::
|
||||
|
||||
::: field name="background-image" type="string" default="''" optional
|
||||
Area background image.
|
||||
:::
|
||||
|
||||
::: field name="background-attachment" type="'fixed' | 'local'" default="'local'" optional
|
||||
Area background attachment method.
|
||||
:::
|
||||
|
||||
::::
|
||||
83
docs/en/guide/components/icon.md
Normal file
83
docs/en/guide/components/icon.md
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
title: Icon
|
||||
icon: grommet-icons:emoji
|
||||
createTime: 2025/10/08 22:58:39
|
||||
permalink: /en/guide/components/icon/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The `<Icon />` component loads icons from different icon libraries based on the `markdown.icon` configuration.
|
||||
|
||||
[The theme also provides markdown syntax support. Click to learn more](../markdown/icons.md){.read-more}
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: { // [!code ++:3]
|
||||
icon: { provider: 'iconify' } // Enabled by default
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```ts
|
||||
interface IconOptions {
|
||||
/**
|
||||
* Icon provider
|
||||
*/
|
||||
provider: 'iconify' | 'iconfont' | 'fontawesome'
|
||||
/**
|
||||
* Default icon prefix. Different providers have different default prefixes
|
||||
* - iconify - Default: `''`
|
||||
* - iconfont - Default: `iconfont icon-`
|
||||
* - fontawesome - Default: `fas`
|
||||
*/
|
||||
prefix?: string
|
||||
/**
|
||||
* Icon asset links
|
||||
*/
|
||||
assets?: IconAssetLink | IconAssetLink[]
|
||||
size?: string | number
|
||||
color?: string
|
||||
}
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="name" type="string" default="''" optional
|
||||
Icon name. When `markdown.icon.prefix` has a value, the prefix in `name` can be omitted.
|
||||
:::
|
||||
|
||||
::: field name="color" type="string" default="'currentcolor'" optional
|
||||
Icon color.
|
||||
:::
|
||||
|
||||
::: field name="size" type="string" default="'1em'" optional
|
||||
Icon size.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
- home - <Icon name="material-symbols:home" color="currentColor" size="1em" />
|
||||
- vscode - <Icon name="skill-icons:vscode-dark" size="2em" />
|
||||
- twitter - <Icon name="skill-icons:twitter" size="2em" />
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
- home - <Icon name="material-symbols:home" color="currentColor" size="1em" />
|
||||
- vscode - <Icon name="skill-icons:vscode-dark" size="2em" />
|
||||
- twitter - <Icon name="skill-icons:twitter" size="2em" />
|
||||
135
docs/en/guide/components/image-card.md
Normal file
135
docs/en/guide/components/image-card.md
Normal file
@ -0,0 +1,135 @@
|
||||
---
|
||||
title: Image Card
|
||||
icon: fa:photo
|
||||
createTime: 2025/10/08 23:35:51
|
||||
permalink: /en/guide/components/image-card/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Use the `<ImageCard>` component to display image cards on a page.
|
||||
|
||||
The Image Card differs from markdown's standard image insertion method by presenting more information
|
||||
related to the image, including title, description, author, link, etc.
|
||||
It is suitable for scenarios such as photography works, design works, promotional posters, and more.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="image" type="string" required
|
||||
The image URL. Local images must use an absolute path, i.e., a path starting with `/`, pointing to the `/public` directory.
|
||||
:::
|
||||
|
||||
::: field name="title" type="string" optional
|
||||
The image title.
|
||||
:::
|
||||
|
||||
::: field name="description" type="string" optional
|
||||
The image description.
|
||||
:::
|
||||
|
||||
::: field name="author" type="string" optional
|
||||
The image author.
|
||||
:::
|
||||
|
||||
::: field name="href" type="string" optional
|
||||
The link to navigate to when the image title is clicked.
|
||||
:::
|
||||
|
||||
::: field name="date" type="string | Date | number" optional
|
||||
The image creation date.
|
||||
:::
|
||||
|
||||
::: field name="width" type="string | number" optional
|
||||
The image width.
|
||||
:::
|
||||
|
||||
::: field name="center" type="boolean" optional
|
||||
Whether to center the image when its width is less than the screen width.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
description="The lighthouse in today's photo is located at Cabo de São Vicente in the Algarve region of southern Portugal. The Alfanzina Lighthouse, built in 1919, shines over the sea, helping vessels navigate the treacherous waters around the area. This lighthouse is a famous tourist attraction and also a symbol of the region's deep connection with the ocean. If you're fortunate enough to live near the lighthouse, this weekend is the perfect time to visit."
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
:description="`The lighthouse in today's photo is located at Cabo de São Vicente in the Algarve region of
|
||||
southern Portugal.The Alfanzina Lighthouse, built in 1919, shines over the sea, helping vessels navigate the
|
||||
treacherous waters around the area. This lighthouse is a famous tourist attraction and also a symbol of the
|
||||
region's deep connection with the ocean. If you're fortunate enough to live near the lighthouse, this weekend is the perfect time to visit.`"
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
|
||||
It can also be placed within a `<CardGrid>` component.
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<CardGrid>
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
description="..."
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
description="..."
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
</CardGrid>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<CardGrid>
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
:description="`The lighthouse in today's photo is located at Cabo de São Vicente in the Algarve region of
|
||||
southern Portugal.The Alfanzina Lighthouse, built in 1919, shines over the sea, helping vessels navigate the
|
||||
treacherous waters around the area. This lighthouse is a famous tourist attraction and also a symbol of the
|
||||
region's deep connection with the ocean. If you're fortunate enough to live near the lighthouse, this weekend is the perfect time to visit.`"
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
<ImageCard
|
||||
image="https://cn.bing.com/th?id=OHR.AlfanzinaLighthouse_ZH-CN9704515669_1920x1080.webp"
|
||||
title="Alfanzina Lighthouse, Algarve, Portugal"
|
||||
:description="`The lighthouse in today's photo is located at Cabo de São Vicente in the Algarve region of
|
||||
southern Portugal.The Alfanzina Lighthouse, built in 1919, shines over the sea, helping vessels navigate the
|
||||
treacherous waters around the area. This lighthouse is a famous tourist attraction and also a symbol of the
|
||||
region's deep connection with the ocean. If you're fortunate enough to live near the lighthouse, this weekend is the perfect time to visit.`"
|
||||
href="/"
|
||||
author="Andreas Kunz"
|
||||
date="2024/08/16"
|
||||
/>
|
||||
</CardGrid>
|
||||
|
||||
[View Photography Works Example](../../../../../blog/1.示例/照片类作品示例.md)
|
||||
105
docs/en/guide/components/link-card.md
Normal file
105
docs/en/guide/components/link-card.md
Normal file
@ -0,0 +1,105 @@
|
||||
---
|
||||
title: Link Card
|
||||
icon: solar:card-send-linear
|
||||
createTime: 2025/10/08 23:14:00
|
||||
permalink: /en/guide/components/link-card/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Use the `<LinkCard>` component to display link cards on pages.
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="title" type="string" default="''" optional
|
||||
Link card title.
|
||||
:::
|
||||
|
||||
::: field name="icon" type="string | { svg: string }" default="''" optional
|
||||
Icon displayed to the left of the title. Supports icons from providers configured in
|
||||
[markdown.icon](../features/icon.md), or image URLs can be used.
|
||||
:::
|
||||
|
||||
::: field name="href" type="string" default="''" optional
|
||||
Link card navigation URL.
|
||||
:::
|
||||
|
||||
::: field name="description" type="string" default="''" optional
|
||||
Link card description. It is recommended to use the component's default slot for description content.
|
||||
:::
|
||||
|
||||
::: field name="target" type="string" default="''" optional
|
||||
Link target behavior.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Slots
|
||||
|
||||
| Name | Description |
|
||||
|---------|----------------------|
|
||||
| default | Card detail content |
|
||||
| title | Custom title content |
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<LinkCard title="Title" href="/" description="Card content" />
|
||||
<LinkCard icon="twemoji:astonished-face" title="Title" href="/" />
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<LinkCard title="Title" href="/" description="Card content" />
|
||||
<LinkCard icon="twemoji:astonished-face" title="Title" href="/" />
|
||||
|
||||
Using component slots enables richer presentations.
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<LinkCard title="Title" href="/">
|
||||
|
||||
- Card content
|
||||
- Card content
|
||||
|
||||
</LinkCard>
|
||||
|
||||
<LinkCard href="/">
|
||||
<template #title>
|
||||
<span style="color: red" >Title</span>
|
||||
</template>
|
||||
|
||||
- Card content
|
||||
- Card content
|
||||
|
||||
</LinkCard>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<LinkCard title="Title" href="/">
|
||||
|
||||
- Card content
|
||||
- Card content
|
||||
|
||||
</LinkCard>
|
||||
|
||||
<LinkCard href="/">
|
||||
<template #title>
|
||||
<span style="color: red" >Title</span>
|
||||
</template>
|
||||
|
||||
- Card content
|
||||
- Card content
|
||||
|
||||
</LinkCard>
|
||||
|
||||
:::info
|
||||
Markdown syntax can also be used within slots, but note that there must be a blank line between the
|
||||
markdown syntax and the tags. Otherwise, it will be parsed as plain text.
|
||||
:::
|
||||
204
docs/en/guide/components/npm-badge.md
Normal file
204
docs/en/guide/components/npm-badge.md
Normal file
@ -0,0 +1,204 @@
|
||||
---
|
||||
title: Npm Badge
|
||||
icon: akar-icons:npm-fill
|
||||
createTime: 2025/10/08 22:07:23
|
||||
permalink: /en/guide/components/npm-badge/
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import NpmBadge from 'vuepress-theme-plume/features/NpmBadge.vue'
|
||||
import NpmBadgeGroup from 'vuepress-theme-plume/features/NpmBadgeGroup.vue'
|
||||
</script>
|
||||
|
||||
## Overview
|
||||
|
||||
The Npm Badge component is used to display npm package information and provide relevant links.
|
||||
|
||||
The badges are powered by <https://shields.io>.
|
||||
|
||||
## Usage
|
||||
|
||||
To use this component, you need to manually import the `NpmBadge` or `NpmBadgeGroup` components:
|
||||
|
||||
```md :no-line-numbers
|
||||
<!-- Import in markdown -->
|
||||
<script setup>
|
||||
import NpmBadge from 'vuepress-theme-plume/features/NpmBadge.vue'
|
||||
import NpmBadgeGroup from 'vuepress-theme-plume/features/NpmBadgeGroup.vue'
|
||||
</script>
|
||||
|
||||
<!-- After importing, you can use them in markdown -->
|
||||
<NpmBadge name="vuepress-theme-plume" type="dm" />
|
||||
|
||||
<!-- Display multiple npm badges side by side -->
|
||||
<NpmBadgeGroup name="vuepress-theme-plume" items="version,dm" />
|
||||
```
|
||||
|
||||
<NpmBadge name="vuepress-theme-plume" type="dm" />
|
||||
|
||||
<NpmBadgeGroup name="vuepress-theme-plume" items="version,dm" />
|
||||
|
||||
## `<NpmBadge />`
|
||||
|
||||
Single npm badge
|
||||
|
||||
### Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="name" type="string" optional
|
||||
npm package name. If empty, it will be obtained from `repo`
|
||||
:::
|
||||
|
||||
::: field name="repo" type="string"
|
||||
Package GitHub repository address in `owner/repo` format. Required when `name` is empty
|
||||
:::
|
||||
|
||||
::: field name="type" type="NpmBadgeType"
|
||||
Badge type
|
||||
:::
|
||||
|
||||
::: field name="theme" type="NpmBadgeTheme" optional default="'flat'"
|
||||
Badge theme
|
||||
:::
|
||||
|
||||
::: field name="label" type="string" optional
|
||||
Badge label
|
||||
:::
|
||||
|
||||
::: field name="color" type="string" optional default="'#32A9C3'"
|
||||
Badge color
|
||||
:::
|
||||
|
||||
::: field name="labelColor" type="string" optional default="'#1B3C4A'"
|
||||
Badge label color
|
||||
:::
|
||||
|
||||
::: field name="branch" type="string" optional default="'main'"
|
||||
Repository branch
|
||||
:::
|
||||
|
||||
::: field name="dir" type="string" optional
|
||||
Package directory in repository. Suitable for monorepo projects
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
### Types
|
||||
|
||||
```ts
|
||||
type NpmBadgeType
|
||||
// github
|
||||
= | 'source' // github source
|
||||
| 'stars' // github stars
|
||||
| 'forks' // github forks
|
||||
| 'license' // github license
|
||||
// npm
|
||||
| 'version' // npm version
|
||||
| 'dt' // alias d18m
|
||||
| 'd18m' // npm downloads last 18 months
|
||||
| 'dw' // npm downloads weekly
|
||||
| 'dm' // npm downloads monthly
|
||||
| 'dy' // npm downloads yearly
|
||||
|
||||
type NpmBadgeTheme = 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' | 'social'
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
- `<NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="source" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="source" />
|
||||
- `<NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="stars" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="stars" />
|
||||
- `<NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="forks" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="forks" />
|
||||
- `<NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="license" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="license" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="version" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="version" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="dt" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="dt" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="d18m" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="d18m" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="dy" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="dy" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="dm" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="dm" />
|
||||
- `<NpmBadge name="vuepress-theme-plume" type="dw" />` - <NpmBadge repo="pengzhanbo/vuepress-theme-plume" type="dw" />
|
||||
|
||||
## `<NpmBadgeGroup />`
|
||||
|
||||
Combines multiple npm badges
|
||||
|
||||
### Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="name" type="string" optional
|
||||
npm package name. If empty, it will be obtained from `repo`
|
||||
:::
|
||||
|
||||
::: field name="repo" type="string"
|
||||
Package GitHub repository address in `owner/repo` format. Required when `name` is empty
|
||||
:::
|
||||
|
||||
::: field name="items" type="string | NpmBadgeType[]" optional default="[]"
|
||||
List of badge types. When passing a `string`, separate with `','` and it will be automatically converted to `NpmBadgeType[]`
|
||||
:::
|
||||
|
||||
::: field name="theme" type="NpmBadgeTheme" optional
|
||||
Badge theme
|
||||
:::
|
||||
|
||||
::: field name="color" type="string" optional
|
||||
Badge color
|
||||
:::
|
||||
|
||||
::: field name="labelColor" type="string" optional
|
||||
Badge label color
|
||||
:::
|
||||
|
||||
::: field name="branch" type="string" optional
|
||||
Repository branch
|
||||
:::
|
||||
|
||||
::: field name="dir" type="string" optional
|
||||
Package directory in repository. Suitable for monorepo projects
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
### Slots
|
||||
|
||||
`<NpmBadgeGroup />` supports passing multiple `<NpmBadge />` components.
|
||||
|
||||
The `Props` declared in `<NpmBadgeGroup />` will be injected into the `<NpmBadge />` components.
|
||||
This approach is used to implement and simplify badge combinations.
|
||||
|
||||
### Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<NpmBadgeGroup
|
||||
repo="pengzhanbo/vuepress-theme-plume"
|
||||
items="stars,version,dm,source"
|
||||
/>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<NpmBadgeGroup repo="pengzhanbo/vuepress-theme-plume" items="stars,version,dm,source" />
|
||||
|
||||
Use `<slot />` to flexibly define badge combinations:
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
<NpmBadgeGroup repo="pengzhanbo/vuepress-theme-plume">
|
||||
<NpmBadge type="stars" />
|
||||
<NpmBadge type="version" label="npm" />
|
||||
<NpmBadge type="dm" />
|
||||
<NpmBadge type="source" />
|
||||
</NpmBadgeGroup>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<NpmBadgeGroup repo="pengzhanbo/vuepress-theme-plume">
|
||||
<NpmBadge type="stars" />
|
||||
<NpmBadge type="version" label="npm" />
|
||||
<NpmBadge type="dm" />
|
||||
<NpmBadge type="source" />
|
||||
</NpmBadgeGroup>
|
||||
50
docs/en/guide/components/plot.md
Normal file
50
docs/en/guide/components/plot.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Plot Text
|
||||
icon: lets-icons:hide-eye
|
||||
createTime: 2025/10/08 23:02:39
|
||||
permalink: /en/guide/components/plot/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Use the `<Plot>` component to display [plot text](../markdown/plot.md) with more flexible control over behavior.
|
||||
|
||||
This component is disabled by default and needs to be enabled in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
plot: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="trigger" type="'hover' | 'click'" default="'hover'" optional
|
||||
Trigger on mouse hover or click
|
||||
:::
|
||||
|
||||
::: field name="effect" type="'blur' | 'mask'" default="'mask'" optional
|
||||
Mask layer effect or text blur effect
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md :no-line-numbers
|
||||
- Hover - <Plot>Visible on hover</Plot>
|
||||
- Click - <Plot trigger="click">Visible on click</Plot>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
- Hover - <Plot>Visible on hover</Plot>
|
||||
- Click - <Plot trigger="click">Visible on click</Plot>
|
||||
120
docs/en/guide/components/repo-card.md
Normal file
120
docs/en/guide/components/repo-card.md
Normal file
@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Repo Card
|
||||
icon: octicon:repo-16
|
||||
createTime: 2025/10/08 21:11:56
|
||||
permalink: /en/guide/components/github-repo-card/
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
|
||||
</script>
|
||||
|
||||
## Overview
|
||||
|
||||
The Repo Card component is used to display GitHub/Gitee repository information.
|
||||
|
||||
## Usage
|
||||
|
||||
To use this component, you need to manually import the `RepoCard` component:
|
||||
|
||||
```md :no-line-numbers
|
||||
<!-- Import in markdown -->
|
||||
<script setup>
|
||||
import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
|
||||
</script>
|
||||
|
||||
<!-- After importing, you can use it in markdown -->
|
||||
<RepoCard repo="pengzhanbo/vuepress-theme-plume" />
|
||||
```
|
||||
|
||||
Register as a global component:
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app }) {
|
||||
app.component('RepoCard', RepoCard)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Global components can be used in any other markdown file:
|
||||
|
||||
```md
|
||||
<RepoCard repo="pengzhanbo/vuepress-theme-plume" />
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
:::: field-group
|
||||
|
||||
::: field name="repo" type="string" required
|
||||
Repository address in `owner/repo` format
|
||||
:::
|
||||
|
||||
::: field name="provider" type="github | gitee" optional default="'github'"
|
||||
Repository platform. Currently only `github`/`gitee` are supported.
|
||||
:::
|
||||
|
||||
::: field name="fullname" type="boolean" optional
|
||||
Whether to display the full repository name.
|
||||
|
||||
The full repository name is `owner/repo`.
|
||||
|
||||
- If the owner is an individual, the full repository name is not displayed by default, only `repo` is shown.
|
||||
- If the owner is an organization, the full repository name is displayed by default.
|
||||
:::
|
||||
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
### Single Card
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
<RepoCard repo="pengzhanbo/vuepress-theme-plume" />
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<RepoCard repo="pengzhanbo/vuepress-theme-plume" />
|
||||
|
||||
### Multiple Cards
|
||||
|
||||
If you want to display multiple cards side by side in a compact way, you can use the `CardGrid` component.
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
<CardGrid>
|
||||
<RepoCard repo="vuepress/core" />
|
||||
<RepoCard repo="vuepress/ecosystem" />
|
||||
</CardGrid>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<CardGrid>
|
||||
<RepoCard repo="vuepress/core" />
|
||||
<RepoCard repo="vuepress/ecosystem" />
|
||||
</CardGrid>
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
<CardGrid>
|
||||
<RepoCard repo="pengzb/vuepress-theme-plume" provider="gitee" />
|
||||
<RepoCard repo="pengzb/vite-plugin-mock-dev-server" provider="gitee" />
|
||||
</CardGrid>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<CardGrid>
|
||||
<RepoCard repo="pengzb/vuepress-theme-plume" provider="gitee" />
|
||||
<RepoCard repo="pengzb/vite-plugin-mock-dev-server" provider="gitee" />
|
||||
</CardGrid>
|
||||
290
docs/en/guide/components/swiper.md
Normal file
290
docs/en/guide/components/swiper.md
Normal file
@ -0,0 +1,290 @@
|
||||
---
|
||||
title: Swiper
|
||||
icon: dashicons:images-alt2
|
||||
createTime: 2025/10/08 22:00:22
|
||||
permalink: /en/guide/components/swiper/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Use the `<Swiper>` component to display image carousels on pages.
|
||||
|
||||
## Usage
|
||||
|
||||
To use this component, first manually install the `swiper` library:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm install swiper
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, manually import the `Swiper` component:
|
||||
|
||||
```md
|
||||
<!-- Import in markdown -->
|
||||
<script setup>
|
||||
import Swiper from 'vuepress-theme-plume/features/Swiper.vue'
|
||||
</script>
|
||||
|
||||
<!-- After importing, you can use it in markdown -->
|
||||
<Swiper :items="['img_link1', 'img_link2']" />
|
||||
```
|
||||
|
||||
Register as a global component:
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import Swiper from 'vuepress-theme-plume/features/Swiper.vue'
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app }) {
|
||||
app.component('Swiper', Swiper)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Global components can be used in any other markdown file:
|
||||
|
||||
```md
|
||||
<Swiper :items="['img_link1', 'img_link2']" />
|
||||
```
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import Swiper from 'vuepress-theme-plume/features/Swiper.vue'
|
||||
|
||||
const images = ref([])
|
||||
|
||||
async function fetchImage() {
|
||||
const res = await fetch('https://api.pengzhanbo.cn/wallpaper/bing/zh/').then((res) => res.json())
|
||||
images.value = res.map(item => ({
|
||||
name: item.title,
|
||||
link: item.url,
|
||||
}))
|
||||
}
|
||||
|
||||
if (!__VUEPRESS_SSR__) {
|
||||
fetchImage()
|
||||
}
|
||||
</script>
|
||||
|
||||
**Example:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" />
|
||||
|
||||
## Props
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| ----------------- | ---------------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------- |
|
||||
| items | `string \| { link: string; href?: string; alt?: string}[]` | `[]` | Image link array. When passing objects, `link` represents image URL, `href` represents navigation link, `alt` represents image description |
|
||||
| width | `number \| string` | `100%` | Carousel area width |
|
||||
| height | `number \| string` | `100%` | Carousel area height |
|
||||
| mode | `'banner' \| 'carousel' \| 'broadcast'` | `'banner'` | Carousel mode: `banner`: banner; `carousel`: carousel; `broadcast`: information display |
|
||||
| navigation | `boolean` | `true` | Whether to show navigation buttons |
|
||||
| effect | `'slide' \| 'fade' \| 'cube' \| 'coverflow' \| 'flip' \| 'cards' \| 'creative'` | `'slide'` | Carousel effect |
|
||||
| delay | `number` | `3000` | Carousel interval time. Only effective when `mode: 'banner'`. Unit: `ms` |
|
||||
| speed | `number` | `300` | Animation duration. Unit: `ms` |
|
||||
| loop | `boolean` | `true` | Whether to loop |
|
||||
| pauseOnMouseEnter | `boolean` | `false` | Whether to pause carousel on mouse hover |
|
||||
| swipe | `boolean` | `true` | Whether to enable gesture swiping |
|
||||
|
||||
For more props, refer to [Swiper Documentation](https://swiperjs.com/swiper-api#parameters)
|
||||
|
||||
## Reference Examples
|
||||
|
||||
### Preset Animation Effects
|
||||
|
||||
**cube:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="cube" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="cube" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**fade:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="fade" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="fade" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**coverflow:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="coverflow" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="coverflow" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**flip:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="flip" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="flip" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**cards:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="cards" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="cards" />
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Custom Animation Effects
|
||||
|
||||
**Example 1:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: [0, 0, -400] },
|
||||
next: { translate: ['100%', 0, 0] },
|
||||
}" />
|
||||
|
||||
::: details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: [0, 0, -400] },
|
||||
next: { translate: ['100%', 0, 0] },
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**Example 2:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: [0, 0, -800], rotate: [180, 0, 0] },
|
||||
next: { shadow: true, translate: [0, 0, -800], rotate: [-180, 0, 0] },
|
||||
}" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: [0, 0, -800], rotate: [180, 0, 0] },
|
||||
next: { shadow: true, translate: [0, 0, -800], rotate: [-180, 0, 0] },
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**Example 3:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: ['-125%', 0, -800], rotate: [0, 0, -90] },
|
||||
next: { shadow: true, translate: ['125%', 0, -800], rotate: [0, 0, 90] },
|
||||
}" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, translate: ['-125%', 0, -800], rotate: [0, 0, -90] },
|
||||
next: { shadow: true, translate: ['125%', 0, -800], rotate: [0, 0, 90] },
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
**Example 4:**
|
||||
|
||||
<Swiper v-if="images.length" :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, origin: 'left center', translate: ['-5%', 0, -200], rotate: [0, 100, 0] },
|
||||
next: { origin: 'right center', translate: ['5%', 0, -200], rotate: [0, -100, 0] },
|
||||
}" />
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper :items="images" effect="creative" :creativeEffect="{
|
||||
prev: { shadow: true, origin: 'left center', translate: ['-5%', 0, -200], rotate: [0, 100, 0] },
|
||||
next: { origin: 'right center', translate: ['5%', 0, -200], rotate: [0, -100, 0] },
|
||||
}"
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Carousel
|
||||
|
||||
<Swiper
|
||||
v-if="images.length"
|
||||
:items="images"
|
||||
mode="carousel"
|
||||
:height="200"
|
||||
:slides-per-view="3"
|
||||
:space-between="20"
|
||||
:speed="5500"
|
||||
/>
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper
|
||||
:items="images"
|
||||
mode="carousel"
|
||||
:height="200"
|
||||
:slides-per-view="3"
|
||||
:space-between="20"
|
||||
:speed="5500"
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Information Display
|
||||
|
||||
<Swiper
|
||||
v-if="images.length"
|
||||
:items="images"
|
||||
mode="broadcast"
|
||||
:height="200"
|
||||
:slides-per-view="3"
|
||||
:space-between="20"
|
||||
mousewheel
|
||||
/>
|
||||
|
||||
:::details View Code
|
||||
|
||||
```md
|
||||
<Swiper
|
||||
:items="images"
|
||||
mode="broadcast"
|
||||
:height="200"
|
||||
:slides-per-view="3"
|
||||
:space-between="20"
|
||||
mousewheel
|
||||
/>
|
||||
```
|
||||
|
||||
:::
|
||||
46
docs/en/guide/custom/component-overrides.md
Normal file
46
docs/en/guide/custom/component-overrides.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
title: Component Overrides
|
||||
icon: carbon:cics-sit-overrides
|
||||
createTime: 2025/10/08 16:20:15
|
||||
permalink: /en/guide/component-overrides/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Layout slots are quite practical, but sometimes you might find them not flexible enough.
|
||||
The theme also provides the capability to override individual components.
|
||||
|
||||
::: warning
|
||||
Before using this feature, you should first familiarize yourself with this theme's source code
|
||||
and understand the various built-in components to safely override them.
|
||||
|
||||
The theme's component source code is hosted on
|
||||
[GitHub](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/theme/src/client/components) under the MIT license.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
The theme registers all non-global components with an
|
||||
[alias](https://v2.vuepress.vuejs.org/zh/reference/plugin-api.html#alias) prefixed with `@theme`.
|
||||
For example, the alias for `VPFooter.vue` is `@theme/VPFooter.vue`.
|
||||
|
||||
If you want to override the `VPFooter.vue` component, you simply need to override this alias in the configuration file `.vuepress/config.ts`:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
import { getDirname, path } from 'vuepress/utils'
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme(),
|
||||
|
||||
alias: {
|
||||
'@theme/VPFooter.vue': path.resolve(
|
||||
__dirname,
|
||||
'./components/MyFooter.vue',
|
||||
),
|
||||
},
|
||||
})
|
||||
```
|
||||
@ -1,8 +1,698 @@
|
||||
---
|
||||
title: Customize Homepage
|
||||
title: Custom Homepage
|
||||
icon: material-symbols:home-outline
|
||||
createTime: 2025/03/04 12:40:11
|
||||
createTime: 2025/10/08 10:44:03
|
||||
permalink: /en/guide/custom-home/
|
||||
---
|
||||
|
||||
todo ...
|
||||
## Overview
|
||||
|
||||
The theme provides a highly flexible approach to customizing the homepage. You can tailor your homepage according to your specific requirements.
|
||||
|
||||
The theme defines your homepage through `frontmatter`. Write the `frontmatter` in the `README.md` file located in your `sourceDir`.
|
||||
|
||||
```md title="README.md"
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
- type: custom
|
||||
---
|
||||
```
|
||||
|
||||
The theme follows a flow layout approach to render the homepage, dividing it vertically into distinct,
|
||||
independent sections, with each section applying a different component.
|
||||
|
||||
Multiple sections can be defined via the `config` property using an array structure. The `type` field specifies the type of each section.
|
||||
The theme includes built-in types such as `banner`, `hero`, `text-image`, `image-text`, `features`, `profile`, and `custom`.
|
||||
You can freely combine these to assemble your custom homepage.
|
||||
If none of these meet your needs, you can also write custom components to define your homepage.
|
||||
|
||||
## Configuration
|
||||
|
||||
### home
|
||||
|
||||
- Type: `boolean`
|
||||
|
||||
Declares whether this page is the homepage.
|
||||
|
||||
### config
|
||||
|
||||
- Type: `PlumeHomeConfig[]`
|
||||
- Default: `[]`
|
||||
|
||||
Defines the section content of the page based on the order of the array.
|
||||
|
||||
```ts
|
||||
interface PlumeHomeConfigBase {
|
||||
/**
|
||||
* The type of this section, which determines the component applied.
|
||||
*/
|
||||
type: 'banner' | 'hero' | 'text-image' | 'image-text' | 'features' | 'profile' | 'custom' | string
|
||||
/**
|
||||
* Whether this section should occupy the full viewport height.
|
||||
*/
|
||||
full?: boolean
|
||||
/**
|
||||
* The background image for this section.
|
||||
* You can define different images for light and dark modes.
|
||||
*/
|
||||
backgroundImage?: string | { light: string, dark: string }
|
||||
/**
|
||||
* The background attachment style for this section.
|
||||
*/
|
||||
backgroundAttachment?: 'fixed' | 'local'
|
||||
}
|
||||
```
|
||||
|
||||
## Section Types
|
||||
|
||||
### banner
|
||||
|
||||
- Type: `PlumeThemeHomeBanner`
|
||||
|
||||
A large banner section, suitable for placement at the very top of the homepage.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeBanner extends PlumeHomeConfigBase {
|
||||
type: 'banner'
|
||||
/**
|
||||
* The large background banner image.
|
||||
*/
|
||||
banner?: string
|
||||
/**
|
||||
* Value range: 0 - 1. Configures the opacity of the mask overlay for the homepage banner image.
|
||||
* Supports different values for light and dark modes. When set to 0, the mask is not displayed.
|
||||
* This can be used to darken the image if the first-screen banner is too bright.
|
||||
*/
|
||||
bannerMask?: number | { light?: number, dark?: number }
|
||||
|
||||
hero?: {
|
||||
name: string
|
||||
tagline?: string
|
||||
text?: string
|
||||
actions?: {
|
||||
theme?: 'brand' | 'alt'
|
||||
text: string
|
||||
link?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: banner
|
||||
banner: https://api.pengzhanbo.cn/wallpaper/bing
|
||||
bannerMask:
|
||||
light: 0.1
|
||||
dark: 0.3
|
||||
hero:
|
||||
name: Peng Zhanbo
|
||||
tagline: Front End Developer
|
||||
text: Even if slow, stop not, even if failed, keep going, but must be able to reach the goal he aims for.
|
||||
actions:
|
||||
-
|
||||
text: My Blog
|
||||
link: /blog/
|
||||
theme: brand
|
||||
-
|
||||
text: Github
|
||||
link: https://github.com/pengzhanbo
|
||||
theme: alt
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
|
||||

|
||||
:::
|
||||
|
||||
### hero
|
||||
|
||||
- Type: `PlumeThemeHomeHero`
|
||||
|
||||
Suitable for documentation-type sites, placed at the top.
|
||||
|
||||
**Tool Support: [Homepage Hero Tint Plate Configuration Tool](../../tools/home-hero-tint-plate.md)**
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeHero extends PlumeHomeConfigBase {
|
||||
type: 'hero'
|
||||
hero: {
|
||||
name: string
|
||||
tagline?: string
|
||||
text?: string
|
||||
actions?: {
|
||||
theme?: 'brand' | 'alt' | 'sponsor'
|
||||
text: string
|
||||
link?: string
|
||||
icon?: string // Icon to the left of the text
|
||||
suffixIcon?: string // Icon to the right of the text
|
||||
target?: '_blank' | '_self' | string
|
||||
rel?: string
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Background image. "tint-plate" is a preset effect, or a custom image URL can be provided.
|
||||
*/
|
||||
background?: 'tint-plate' | string
|
||||
|
||||
/**
|
||||
* When background is the preset, configure RGB values to adjust the background color.
|
||||
* This configuration only takes effect when `background` is set to `tint-plate`.
|
||||
*/
|
||||
tintPlate?: TintPlate
|
||||
/**
|
||||
* If using a non-preset background, set the filter effect for the background image.
|
||||
*/
|
||||
filter?: string
|
||||
}
|
||||
interface TintPlateObj {
|
||||
// value represents the base color value, range 0 ~ 255
|
||||
// offset represents the offset from the base value, range 0 ~ (255 - value)
|
||||
r: { value: number, offset: number }
|
||||
g: { value: number, offset: number }
|
||||
b: { value: number, offset: number }
|
||||
}
|
||||
type TintPlate
|
||||
= | number // e.g., 210
|
||||
| string // e.g., '210,210,210' => red,green,blue
|
||||
// e.g., { r: { value: 220, offset: 36 }, g: { value: 220, offset: 36 }, b: { value: 220, offset: 36 } }
|
||||
| TintPlateObj
|
||||
// e.g., { light: 210, dark: 20 }
|
||||
// e.g., { light: '210,210,210', dark: '20,20,20' }
|
||||
| { light: number | string, dark: number | string }
|
||||
| { light: TintPlateObj, dark: TintPlateObj }
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: hero
|
||||
full: true
|
||||
background: tint-plate
|
||||
hero:
|
||||
name: Theme Plume
|
||||
tagline: Vuepress Next Theme
|
||||
text: A minimalistic, feature-rich vuepress documentation & blog theme
|
||||
actions:
|
||||
-
|
||||
theme: brand
|
||||
text: Get Started →
|
||||
link: /
|
||||
-
|
||||
theme: alt
|
||||
text: Github
|
||||
link: https://github.com/pengzhanbo/vuepress-theme-plume
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-hero.jpg" alt="Theme Plume" />
|
||||
:::
|
||||
|
||||
When `background` is configured as `tint-plate`, you can additionally configure `tintPlate` to adjust
|
||||
the background hue, with a range of `0 ~ 255`:
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: hero
|
||||
full: true
|
||||
background: tint-plate
|
||||
tintPlate: 210
|
||||
---
|
||||
```
|
||||
|
||||
`tintPlate` is used to configure RGB values:
|
||||
|
||||
- When configured as a single number, it sets the red, green, and blue color channels to the same value (range: 0 - 255). Example: `210`.
|
||||
- When configured as three comma-separated values, it sets the red, green, and blue channels to different values (range: 0 - 255). Example: `210,210,210`.
|
||||
- When configured as a `TintPlateObj`, it allows more granular control over each color channel and its corresponding offset.
|
||||
- It can also be configured as `{ light, dark }` to use different color values in dark and light modes.
|
||||
|
||||
::: info
|
||||
To facilitate the configuration of aesthetically pleasing and personalized backgrounds,
|
||||
the theme also provides a [Homepage Hero Tint Plate Configuration Tool](../../tools/custom-theme.md)
|
||||
for visual configuration. You can generate configuration content and copy it directly for use in your own project.
|
||||
:::
|
||||
|
||||
The theme also supports customizing the colors of `name`, `tagline`, and `text`.
|
||||
|
||||
Configure this via CSS Variables.
|
||||
|
||||
```css
|
||||
/* Default settings, can be overridden in `index.css` */
|
||||
:root {
|
||||
/* home hero name background color. The text color is defined via background clipping,
|
||||
allowing gradient backgrounds for more expressive text. */
|
||||
--vp-bg-home-hero-name: linear-gradient(315deg, var(--vp-c-purple-1) 15%, var(--vp-c-brand-2) 65%, var(--vp-c-brand-2) 100%);
|
||||
--vp-c-home-hero-tagline: var(--vp-c-text-2);
|
||||
--vp-c-home-hero-text: var(--vp-c-text-3);
|
||||
}
|
||||
```
|
||||
|
||||
### doc-hero
|
||||
|
||||
- Type: `PlumeThemeHomeDocHero`
|
||||
|
||||
Suitable for documentation-type sites, placed at the top.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeDocHero {
|
||||
type: 'doc-hero'
|
||||
hero: {
|
||||
name: string
|
||||
tagline?: string
|
||||
text?: string
|
||||
image?: string
|
||||
| { src: string, alt?: string }
|
||||
| { dark: string, light: string, alt?: string }
|
||||
actions?: {
|
||||
theme?: 'brand' | 'alt' | 'sponsor'
|
||||
text: string
|
||||
link?: string
|
||||
icon?: string // Icon to the left of the text
|
||||
suffixIcon?: string // Icon to the right of the text
|
||||
target?: '_blank' | '_self' | string
|
||||
rel?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: doc-hero
|
||||
hero:
|
||||
name: Theme Plume
|
||||
text: VuePress Next Theme
|
||||
tagline: A minimalistic, easy-to-use, feature-rich vuepress documentation & blog theme
|
||||
image: /plume.png
|
||||
actions:
|
||||
-
|
||||
theme: brand
|
||||
text: Get Started →
|
||||
link: /guide/intro/
|
||||
-
|
||||
theme: alt
|
||||
text: Github
|
||||
link: https://github.com/pengzhanbo/vuepress-theme-plume
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-doc-hero.jpg" alt="Theme Plume" />
|
||||
:::
|
||||
|
||||
The theme also supports customizing the colors of `name`, `tagline`, `text`, and the background color of the `image`.
|
||||
|
||||
Configure this via CSS Variables.
|
||||
|
||||
```css
|
||||
/* Default settings, can be overridden in `index.css` */
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: linear-gradient(120deg, var(--vp-c-purple-1) 30%, var(--vp-c-brand-2));
|
||||
--vp-home-hero-tagline: var(--vp-c-text-2);
|
||||
--vp-home-hero-text: var(--vp-c-text-1);
|
||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-soft) 50%, var(--vp-c-brand-2) 50%);
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
}
|
||||
```
|
||||
|
||||
### features
|
||||
|
||||
- Type: `PlumeThemeHomeFeatures`
|
||||
|
||||
Suitable for displaying features, functionalities, etc.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeFeatures extends PlumeHomeConfigBase {
|
||||
type: 'features'
|
||||
title?: string
|
||||
description?: string
|
||||
features: PlumeThemeHomeFeature[]
|
||||
}
|
||||
|
||||
interface PlumeThemeHomeFeature {
|
||||
/**
|
||||
* Icon, also supports passing an iconify icon name.
|
||||
*/
|
||||
icon?: FeatureIcon
|
||||
title: string
|
||||
details?: string
|
||||
link?: string
|
||||
linkText?: string
|
||||
rel?: string
|
||||
target?: string
|
||||
}
|
||||
|
||||
type FeatureIcon = string | {
|
||||
src: string
|
||||
alt?: string
|
||||
width?: string
|
||||
height?: string
|
||||
wrap?: boolean
|
||||
} | {
|
||||
light: string
|
||||
dark: string
|
||||
alt?: string
|
||||
width?: string
|
||||
height?: string
|
||||
wrap?: boolean
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: features
|
||||
features:
|
||||
-
|
||||
title: Responsive Layout
|
||||
icon: 💻
|
||||
details: Adapts to mobile devices, PCs, and tablets.
|
||||
-
|
||||
title: Blog & Documentation
|
||||
icon: 📖
|
||||
details: Whether you want to write a blog, product documentation, or both.
|
||||
-
|
||||
title: Out of the Box
|
||||
icon: 🚀
|
||||
details: Supports zero-configuration usage, along with rich customization options.
|
||||
-
|
||||
title: Multi-language
|
||||
icon: ⚖
|
||||
details: Built-in support for Chinese/English, with the ability to add more languages.
|
||||
-
|
||||
title: Dual Theme
|
||||
icon: 👨💻
|
||||
details: Supports light/dark themes, including code highlighting.
|
||||
-
|
||||
title: Plugins
|
||||
icon: 📦
|
||||
details: Rich built-in plugins to handle common website needs in one place.
|
||||
-
|
||||
title: Search, Comments
|
||||
icon: 🔍
|
||||
details: Supports multiple comment systems, local search, and Algolia search.
|
||||
-
|
||||
title: Encryption
|
||||
icon: 🔒
|
||||
details: Supports full-site encryption, partial encryption (encrypted directories, encrypted articles).
|
||||
-
|
||||
title: Markdown Enhancements
|
||||
icon: 📝
|
||||
details: Supports Markdown syntax, code block groups, hint containers, task lists, mathematical formulas, code demos, etc.
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-features.jpg" alt="custom-features" />
|
||||
:::
|
||||
|
||||
### text-image | image-text
|
||||
|
||||
- Type: `PlumeThemeHomeTextImage`
|
||||
|
||||
Left-right layout for text and image.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
|
||||
type: 'text-image' | 'image-text'
|
||||
image: PlumeThemeImage
|
||||
width?: number | string
|
||||
title?: string
|
||||
description?: string
|
||||
list: (string | { title?: string, description?: string })[]
|
||||
}
|
||||
|
||||
type PlumeThemeImage
|
||||
= | string
|
||||
| { src: string, alt?: string }
|
||||
| { dark: string, light: string, alt?: string }
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: image-text
|
||||
title: Features
|
||||
description: Rich built-in features to meet general website requirements.
|
||||
image: /images/plume-1.svg
|
||||
list:
|
||||
-
|
||||
title: Article Information
|
||||
description: Add tags, categories, word count, reading time, writing date, and other information to articles.
|
||||
-
|
||||
title: Comments
|
||||
description: Support for 4 comment systems, allowing you to freely choose the one that fits your needs.
|
||||
-
|
||||
title: Search
|
||||
description: Supports minisearch-based local search and Algolia search.
|
||||
-
|
||||
title: Encryption
|
||||
description: Supports full-site encryption and partial encryption (encrypted directories, encrypted articles).
|
||||
-
|
||||
title: Code Copy
|
||||
description: One-click copying of code block content.
|
||||
-
|
||||
type: text-image
|
||||
title: Blog
|
||||
description: The theme natively supports blogging, generating your personal blog.
|
||||
image: /images/plume-2.svg
|
||||
list:
|
||||
-
|
||||
title: Article List
|
||||
description: Automatically sorts and generates blog article list pages based on writing dates.
|
||||
-
|
||||
title: Author Information
|
||||
description: Customize name, motto, avatar, and social media links.
|
||||
-
|
||||
title: Tags, Archive
|
||||
description: Automatically generates tag pages and archives articles by year.
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-image-text.jpg" alt="image-text" />
|
||||
:::
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-text-image.jpg" alt="text-image" />
|
||||
:::
|
||||
|
||||
### posts
|
||||
|
||||
Inserts a post collection article list page as a separate section into the homepage.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomePosts extends PlumeHomeConfigBase {
|
||||
type: 'posts'
|
||||
collection?: string
|
||||
}
|
||||
```
|
||||
|
||||
When multiple post collections exist, it reads the article list from the first collection by default.
|
||||
You can specify which collection's article list to read using the `collection` configuration option.
|
||||
|
||||
The value of `collection` should match the `dir` value of the collection.
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: posts
|
||||
collection: blog
|
||||
---
|
||||
```
|
||||
|
||||
### profile
|
||||
|
||||
- Type: `PlumeThemeHomeProfile`
|
||||
|
||||
Displays personal information.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeProfile extends PlumeHomeConfigBase {
|
||||
type: 'profile'
|
||||
name?: string
|
||||
description?: string
|
||||
avatar?: PlumeThemeImage
|
||||
circle?: boolean
|
||||
}
|
||||
|
||||
type PlumeThemeImage
|
||||
= | string
|
||||
| { src: string, alt?: string }
|
||||
| { dark: string, light: string, alt?: string }
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: profile
|
||||
name: pengzhanbo
|
||||
description: Even if slow, stop not, even if failed, keep going, but must be able to reach the goal he aims for.
|
||||
avatar: /images/avatar.png
|
||||
---
|
||||
```
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-profile.jpg" alt="profile" />
|
||||
:::
|
||||
|
||||
### custom
|
||||
|
||||
- Type: `PlumeThemeHomeCustom`
|
||||
|
||||
Custom content. The markdown content written in the `README.md` file will be inserted into the corresponding section.
|
||||
|
||||
```ts
|
||||
interface PlumeThemeHomeCustom extends PlumeHomeConfigBase {
|
||||
type: 'custom'
|
||||
}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
````md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: custom
|
||||
---
|
||||
|
||||
### Installation
|
||||
|
||||
:::code-tabs
|
||||
@tab pnpm
|
||||
```sh
|
||||
pnpm add vuepress@next vuepress-theme-plume vue
|
||||
```
|
||||
@tab npm
|
||||
```sh
|
||||
npm install vuepress@next vuepress-theme-plume
|
||||
```
|
||||
@tab yarn
|
||||
```sh
|
||||
yarn add vuepress@next vuepress-theme-plume
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
**Result:**
|
||||
|
||||
:::demo-wrapper img no-padding
|
||||
<img src="/images/custom-content.jpg" alt="content" />
|
||||
:::
|
||||
|
||||
## Custom Section Types
|
||||
|
||||
When the built-in section types are insufficient for your needs, you can create custom section types.
|
||||
|
||||
Each custom section type is essentially a component.
|
||||
|
||||
A simple example is as follows:
|
||||
|
||||
::: code-tabs
|
||||
@tab your-component.vue
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { ThemeHomeConfigBase } from 'vuepress-theme-plume'
|
||||
import { VPHomeBox } from 'vuepress-theme-plume/client'
|
||||
|
||||
const props = defineProps<ThemeHomeConfigBase & {
|
||||
// Component props, properties from frontmatter will be passed to the component
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPHomeBox
|
||||
:type="type"
|
||||
:background-image="backgroundImage"
|
||||
:background-attachment="backgroundAttachment"
|
||||
:full="full"
|
||||
>
|
||||
<!-- Customize your content -->
|
||||
<div>...</div>
|
||||
</VPHomeBox>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Add the component in the `enhance` hook within `.vuepress/client.ts`
|
||||
::: code-tabs
|
||||
@tab .vuepress/client.ts
|
||||
|
||||
```ts
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
import YourComponent from 'your-component.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app }) {
|
||||
app.component('your-component', YourComponent)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Then, you can use `your-component` in your `README.md`.
|
||||
|
||||
```md
|
||||
---
|
||||
home: true
|
||||
config:
|
||||
-
|
||||
type: 'your-component'
|
||||
# ...
|
||||
---
|
||||
```
|
||||
|
||||
179
docs/en/guide/custom/slots.md
Normal file
179
docs/en/guide/custom/slots.md
Normal file
@ -0,0 +1,179 @@
|
||||
---
|
||||
title: Layout Slots
|
||||
icon: ph:layout-duotone
|
||||
createTime: 2025/10/08 16:19:43
|
||||
permalink: /en/guide/layout-slots/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme provides extensive layout slots through `<Layout />` and `<NotFound />` components,
|
||||
allowing content injection at different positions of the page. This enables users to personalize the theme according to their needs.
|
||||
|
||||
## Usage
|
||||
|
||||
Taking `<Layout />` as an example, first create a client configuration file: `.vuepress/client.ts`:
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
import Layout from './layouts/Layout.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
layouts: {
|
||||
Layout,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
::: info
|
||||
The `Layout` name in `layouts` is fixed. This uses JavaScript shorthand syntax,
|
||||
essentially equivalent to `Layout: Layout`, which is crucial for implementing layout slots.
|
||||
The same rule applies to `NotFound`.
|
||||
|
||||
Other components passed that are not `Layout`/`NotFound` are considered custom layout components.
|
||||
:::
|
||||
|
||||
Then, create `.vuepress/layouts/Layout.vue` as the default component for layout slots,
|
||||
and import the current theme's `<Layout />` component in this file.
|
||||
|
||||
```vue {7-11} title=".vuepress/layouts/Layout.vue"
|
||||
<script setup>
|
||||
import { Layout } from 'vuepress-theme-plume/client' // [!code hl]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<template #page-bottom>
|
||||
<div class="custom-content">
|
||||
Custom Content
|
||||
</div>
|
||||
</template>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.custom-content {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
Content injection can also be implemented using render functions in `.vuepress/client.ts`:
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/client.ts
|
||||
|
||||
```ts
|
||||
import { h } from 'vue'
|
||||
import { Layout } from 'vuepress-theme-plume/client'
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
import CustomContent from './components/CustomContent.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
layouts: {
|
||||
Layout: () => h(Layout, null, {
|
||||
'page-bottom': () => h(CustomContent),
|
||||
}),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/components/CustomContent.vue
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="custom-content">
|
||||
Custom Content
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Slots
|
||||
|
||||
::: info
|
||||
You can preview <https://plume-layout-slots.netlify.app> to see the positions of all available slots in the site.
|
||||
:::
|
||||
|
||||
### `<Layout />` Slots
|
||||
|
||||
- When `pageLayout: doc`:
|
||||
|
||||
- `doc-top`
|
||||
- `doc-bottom`
|
||||
- `doc-content-before`
|
||||
- `doc-footer-before`
|
||||
- `doc-before`
|
||||
- `doc-after`
|
||||
- `doc-meta-top`
|
||||
- `doc-meta-bottom`
|
||||
- `doc-meta-before`
|
||||
- `doc-meta-after`
|
||||
- `sidebar-nav-before`
|
||||
- `sidebar-nav-after`
|
||||
- `aside-top`
|
||||
- `aside-bottom`
|
||||
- `aside-outline-before`
|
||||
- `aside-outline-after`
|
||||
|
||||
- When `pageLayout: page`:
|
||||
|
||||
- `page-top`
|
||||
- `page-bottom`
|
||||
|
||||
- In post collection related pages (applicable to post list pages, tags pages, and archives pages):
|
||||
|
||||
- `posts-top`
|
||||
- `posts-bottom`
|
||||
- `posts-aside-top`
|
||||
- `posts-aside-bottom`
|
||||
- `posts-extract-before`
|
||||
- `posts-extract-after`
|
||||
|
||||
- In post list pages:
|
||||
|
||||
- `posts-post-list-before`
|
||||
- `posts-post-list-after`
|
||||
- `posts-post-list-pagination-after`
|
||||
|
||||
- In tags pages:
|
||||
|
||||
- `posts-tags-before`
|
||||
- `posts-tags-title-after`
|
||||
- `posts-tags-content-before`
|
||||
- `posts-tags-after`
|
||||
|
||||
- In archives pages:
|
||||
|
||||
- `posts-archives-before`
|
||||
- `posts-archives-after`
|
||||
|
||||
- In categories pages:
|
||||
|
||||
- `posts-categories-before`
|
||||
- `posts-categories-content-before`
|
||||
- `posts-categories-after`
|
||||
|
||||
### `<NotFound />` Slots
|
||||
|
||||
- `not-found`
|
||||
|
||||
### Common Slots
|
||||
|
||||
The following slots are supported in both `<Layout />` and `<NotFound />`:
|
||||
|
||||
- `layout-top`
|
||||
- `layout-bottom`
|
||||
- `nav-bar-title-before`
|
||||
- `nav-bar-title-after`
|
||||
- `nav-bar-content-before`
|
||||
- `nav-bar-content-after`
|
||||
- `nav-bar-menu-before`
|
||||
- `nav-bar-menu-after`
|
||||
- `nav-screen-content-before`
|
||||
- `nav-screen-content-after`
|
||||
- `nav-screen-menu-before`
|
||||
- `nav-screen-menu-after`
|
||||
- `footer-content`
|
||||
- `bulletin-content`
|
||||
@ -1,10 +1,96 @@
|
||||
---
|
||||
title: Customize Style
|
||||
title: Custom Styles
|
||||
icon: icon-park-outline:theme
|
||||
createTime: 2025/03/23 14:53:21
|
||||
createTime: 2025/10/08 20:18:52
|
||||
permalink: /en/guide/custom-style/
|
||||
---
|
||||
|
||||
## Theme Customization
|
||||
|
||||
Custom styles are supported.
|
||||
|
||||
Although the theme uses [SASS](https://sass-lang.com/) as the CSS preprocessor,
|
||||
all colors are defined using `CSS Variables`. Therefore, you can create a CSS file or SCSS file to override them.
|
||||
|
||||
First, create a `styles/index.css` file in the `.vuepress` directory. Then, import this file in the [client configuration file](https://v2.vuepress.vuejs.org/guide/configuration.html#client-config-file).
|
||||
|
||||
:::code-tabs
|
||||
|
||||
@tab .vuepress/client.ts
|
||||
|
||||
```ts
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
|
||||
import './styles/index.css' // [!code ++]
|
||||
|
||||
export default defineClientConfig({
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/styles/index.css
|
||||
|
||||
```css
|
||||
:root {
|
||||
--vp-c-brand-1: #5086a1;
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Style File
|
||||
The titles are used for external jumps.
|
||||
todo ...
|
||||
|
||||
Create a file such as `custom.css` in the `.vuepress` directory.
|
||||
|
||||
Add additional styles or override default styles here:
|
||||
|
||||
```scss
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
```
|
||||
|
||||
You can also use it to override the predefined CSS variables of the default theme.
|
||||
|
||||
Below are some predefined variables. For the complete list, please refer to [vars.css](https://github.com/pengzhanbo/vuepress-theme-plume/blob/main/theme/src/client/styles/vars.css).
|
||||
|
||||
```scss
|
||||
:root {
|
||||
/** Theme Colors */
|
||||
--vp-c-brand-1: #5086a1;
|
||||
--vp-c-brand-2: #6aa1b7;
|
||||
--vp-c-brand-3: #8cccd5;
|
||||
--vp-c-brand-soft: rgba(131, 208, 218, 0.314);
|
||||
|
||||
/** Background Colors */
|
||||
--vp-c-bg: #ffffff;
|
||||
--vp-c-bg-alt: #f6f6f7;
|
||||
--vp-c-bg-elv: #ffffff;
|
||||
--vp-c-bg-soft: #f6f6f7;
|
||||
|
||||
/** Text Colors */
|
||||
--vp-c-text-1: rgba(60, 60, 67);
|
||||
--vp-c-text-2: rgba(60, 60, 67, 0.78);
|
||||
--vp-c-text-3: rgba(60, 60, 67, 0.56);
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--vp-c-brand-1: #8cccd5;
|
||||
--vp-c-brand-2: #6aa1b7;
|
||||
--vp-c-brand-3: #5086a1;
|
||||
--vp-c-brand-soft: rgba(131, 208, 218, 0.314);
|
||||
|
||||
--vp-c-bg: #1b1b1f;
|
||||
--vp-c-bg-alt: #161618;
|
||||
--vp-c-bg-elv: #202127;
|
||||
--vp-c-bg-soft: #202127;
|
||||
|
||||
--vp-c-text-1: rgba(255, 255, 245, 0.86);
|
||||
--vp-c-text-2: rgba(235, 235, 245, 0.6);
|
||||
--vp-c-text-3: rgba(235, 235, 245, 0.38);
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
The theme provides a [Theme Color Tool](../../../tools/custom-theme.md) that you can use to create custom colors.
|
||||
:::
|
||||
|
||||
62
docs/en/guide/embed/acfun.md
Normal file
62
docs/en/guide/embed/acfun.md
Normal file
@ -0,0 +1,62 @@
|
||||
---
|
||||
title: AcFun Video
|
||||
icon: lets-icons:video-fill
|
||||
createTime: 2025/10/08 10:57:45
|
||||
permalink: /en/guide/embed/video/acfun/
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme provides the capability to embed AcFun videos.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
acfun: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
Simple syntax:
|
||||
|
||||
```md
|
||||
@[acfun](id)
|
||||
```
|
||||
|
||||
More options:
|
||||
|
||||
```md
|
||||
@[acfun width="100%" height="400px" ratio="16:9"](id)
|
||||
```
|
||||
|
||||
**Parameter Description:**
|
||||
|
||||
- id: Video ID
|
||||
- width: Video width
|
||||
- height: Video height
|
||||
- ratio: Video aspect ratio, defaults to `16:9`
|
||||
|
||||
## Examples
|
||||
|
||||
### Widescreen Video
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[acfun](ac47431669)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[acfun](ac47431669)
|
||||
164
docs/en/guide/embed/artplayer.md
Normal file
164
docs/en/guide/embed/artplayer.md
Normal file
@ -0,0 +1,164 @@
|
||||
---
|
||||
title: ArtPlayer Video
|
||||
icon: icon-park-outline:video
|
||||
createTime: 2025/10/08 16:13:54
|
||||
permalink: /en/guide/embed/video/artplayer/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme provides the capability to embed custom source videos.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
artPlayer: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
This feature relies on the `artplayer` player implementation. The theme does not include this dependency
|
||||
by default. When enabling the `artPlayer` feature, manual installation is required.
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i artplayer
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The artPlayer player natively supports video formats including `'mp4'`, `'mp3'`, `'webm'`, and `'ogg'`.
|
||||
|
||||
It also supports extending compatibility for additional formats.
|
||||
|
||||
If your video format is `'mpd'` or `'dash'`, you need to manually install `dashjs`:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i dashjs
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
If your video format is `'m3u8'` or `'hls'`, you need to manually install `hls.js`:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i hls.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
If your video format is `'ts'` or `'flv'`, you need to manually install `mpegts.js`:
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i mpegts.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Markdown Syntax
|
||||
|
||||
```md
|
||||
@[artPlayer](src)
|
||||
```
|
||||
|
||||
With configuration options:
|
||||
|
||||
```md
|
||||
@[artPlayer muted autoplay loop width="100%" height="400px" ratio="16:9"](src)
|
||||
```
|
||||
|
||||
- `src`: Video source URL
|
||||
|
||||
**Parameter Description:**
|
||||
|
||||
- `width`: Video width
|
||||
- `height`: Video height
|
||||
- `ratio`: Video aspect ratio, defaults to `16:9`
|
||||
- `type`: Video format, automatically parsed from the video URL by default
|
||||
- `autoplay`: Whether to enable autoplay
|
||||
- `muted`: Whether to mute, defaults to `true` when autoplay is enabled
|
||||
- `volume`: Volume level, range from `0 - 1`
|
||||
- `poster`: Video poster image URL
|
||||
- `auto-mini`: Automatically enters mini-player mode when the player scrolls out of the browser viewport
|
||||
|
||||
## Global Component
|
||||
|
||||
The theme provides a global component `<ArtPlayer />` to support more flexible and comprehensive usage.
|
||||
|
||||
### Props
|
||||
|
||||
| Field | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| src | `string` | Required, video source URL |
|
||||
| type | `string` | Optional, video format, parsed from `src` by default |
|
||||
| width | `string` | Optional, width, defaults to `100%` |
|
||||
| height | `string` | Optional, height |
|
||||
| ratio | `string` | Optional, aspect ratio, defaults to `16:9` |
|
||||
|
||||
For more `Props`, please refer to the
|
||||
[artPlayer documentation](https://artplayer.org/document/start/option.html). The theme supports all available options.
|
||||
|
||||
## Examples
|
||||
|
||||
::: tip Note
|
||||
The video resources in the examples are sourced from [artplayer.org](https://artplayer.org).
|
||||
:::
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
@[artPlayer](https://artplayer.org/assets/sample/video.mp4)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
@[artPlayer](https://artplayer.org/assets/sample/video.mp4)
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
<ArtPlayer
|
||||
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
||||
fullscreen
|
||||
/>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
<ArtPlayer
|
||||
src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8"
|
||||
fullscreen
|
||||
/>
|
||||
|
||||
## Explanation
|
||||
|
||||
The markdown syntax `@[artPlayer](src)` is internally converted to the `<ArtPlayer />` component, which is equivalent to:
|
||||
|
||||
```md
|
||||
<ArtPlayer
|
||||
src="src"
|
||||
fullscreen
|
||||
flip
|
||||
playback-rate
|
||||
aspect-ratio
|
||||
setting
|
||||
pip
|
||||
/>
|
||||
```
|
||||
103
docs/en/guide/embed/audioReader.md
Normal file
103
docs/en/guide/embed/audioReader.md
Normal file
@ -0,0 +1,103 @@
|
||||
---
|
||||
title: Audio Reader
|
||||
icon: rivet-icons:audio
|
||||
createTime: 2025/10/08 22:31:01
|
||||
permalink: /en/guide/embed/audio/reader/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding audio reading capabilities in documentation.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
|
||||
|
||||
**Audio Reader** is not a music player; it simply embeds an
|
||||
(@[audioReader](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio))
|
||||
button within content that plays an audio clip when clicked.
|
||||
|
||||
It is suitable for playing short audio clips, such as **word pronunciation guides**.
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
audioReader: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Markdown Syntax
|
||||
|
||||
The audio embedding markdown syntax is an inline syntax, allowing usage anywhere within markdown.
|
||||
|
||||
```md
|
||||
@[audioReader](src)
|
||||
```
|
||||
|
||||
With configuration options:
|
||||
|
||||
```md
|
||||
@[audioReader type="audio/mpeg" title="title" autoplay start-time="0" end-time="10" volume="0.7"](src)
|
||||
```
|
||||
|
||||
**Parameter Description:**
|
||||
|
||||
- `type`: Audio type, formatted as `audio/mpeg`.
|
||||
Defaults to inference from the file extension in the audio URL. If the URL lacks an extension, declare manually.
|
||||
- `title`: Audio title, displayed before the audio icon.
|
||||
- `autoplay`: Whether to enable autoplay (not recommended).
|
||||
- `start-time`: Audio playback start time in seconds.
|
||||
- `end-time`: Audio playback end time in seconds.
|
||||
- `volume`: Audio playback volume, range from `0 ~ 1`.
|
||||
|
||||
## Global Component
|
||||
|
||||
The theme provides a global component `<AudioReader />` to support more flexible and comprehensive usage.
|
||||
|
||||
### Props
|
||||
|
||||
| Field | Type | Description |
|
||||
| --------- | --------- | ----------------------------------- |
|
||||
| src | `string` | Required, audio source URL |
|
||||
| type | `string` | Optional, audio format, parsed from `src` by default |
|
||||
| autoplay | `boolean` | Optional, whether to enable autoplay (not recommended) |
|
||||
| startTime | `number` | Optional, audio playback start time in seconds |
|
||||
| endTime | `number` | Optional, audio playback end time in seconds |
|
||||
| volume | `number` | Optional, audio playback volume, range from `0 ~ 1` |
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
audio 美 [ˈɔːdioʊ] @[audioReader](/audio/audio.mp3)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
audio 美 [ˈɔːdioʊ] @[audioReader](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio)
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
audio 美 @[audioReader title="[ˈɔːdioʊ]"](/audio/audio.mp3)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
audio 美 @[audioReader title="[ˈɔːdioʊ]"](https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio)
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
audio 美 <AudioReader src="/audio/audio.mp3">[ˈɔːdioʊ]</AudioReader>
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
audio 美 <AudioReader src="https://sensearch.baidu.com/gettts?lan=en&spd=3&source=alading&text=audio">[ˈɔːdioʊ]</AudioReader>
|
||||
85
docs/en/guide/embed/bilibili.md
Normal file
85
docs/en/guide/embed/bilibili.md
Normal file
@ -0,0 +1,85 @@
|
||||
---
|
||||
title: Bilibili Video
|
||||
icon: ri:bilibili-fill
|
||||
createTime: 2025/10/08 12:26:47
|
||||
permalink: /en/guide/embed/video/bilibili/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme provides the capability to embed Bilibili videos.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdownPower.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
bilibili: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
Simple syntax:
|
||||
|
||||
```md
|
||||
@[bilibili](bvid)
|
||||
```
|
||||
|
||||
For videos with multiple parts, add `p1`, `p2`, `p3` etc. after `bilibili`:
|
||||
|
||||
```md
|
||||
@[bilibili p1](aid cid)
|
||||
```
|
||||
|
||||
More options:
|
||||
|
||||
```md
|
||||
@[bilibili p1 autoplay time="0" width="100%" height="400px" ratio="16:9"](bvid aid cid)
|
||||
```
|
||||
|
||||
**Parameter Description:**
|
||||
|
||||
- bvid: Video BV ID
|
||||
- aid: Video AID
|
||||
- cid: Video CID
|
||||
- autoplay: Whether to enable autoplay
|
||||
- time: Video playback start time in seconds, or in `mm:ss` or `hh:mm:ss` format
|
||||
- width: Video width
|
||||
- height: Video height
|
||||
- ratio: Video aspect ratio, defaults to `16:9`
|
||||
|
||||
For videos with multiple parts, `bvid` can be omitted, but `aid` and `cid` must be provided.
|
||||
|
||||
## Examples
|
||||
|
||||
### Widescreen Video
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[bilibili](BV1EZ42187Hg)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[bilibili](BV1EZ42187Hg)
|
||||
|
||||
### Vertical Video
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[bilibili width="320px" ratio="9:16"](BV1zr42187eg)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[bilibili width="320px" ratio="9:16"](BV1zr42187eg)
|
||||
114
docs/en/guide/embed/pdf.md
Normal file
114
docs/en/guide/embed/pdf.md
Normal file
@ -0,0 +1,114 @@
|
||||
---
|
||||
title: PDF Reader
|
||||
icon: teenyicons:pdf-outline
|
||||
createTime: 2025/10/08 13:30:53
|
||||
permalink: /en/guide/embed/pdf/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports embedding PDF files in markdown, enabling direct PDF reading within the page.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
pdf: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
The simplest syntax is as follows:
|
||||
|
||||
```md
|
||||
@[pdf](url)
|
||||
```
|
||||
|
||||
To open a specific page, add a page number after `pdf`:
|
||||
|
||||
```md
|
||||
@[pdf 2](url)
|
||||
```
|
||||
|
||||
Additional options can be added to `@[pdf ]` for more flexible control:
|
||||
|
||||
```md
|
||||
@[pdf 2 no-toolbar width="100%" height="400px" ratio="16:9" zoom="100"](url)
|
||||
```
|
||||
|
||||
- `no-toolbar` - Hide the toolbar
|
||||
- `width` - Width, defaults to 100%
|
||||
- `height` - Height, defaults to `auto`
|
||||
- `ratio` - Aspect ratio, defaults to `16:9`, only effective when height is not specified
|
||||
- `zoom` - Zoom level, percentage
|
||||
|
||||
## Examples
|
||||
|
||||
### Default
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[pdf](https://plume.pengzhanbo.cn/files/sample.pdf)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[pdf](/files/sample.pdf)
|
||||
|
||||
### Set Page Number to 2
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[pdf 2](https://plume.pengzhanbo.cn/files/sample.pdf)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[pdf 2 zoom="95"](/files/sample.pdf)
|
||||
|
||||
### Hide Toolbar
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[pdf no-toolbar](https://plume.pengzhanbo.cn/files/sample.pdf)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[pdf no-toolbar](/files/sample.pdf)
|
||||
|
||||
### 90% Zoom Level
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[pdf zoom="90"](https://plume.pengzhanbo.cn/files/sample.pdf)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[pdf zoom="90"](/files/sample.pdf)
|
||||
|
||||
### 21:29 Aspect Ratio
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[pdf zoom="95" ratio="21:29"](https://plume.pengzhanbo.cn/files/sample.pdf)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[pdf zoom="95" ratio="21:29"](/files/sample.pdf)
|
||||
65
docs/en/guide/embed/youtube.md
Normal file
65
docs/en/guide/embed/youtube.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: YouTube Video
|
||||
icon: mdi:youtube
|
||||
createTime: 2025/10/08 14:30:33
|
||||
permalink: /en/guide/embed/video/youtube/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme provides the capability to embed YouTube videos.
|
||||
|
||||
This feature is powered by [vuepress-plugin-md-power](../../config/plugins/markdown-power.md).
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
youtube: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
Simple syntax:
|
||||
|
||||
```md
|
||||
@[youtube](id)
|
||||
```
|
||||
|
||||
More options:
|
||||
|
||||
```md
|
||||
@[youtube autoplay loop start="0" end="0" width="100%" height="400px" ratio="16:9"](id)
|
||||
```
|
||||
|
||||
**Parameter Description:**
|
||||
|
||||
- id: Video ID
|
||||
- autoplay: Whether to enable autoplay
|
||||
- loop: Whether to enable loop playback
|
||||
- start: Video playback start time in seconds, or in `mm:ss` or `hh:mm:ss` format
|
||||
- end: Video playback end time in seconds, or in `mm:ss` or `hh:mm:ss` format
|
||||
- width: Video width
|
||||
- height: Video height
|
||||
- ratio: Video aspect ratio, defaults to `16:9`
|
||||
|
||||
## Examples
|
||||
|
||||
### Widescreen Video
|
||||
|
||||
Input:
|
||||
|
||||
```md
|
||||
@[youtube](0JJPfz5dg20)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
@[youtube](0JJPfz5dg20)
|
||||
391
docs/en/guide/features/bulletin.md
Normal file
391
docs/en/guide/features/bulletin.md
Normal file
@ -0,0 +1,391 @@
|
||||
---
|
||||
title: Bulletin
|
||||
icon: mingcute:announcement-line
|
||||
createTime: 2025/10/08 21:51:22
|
||||
permalink: /en/guide/features/bulletin/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The bulletin is a real-time notification component that enables convenient display of notification messages within the site.
|
||||
|
||||
Such as the bulletin in the top-right corner.
|
||||
|
||||
## Usage
|
||||
|
||||
The theme provides very convenient and flexible methods for using the bulletin.
|
||||
You can choose the appropriate configuration method based on your requirements.
|
||||
|
||||
### Configuration Options
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
// more options...
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```ts
|
||||
interface BulletinOptions {
|
||||
/**
|
||||
* Bulletin position
|
||||
* @default 'top-right'
|
||||
*/
|
||||
layout?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center'
|
||||
|
||||
/**
|
||||
* Whether to display gradient border
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
border?: boolean
|
||||
|
||||
/**
|
||||
* Pages where the bulletin is displayed
|
||||
*
|
||||
* - `true` indicates all pages
|
||||
* - `false` indicates no display
|
||||
* - Pass a function that returns `true` when display is enabled
|
||||
*/
|
||||
enablePage?: boolean | ((page: Page) => boolean)
|
||||
|
||||
/**
|
||||
* Bulletin display duration
|
||||
*
|
||||
* @default 'always'
|
||||
*
|
||||
* - `'session'`: After closing the bulletin, it won't display again during the current session cycle. It will reappear in new session cycles. Refreshing the page won't make it reappear.
|
||||
* - `'always'`: Always display. After closing, refreshing the page will make it reappear.
|
||||
* - `'once'`: Display only in the current cycle. After closing, it won't display again. Neither new sessions nor page refreshes will make it reappear.
|
||||
*/
|
||||
lifetime?: 'session' | 'always' | 'once'
|
||||
|
||||
/**
|
||||
* Bulletin ID
|
||||
*
|
||||
* The bulletin display duration uses the `id` as a unique identifier
|
||||
*/
|
||||
id?: string
|
||||
|
||||
/**
|
||||
* Bulletin title
|
||||
*/
|
||||
title?: string
|
||||
|
||||
/**
|
||||
* Bulletin content
|
||||
*
|
||||
* Markdown syntax or HTML text can be used.
|
||||
* When using markdown, declare `contentType` as `markdown`
|
||||
*/
|
||||
content?: string
|
||||
|
||||
/**
|
||||
* Bulletin content type
|
||||
*
|
||||
* - `markdown` indicates using markdown syntax
|
||||
* - `text` indicates using plain text (can be HTML content)
|
||||
*
|
||||
* @default 'text'
|
||||
*/
|
||||
contentType?: 'markdown' | 'text'
|
||||
|
||||
/**
|
||||
* Pass a `markdown` or `html` file path and use the file content as bulletin content
|
||||
*
|
||||
* - When using `.md` files, markdown syntax will be parsed
|
||||
* - When using `.html` files, only include bulletin content. Please avoid using tags like `<html>`, `<body>`, `<script>`, etc.
|
||||
*/
|
||||
contentFile?: string
|
||||
}
|
||||
```
|
||||
|
||||
## Simple Bulletin
|
||||
|
||||
When you only need to configure a simple bulletin with brief content, you can directly use `bulletin.content` to add content.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
content: 'Bulletin content',
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also declare `bulletin.contentType` as `markdown` to use markdown syntax in the `content`.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
contentType: 'markdown', // [!code hl]
|
||||
content: `\
|
||||
**Update Notes**
|
||||
|
||||
- Added some features
|
||||
- Fixed some bugs
|
||||
`,
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Long Content Bulletin
|
||||
|
||||
When you need to configure a bulletin with lengthy content, writing long content in the configuration file
|
||||
may appear bloated and difficult to read. In such cases, use `bulletin.contentFile` to specify a content
|
||||
file path, separating the long content from the configuration file.
|
||||
|
||||
`bulletin.contentFile` requires an absolute path to a `markdown` or `html` file.
|
||||
The theme will use the content of this file as the bulletin content.
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/config.ts
|
||||
|
||||
```ts
|
||||
import path from 'node:path'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
contentFile: path.join(__dirname, '_bulletin.md'),
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab .vuepress/_bulletin.md
|
||||
|
||||
```md
|
||||
**Update Notes**
|
||||
|
||||
- Added some features
|
||||
- Fixed some bugs
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
The theme monitors changes to `bulletin.contentFile`. When the file content changes, the bulletin will be re-rendered.
|
||||
|
||||
## Bulletin with Custom Content Interactions
|
||||
|
||||
Using `bulletin.content` or `bulletin.contentFile` only allows writing plain text bulletin content and
|
||||
some interactive content supported by `markdown` syntax. It does not support writing bulletin content with other custom interactions.
|
||||
|
||||
For such scenarios, the theme also provides corresponding support.
|
||||
|
||||
First, configure the basic content of `bulletin`. You don't need to configure `bulletin.content` or `bulletin.contentFile` at this point.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Then, register the global component `BulletinContent` in `.vuepress/client.ts`.
|
||||
The theme will automatically detect this component and use it as the bulletin content.
|
||||
|
||||
```ts title=".vuepress/client.ts"
|
||||
import { defineClientConfig } from '@vuepress/client'
|
||||
import BulletinContent from './components/BulletinContent.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance: ({ app }) => {
|
||||
app.component('BulletinContent', BulletinContent)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Next, write the `BulletinContent.vue` component.
|
||||
|
||||
```vue title=".vuepress/components/BulletinContent.vue"
|
||||
<script setup>
|
||||
// Write custom bulletin content interactions
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bulletin-content">
|
||||
<!-- Custom bulletin content -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Custom bulletin content styles */
|
||||
</style>
|
||||
```
|
||||
|
||||
## Custom Bulletin Styles
|
||||
|
||||
You can directly override the bulletin styles via CSS.
|
||||
|
||||
Modify the following CSS variables to easily control the bulletin styles.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--vp-bulletin-bg-color: var(--vp-c-bg);
|
||||
--vp-bulletin-text-color: var(--vp-c-text-1);
|
||||
--vp-bulletin-title-color: var(--vp-c-text-1);
|
||||
--vp-bulletin-font-size: 16px;
|
||||
--vp-bulletin-title-font-size: 18px;
|
||||
--vp-bulletin-line-height: 24px;
|
||||
--vp-bulletin-border-width: 2px;
|
||||
--vp-bulletin-border: conic-gradient(var(--vp-c-important-3), var(--vp-c-danger-3), var(--vp-c-success-3), var(--vp-c-important-3));
|
||||
--vp-bulletin-width: 320px;
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, override the bulletin styles globally via the `.vp-bulletin` class.
|
||||
|
||||
```css
|
||||
.vp-bulletin {
|
||||
/* Bulletin styles */
|
||||
}
|
||||
```
|
||||
|
||||
## Fully Custom Bulletin
|
||||
|
||||
When you don't want to use the theme's built-in bulletin at all, you can completely customize the
|
||||
bulletin by registering a global `Bulletin` component.
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/client.ts
|
||||
|
||||
```ts
|
||||
import { defineClientConfig } from '@vuepress/client'
|
||||
import Bulletin from './components/Bulletin.vue'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance: ({ app }) => {
|
||||
app.component('Bulletin', Bulletin)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Next, write the `Bulletin.vue` component.
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/components/Bulletin.vue
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// Write custom bulletin
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bulletin">
|
||||
<!-- Custom bulletin -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Custom bulletin styles */
|
||||
</style>
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
You need to write the bulletin component from scratch. To facilitate writing the bulletin, the theme
|
||||
provides the composable API `useBulletinControl()`, which you can use directly in the `Bulletin.vue` component.
|
||||
|
||||
```ts
|
||||
import { useBulletinControl } from 'vuepress-theme-plume/composables'
|
||||
|
||||
const {
|
||||
bulletin, // Bulletin configuration, read from theme configuration
|
||||
showBulletin, // Whether to show the bulletin
|
||||
enableBulletin, // Whether the bulletin is enabled on the current page
|
||||
close, // Close the bulletin
|
||||
} = useBulletinControl()
|
||||
```
|
||||
|
||||
## Related Notes
|
||||
|
||||
### Bulletin Unique Identifier
|
||||
|
||||
The bulletin's unique identifier is configured via `bulletin.id`.
|
||||
|
||||
The unique identifier is used to distinguish bulletins and determine the validity period of `bulletin.lifetime` based on this identifier.
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
id: 'my-bulletin', // [!code hl]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
When you don't explicitly configure `bulletin.id`, the theme generates a hash value based on the `bulletin` object as the unique identifier.
|
||||
|
||||
### Bulletin Display Duration
|
||||
|
||||
The bulletin display duration is configured via `bulletin.lifetime`.
|
||||
|
||||
- `session`: During the current session cycle, if the user doesn't close the bulletin,
|
||||
it will continue to display, including into the next session cycle. When the user closes the bulletin,
|
||||
it is considered expired and won't display again during the current session cycle, but will reappear in the next session cycle.
|
||||
|
||||
- `always`: Even if the user closes the bulletin, it will reappear not only in the next session cycle but also when refreshing the page.
|
||||
|
||||
- `once`: Once the bulletin is closed during the current session cycle, it won't display again afterward.
|
||||
|
||||
::: details What is a session?
|
||||
**Session** refers to the period when you visit a site. As long as the browser tab where the site is
|
||||
located remains open, the site maintains the same session, even if the page is refreshed.
|
||||
:::
|
||||
|
||||
### Bulletin Position
|
||||
|
||||
The bulletin position is configured via `bulletin.layout`.
|
||||
|
||||
- `top-left`: Top left
|
||||
- `top-right`: Top right
|
||||
- `bottom-left`: Bottom left
|
||||
- `bottom-right`: Bottom right
|
||||
- `center`: Top center
|
||||
|
||||
### Pages Where Bulletin is Displayed
|
||||
|
||||
The pages where the bulletin is displayed are configured via `bulletin.enablePage`.
|
||||
|
||||
- `true` indicates all pages
|
||||
- `false` indicates no display
|
||||
- Pass a function that returns `true` when display is enabled
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
bulletin: {
|
||||
layout: 'top-right',
|
||||
title: 'Bulletin Title',
|
||||
enablePage: (page) => {
|
||||
return page.path === '/custom-path/'
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
160
docs/en/guide/features/changelog.md
Normal file
160
docs/en/guide/features/changelog.md
Normal file
@ -0,0 +1,160 @@
|
||||
---
|
||||
title: Changelog
|
||||
icon: radix-icons:activity-log
|
||||
createTime: 2025/10/08 18:16:25
|
||||
permalink: /en/guide/features/changelog/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports adding article changelogs to better track the modification history of your articles.
|
||||
|
||||
Article changelogs are obtained through git commit history.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html).
|
||||
|
||||
::: warning Note
|
||||
This feature relies on the `git log` command to retrieve commit history for each markdown file,
|
||||
which can be relatively time-consuming, especially for large projects with extensive commit histories.
|
||||
Therefore, this feature is not enabled in development environments by default and is only enabled in production environments.
|
||||
|
||||
However, you can still enable it in development environments by setting `theme.plugins.git` to `true` for testing purposes.
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: { git: true }
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
The theme has built-in support for the
|
||||
[@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) plugin, so you can use it without reinstalling.
|
||||
|
||||
Enable this feature in the theme configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Disabled by default, only takes effect when plugins.git is true
|
||||
// This configuration is invalid in plume.config.ts
|
||||
changelog: true,
|
||||
|
||||
plugins: {
|
||||
// If you declare it directly as true here, it means the feature is enabled in both development and production environments
|
||||
git: process.env.NODE_ENV === 'production'
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts
|
||||
interface ChangelogOptions {
|
||||
/**
|
||||
* Maximum number of change records, defaults to all records
|
||||
*/
|
||||
maxCount?: number
|
||||
/**
|
||||
* Git repository URL, e.g., https://github.com/vuepress/ecosystem
|
||||
*/
|
||||
repoUrl?: string
|
||||
/**
|
||||
* Commit URL pattern
|
||||
*
|
||||
* - `:repo` - Git repository URL
|
||||
* - `:hash` - Commit hash
|
||||
*
|
||||
* @default ':repo/commit/:hash'
|
||||
*/
|
||||
commitUrlPattern?: string
|
||||
/**
|
||||
* Issue URL pattern
|
||||
*
|
||||
* - `:repo` - Git repository URL
|
||||
* - `:issue` - Issue ID
|
||||
*
|
||||
* @default ':repo/issues/:issue'
|
||||
*/
|
||||
issueUrlPattern?: string
|
||||
/**
|
||||
* Tag URL pattern
|
||||
* Default: ':repo/releases/tag/:tag'
|
||||
*
|
||||
* - `:repo` - Git repository URL
|
||||
* - `:tag` - Tag name
|
||||
*
|
||||
* @default ':repo/releases/tag/:tag'
|
||||
*/
|
||||
tagUrlPattern?: string
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
changelog: {
|
||||
maxCount: 10,
|
||||
repoUrl: 'https://github.com/vuepress/vuepress',
|
||||
commitUrlPattern: ':repo/commit/:hash',
|
||||
issueUrlPattern: ':repo/issues/:issue',
|
||||
tagUrlPattern: ':repo/releases/tag/:tag'
|
||||
},
|
||||
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
::: warning Note
|
||||
Ensure that `changelog.repoUrl` is correctly configured. The default value is [docsRepo](../../config/theme.md#docsrepo).
|
||||
|
||||
The theme by default adapts to the URL patterns of git hosting services like `GitHub`, `GitLab`, `Gitee`, and `Bitbucket`.
|
||||
If you're using a self-hosted service or others, please configure `commitUrlPattern`, `issueUrlPattern`, and `tagUrlPattern` accordingly.
|
||||
:::
|
||||
|
||||
## Notes
|
||||
|
||||
This feature requires your project to be under a
|
||||
[Git repository](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) so it can collect information from the commit history.
|
||||
|
||||
**When building your site, you should ensure all commit records are accessible.**
|
||||
|
||||
For example, CI workflows typically add the `--depth 1` parameter when cloning your repository to avoid
|
||||
fetching all commit history. Therefore, you need to disable this feature so the plugin can work properly in CI.
|
||||
|
||||
Services like `GitHub Actions`, `Netlify`, and `Vercel` do not fetch all commit history by default.
|
||||
|
||||
In `GitHub Actions`, you can add the `--depth 0` parameter to ensure `GitHub Actions` can correctly fetch all commit records.
|
||||
|
||||
``` yaml title=".github/workflows/deploy.yml"
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4 # [!code focus:3]
|
||||
with: # [!code ++:2]
|
||||
fetch-depth: 0
|
||||
```
|
||||
|
||||
For services like `Netlify` and `Vercel`, the processing method is relatively more complex.
|
||||
In such cases, you can first complete the build in `GitHub Actions` and output the artifacts to
|
||||
a separate branch, then use that branch for deployment in `Netlify` or `Vercel`.
|
||||
|
||||
::: info
|
||||
For projects created via the theme's `cli` tool, when selecting the deployment method as `GitHub Action`,
|
||||
the build artifacts are output to the `gh_pages` branch. You can base your `Netlify` or `Vercel` deployment on this branch.
|
||||
:::
|
||||
262
docs/en/guide/features/comments.md
Normal file
262
docs/en/guide/features/comments.md
Normal file
@ -0,0 +1,262 @@
|
||||
---
|
||||
title: Comments
|
||||
icon: la:comment
|
||||
createTime: 2025/10/08 11:58:59
|
||||
permalink: /en/guide/features/comments/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Article comments are powered by [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/).
|
||||
|
||||
The theme has built-in plugin support, so you can use it without reinstalling.
|
||||
|
||||
In this theme, configure through the following fields:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
comment: {
|
||||
// Service provider
|
||||
provider: '', // "Artalk" | "Giscus" | "Twikoo" | "Waline"
|
||||
// Whether comments are enabled by default
|
||||
comment: true,
|
||||
|
||||
// Other configurations based on the service provider
|
||||
// ...
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Service Providers
|
||||
|
||||
[@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/) supports various
|
||||
comment service providers such as `"Artalk" | "Giscus" | "Twikoo" | "Waline"`.
|
||||
|
||||
You can configure based on your requirements.
|
||||
|
||||
- `Giscus` is a comment system based on GitHub Discussions, easy to set up. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/giscus/)
|
||||
- `Waline` is a comment system that requires a backend, offering higher security. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/)
|
||||
- `Twikoo` is a concise, secure, free static website comment system based on Tencent Cloud Base. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/twikoo/)
|
||||
- `Artalk` is a concise self-hosted comment system that you can easily deploy on your server and embed in frontend pages. [View documentation](https://ecosystem.vuejs.press/zh/plugins/blog/comment/artalk/)
|
||||
|
||||
::: tip Recommended Comment Services
|
||||
|
||||
- For programmers and developers: Giscus
|
||||
- For the general public: Waline
|
||||
:::
|
||||
|
||||
::: note
|
||||
Examples are forked from [@vuepress/plugin-comment](https://ecosystem.vuejs.press/zh/plugins/blog/comment/),
|
||||
following the [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE) license.
|
||||
:::
|
||||
|
||||
## Giscus
|
||||
|
||||
Giscus is a comment system based on GitHub Discussions, easy to set up.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
::: steps
|
||||
|
||||
1. You need to create a public repository and enable Discussions to serve as the location for storing comments.
|
||||
|
||||
2. You need to install the [Giscus App](https://github.com/apps/giscus) to grant it permission to access the corresponding repository.
|
||||
|
||||
3. After completing the above steps, go to the [Giscus page](https://giscus.app/zh-CN) to get your settings.
|
||||
|
||||
You only need to fill in the repository and Discussion category, then scroll to the "Enable giscus" section
|
||||
at the bottom of the page to obtain the four attributes: `data-repo`, `data-repo-id`, `data-category`, and `data-category-id`.
|
||||
|
||||
:::
|
||||
|
||||
### Configuration
|
||||
|
||||
Set `provider: 'Giscus'` and pass `data-repo`, `data-repo-id`, `data-category`, and `data-category-id` as
|
||||
plugin options to `repo`, `repoId`, `category`, and `categoryId`.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
comment: {
|
||||
provider: 'Giscus', // "Artalk" | "Giscus" | "Twikoo" | "Waline"
|
||||
comment: true,
|
||||
repo: 'Your_Repo', // [!code ++]
|
||||
repoId: 'Your_RepoId', // [!code ++]
|
||||
category: 'Your_Category', // [!code ++]
|
||||
categoryId: 'Your_CategoryId', // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Themes
|
||||
|
||||
By default, Giscus uses `light` or `dark` themes (based on the dark mode state).
|
||||
|
||||
If you want to customize themes for light and dark modes, you can set the `lightTheme` and `darkTheme` options
|
||||
using built-in theme keywords or custom CSS links starting with `https://`.
|
||||
|
||||
## Waline
|
||||
|
||||
A secure comment system with a backend.
|
||||
|
||||
### Installation
|
||||
|
||||
If you want to use Waline in the theme, you need to install `@waline/client` first.
|
||||
|
||||
::: npm-to
|
||||
|
||||
```sh
|
||||
npm i @waline/client
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### LeanCloud Setup (Database)
|
||||
|
||||
::: steps
|
||||
|
||||
1. [Login](https://console.leancloud.app/login) or [Register](https://console.leancloud.app/register) for
|
||||
`LeanCloud International` and enter the [Console](https://console.leancloud.app/apps)
|
||||
|
||||
2. Click [Create Application](https://console.leancloud.app/apps) in the upper left corner and choose a name
|
||||
you like (please select the free development plan):
|
||||
|
||||

|
||||
|
||||
3. Enter the application, select `Settings` > `Application Keys` in the lower left corner.
|
||||
You can see your `APP ID`, `APP Key`, and `Master Key`. Please record them for later use.
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
::: warning Domestic version requires ICP filing
|
||||
|
||||
If you are using the LeanCloud domestic version ([leancloud.cn](https://leancloud.cn)), we recommend
|
||||
switching to the international version ([leancloud.app](https://leancloud.app)).
|
||||
Otherwise, you need to bind an **already ICP-filed** domain to the application, purchase an independent IP, and complete the ICP filing process:
|
||||
|
||||
- Log in to the domestic version and enter the application you need to use
|
||||
- Select `Settings` > `Domain Binding` > `API Access Domain` > `Bind New Domain` > Enter domain > `OK`.
|
||||
- Follow the instructions on the page to complete the CNAME resolution in DNS as required.
|
||||
- Purchase an independent IP and submit a work order to complete the ICP filing. (The current price for an independent IP is ¥50/month)
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
### Vercel Deployment (Server)
|
||||
|
||||
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwalinejs%2Fwaline%2Ftree%2Fmain%2Fexample)
|
||||
|
||||
:::: steps
|
||||
|
||||
1. Click the button above to jump to Vercel for server-side deployment.
|
||||
|
||||
::: note
|
||||
|
||||
If you are not logged in, Vercel will prompt you to register or log in. Please use your GitHub account for quick login.
|
||||
|
||||
:::
|
||||
|
||||
2. Enter a Vercel project name you like and click `Create` to continue:
|
||||
|
||||

|
||||
|
||||
3. At this point, Vercel will help you create and initialize a repository based on the Waline template,
|
||||
with the repository name being the project name you entered earlier.
|
||||
|
||||

|
||||
|
||||
After a minute or two, a full screen of fireworks will celebrate your successful deployment.
|
||||
Click `Go to Dashboard` to jump to the application's console.
|
||||
|
||||

|
||||
|
||||
4. Click `Settings` at the top - `Environment Variables` to enter the environment variable configuration page,
|
||||
and configure the three environment variables `LEAN_ID`, `LEAN_KEY`, and `LEAN_MASTER_KEY`.
|
||||
Their values correspond to the `APP ID`, `APP KEY`, and `Master Key` obtained from LeanCloud in the previous step, respectively.
|
||||
|
||||

|
||||
|
||||
::: note
|
||||
|
||||
If you are using the LeanCloud domestic version, please additionally configure the `LEAN_SERVER`
|
||||
environment variable with the value of your bound domain.
|
||||
|
||||
:::
|
||||
|
||||
5. After configuring the environment variables, click `Deployments` at the top,
|
||||
then click the `Redeploy` button on the right side of the latest deployment to redeploy.
|
||||
This step is to make the environment variables you just set take effect.
|
||||
|
||||

|
||||
|
||||
6. At this point, it will jump to the `Overview` interface to start deployment.
|
||||
Wait a moment until the `STATUS` becomes `Ready`. Then click `Visit` to jump to the deployed
|
||||
website address, which is your server address.
|
||||
|
||||

|
||||
|
||||
::::
|
||||
|
||||
### Domain Binding (Optional)
|
||||
|
||||
::: steps
|
||||
|
||||
1. Click `Settings` - `Domains` at the top to enter the domain configuration page.
|
||||
|
||||
2. Enter the domain you want to bind and click `Add`.
|
||||
|
||||

|
||||
|
||||
3. Add a new `CNAME` record at your domain DNS provider.
|
||||
|
||||
| Type | Name | Value |
|
||||
| ----- | ------- | -------------------- |
|
||||
| CNAME | example | cname.vercel-dns.com |
|
||||
|
||||
4. Wait for it to take effect. You can now access it via your own domain :tada:
|
||||
|
||||
- Comment system: example.your-domain.com
|
||||
- Comment management: example.your-domain.com/ui
|
||||
|
||||

|
||||
|
||||
:::
|
||||
|
||||
### Client
|
||||
|
||||
#### Using the Plugin
|
||||
|
||||
Set `provider: "Waline"` in the plugin options, and set the server address `serverURL` to the value obtained in the previous step.
|
||||
|
||||
At this point, place the `<CommentService>` component in a suitable location on your website
|
||||
(usually at the bottom of the page) to use the Waline comment functionality.
|
||||
|
||||
::: tip
|
||||
|
||||
You can also pass other options supported by Waline (except `el`). For details, see [Waline Configuration](https://ecosystem.vuejs.press/zh/plugins/blog/comment/waline/config.html).
|
||||
|
||||
:::
|
||||
|
||||
### Comment Management (Admin Panel)
|
||||
|
||||
::: steps
|
||||
|
||||
1. After deployment is complete, please visit `<serverURL>/ui/register` to register. The first person to register will be set as the administrator.
|
||||
|
||||
2. After logging in as an administrator, you can see the comment management interface. Here you can modify, mark, or delete comments.
|
||||
|
||||
3. Users can also register accounts through the comment box. After logging in, they will be redirected to their own profile page.
|
||||
|
||||
:::
|
||||
@ -1,9 +0,0 @@
|
||||
---
|
||||
title: Component
|
||||
icon: radix-icons:component-2
|
||||
createTime: 2025/03/24 19:52:21
|
||||
outline: 2
|
||||
permalink: /en/guide/features/component/
|
||||
---
|
||||
|
||||
The original content of this document has been migrated to Component .
|
||||
329
docs/en/guide/features/contributors.md
Normal file
329
docs/en/guide/features/contributors.md
Normal file
@ -0,0 +1,329 @@
|
||||
---
|
||||
title: Contributors
|
||||
icon: simple-icons:contributorcovenant
|
||||
createTime: 2025/10/08 16:26:54
|
||||
permalink: /en/guide/features/contributors/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports adding contributor information to articles to better track your article contributors.
|
||||
|
||||
Article contributors are obtained through git commit history.
|
||||
|
||||
This feature is powered by [@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html).
|
||||
|
||||
::: warning Note
|
||||
This feature relies on the `git log` command to retrieve commit history for each markdown file,
|
||||
which can be relatively time-consuming, especially for large projects with extensive commit histories.
|
||||
Therefore, this feature is not enabled in development environments by default and is only enabled in production environments.
|
||||
|
||||
However, you can still enable it in development environments by setting `theme.plugins.git` to `true` for testing purposes.
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: { git: true }
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
The theme has built-in support for the
|
||||
[@vuepress/plugin-git](https://ecosystem.vuejs.press/zh/plugins/development/git.html) plugin, so you can use it without reinstalling.
|
||||
|
||||
Enable this feature in the theme configuration file:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Enabled by default, only takes effect when plugins.git is true
|
||||
// This configuration is invalid in plume.config.ts
|
||||
contributors: true,
|
||||
|
||||
plugins: {
|
||||
// If you declare it directly as true here, it means the feature is enabled in both development and production environments
|
||||
git: process.env.NODE_ENV === 'production'
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### mode
|
||||
|
||||
- Type: `'inline' | 'block'`
|
||||
- Default: `'inline'`
|
||||
- Description:
|
||||
|
||||
- `inline`: Display contributor information at the bottom of the article page,
|
||||
alongside the last updated time. In this mode, only contributor names are displayed.
|
||||
|
||||

|
||||
|
||||
- `block`: Insert contributor information at the end of the article content. This mode includes contributor names, links, and avatars.
|
||||
(As shown at the end of the current page's content)
|
||||
|
||||
In `block` mode, avatars are displayed by default for all contributors,
|
||||
even if you haven't provided an avatar URL.
|
||||
The plugin will generate avatar URLs from `https://gravatar.com/` based on email addresses or usernames.
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### info
|
||||
|
||||
- Type: `ContributorInfo[]`
|
||||
|
||||
```ts
|
||||
interface ContributorInfo {
|
||||
/**
|
||||
* Contributor's username on Git hosting service
|
||||
*/
|
||||
username: string
|
||||
/**
|
||||
* Name displayed for the contributor on the page, defaults to `username`
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* Contributor alias. Since the username saved in local git configuration might not match the hosting service username,
|
||||
* aliases can be used to map to the actual username
|
||||
*/
|
||||
alias?: string[] | string
|
||||
/**
|
||||
* Contributor avatar URL
|
||||
* If the git hosting service is `GitHub`, this can be omitted as the plugin will auto-fill it
|
||||
*/
|
||||
avatar?: string
|
||||
/**
|
||||
* Contributor profile URL
|
||||
* If the git hosting service is `GitHub`, this can be omitted as the plugin will auto-fill it
|
||||
*/
|
||||
url?: string
|
||||
}
|
||||
```
|
||||
|
||||
- Description:
|
||||
|
||||
List of contributor information.
|
||||
|
||||
The username and email configured in the user's local git service might not match the user information
|
||||
on git hosting services (like GitHub, GitLab, Gitee). You can pre-configure contributor information here.
|
||||
|
||||
(For non-GitHub git hosting services such as GitLab and Gitee, since avatars and user URLs cannot be
|
||||
directly obtained from usernames, please supplement and complete user information here.)
|
||||
|
||||
::: code-tabs
|
||||
|
||||
@tab Github
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
info: [
|
||||
{
|
||||
username: 'pengzhanbo', // github username
|
||||
alias: ['peng_zhan_bo'], // alias, username in local git configuration
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab Gitlab
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
info: [
|
||||
{
|
||||
username: 'pengzhanbo', // gitlab username
|
||||
alias: ['peng_zhan_bo'], // alias, username in local git configuration
|
||||
url: 'https://gitlab.com/pengzhanbo',
|
||||
avatar: 'https://gitlab.com/uploads/-/system/user/avatar/1/avatar.png',
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab Gitee
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
info: [
|
||||
{
|
||||
username: 'pengzhanbo', // gitee username
|
||||
alias: ['peng_zhan_bo'], // alias, username in local git configuration
|
||||
url: 'https://gitee.com/pengzhanbo',
|
||||
avatar: 'https://foruda.gitee.com/avatar/1234455/avatar.png',
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab Bitbucket
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
info: [
|
||||
{
|
||||
username: 'pengzhanbo', // bitbucket username
|
||||
alias: ['peng_zhan_bo'], // alias, username in local git configuration
|
||||
url: 'https://bitbucket.org/pengzhanbo',
|
||||
avatar: 'https://bitbucket.org/pengzhanbo/avatar/1234455/avatar.png',
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@tab Others
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
contributors: {
|
||||
mode: 'block',
|
||||
info: [
|
||||
{
|
||||
username: 'pengzhanbo', // username
|
||||
alias: ['peng_zhan_bo'], // alias, username in local git configuration
|
||||
url: 'https://your-git.com/pengzhanbo',
|
||||
avatar: 'https://your-git.com/avatar.png',
|
||||
}
|
||||
]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### avatar
|
||||
|
||||
- Type: `boolean`
|
||||
- Default: `true`
|
||||
- Description: Whether to display contributor avatars
|
||||
|
||||
### avatarPattern
|
||||
|
||||
- Type: `string`
|
||||
- Default: `'https://github.com/:username.png'`
|
||||
- Description: Contributor avatar URL pattern
|
||||
|
||||
`:username` will be replaced with the contributor's username
|
||||
|
||||
### transform(contributors)
|
||||
|
||||
- Type: `(contributors: GitContributor[]) => GitContributor[]`
|
||||
|
||||
```ts
|
||||
interface GitContributor {
|
||||
name: string // Display name
|
||||
username: string // Git hosting service username
|
||||
email: string
|
||||
commits: number // Number of commits by the contributor
|
||||
avatar?: string
|
||||
}
|
||||
```
|
||||
|
||||
- Description:
|
||||
|
||||
Contributor transformation function. This function should return a new list of contributors.
|
||||
You can add transformation logic here, such as sorting, deduplication, or completing information.
|
||||
|
||||
## frontmatter
|
||||
|
||||
### contributors
|
||||
|
||||
- Type: `boolean | string[]`
|
||||
|
||||
- Description:
|
||||
|
||||
Whether to display contributor information.
|
||||
|
||||
If your article comes from a third party and git commits cannot fully list all authors, you can supplement contributors here.
|
||||
|
||||
## Notes
|
||||
|
||||
This feature requires your project to be under a
|
||||
[Git repository](https://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository) so it can collect information from the commit history.
|
||||
|
||||
**When building your site, you should ensure all commit records are accessible.**
|
||||
|
||||
For example, CI workflows typically add the `--depth 1` parameter when cloning your repository to avoid
|
||||
fetching all commit history. Therefore, you need to disable this feature so the plugin can work properly in CI.
|
||||
|
||||
Services like `GitHub Actions`, `Netlify`, and `Vercel` do not fetch all commit history by default.
|
||||
|
||||
In `GitHub Actions`, you can add the `--depth 0` parameter to ensure `GitHub Actions` can correctly fetch all commit records.
|
||||
|
||||
``` yaml title=".github/workflows/deploy.yml"
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4 # [!code focus:3]
|
||||
with: # [!code ++:2]
|
||||
fetch-depth: 0
|
||||
```
|
||||
|
||||
For services like `Netlify` and `Vercel`, the processing method is relatively more complex.
|
||||
In such cases, you can first complete the build in `GitHub Actions` and output the artifacts to a
|
||||
separate branch, then use that branch for deployment in `Netlify` or `Vercel`.
|
||||
|
||||
::: info
|
||||
For projects created via the theme's `cli` tool, when selecting the deployment method as `GitHub Action`,
|
||||
the build artifacts are output to the `gh_pages` branch. You can base your `Netlify` or `Vercel` deployment on this branch.
|
||||
:::
|
||||
261
docs/en/guide/features/copyright.md
Normal file
261
docs/en/guide/features/copyright.md
Normal file
@ -0,0 +1,261 @@
|
||||
---
|
||||
title: Article Copyright
|
||||
icon: lucide:creative-commons
|
||||
createTime: 2025/10/08 10:52:49
|
||||
permalink: /en/guide/features/copyright/
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import VPCopyright from '@theme/VPCopyright.vue'
|
||||
</script>
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports adding **copyright** declarations for articles.
|
||||
|
||||
Articles typically originate from original works, reposts, translations, etc.
|
||||
Adding copyright information for different sources helps better protect intellectual property rights and avoid copyright disputes.
|
||||
|
||||
### Creative Commons
|
||||
|
||||
The theme natively supports copyright declarations using [Creative Commons](https://creativecommons.org/) licenses, including:
|
||||
|
||||
<style>
|
||||
.doc-cc-list [class^="vpi-license-"] {
|
||||
margin-left: 8px;
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
color: var(--vp-c-text-2);
|
||||
transition: color var(--vp-t-color);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="doc-cc-list">
|
||||
|
||||
- [CC0 1.0 Universal (CC0)](https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
<span class="vpi-license-zero" />
|
||||
- [Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" />
|
||||
- [Attribution-ShareAlike 4.0 International (CC-BY-SA-4.0)](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" /><span class="vpi-license-sa" />
|
||||
- [Attribution-NonCommercial 4.0 International (CC-BY-NC-4.0)](https://creativecommons.org/licenses/by-nc/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" /><span class="vpi-license-nc" />
|
||||
- [Attribution-NoDerivatives 4.0 International (CC-BY-ND-4.0)](https://creativecommons.org/licenses/by-nd/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" /><span class="vpi-license-nd" />
|
||||
- [Attribution-NonCommercial-ShareAlike 4.0 International (CC-BY-NC-SA-4.0)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" /><span class="vpi-license-nc" /><span class="vpi-license-sa" />
|
||||
- [Attribution-NonCommercial-NoDerivatives 4.0 International (CC-BY-NC-ND-4.0)](https://creativecommons.org/licenses/by-nc-nd/4.0/)
|
||||
<span class="vpi-license-cc" /><span class="vpi-license-by" /><span class="vpi-license-nc" /><span class="vpi-license-nd" />
|
||||
|
||||
</div>
|
||||
|
||||
You can select different licenses based on your requirements, or define custom licenses.
|
||||
|
||||
### Copyright Information
|
||||
|
||||
Copyright information includes:
|
||||
|
||||
- Copyright owner, copyright owner link
|
||||
- Copyright license, copyright license link
|
||||
- Original work link
|
||||
|
||||
This information is displayed at the bottom of articles.
|
||||
|
||||
::: tip It is recommended to enable the [Contributors](./contributors.md) feature when using this
|
||||
functionality. For original articles, the theme automatically uses the first contributor as the
|
||||
copyright owner. You can also manually specify the copyright owner in the article frontmatter.
|
||||
:::
|
||||
|
||||
## Global Configuration
|
||||
|
||||
You can declare the `CC-BY-4.0` license for all articles on your site with the following configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
copyright: 'CC-BY-4.0' // [!code hl]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can declare a custom copyright license for all articles on your site with the following configuration:
|
||||
|
||||
```ts :no-line-numbers title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
copyright: { // [!code hl:6]
|
||||
license: {
|
||||
name: 'MIT', // License name
|
||||
url: 'https://your-license-url' // License URL
|
||||
},
|
||||
author: {
|
||||
name: 'Your Name', // Copyright owner name
|
||||
url: 'https://your-author-url' // Copyright owner URL
|
||||
},
|
||||
creation: 'reprint' // Creation type
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**Configuration Type:**
|
||||
|
||||
```ts
|
||||
export type CopyrightLicense
|
||||
= | 'CC-BY-4.0'
|
||||
| 'CC-BY-SA-4.0'
|
||||
| 'CC-BY-NC-4.0'
|
||||
| 'CC-BY-NC-SA-4.0'
|
||||
| 'CC-BY-ND-4.0'
|
||||
| 'CC-BY-NC-ND-4.0'
|
||||
| 'CC0'
|
||||
| string
|
||||
|
||||
/**
|
||||
* - When set to `true`, defaults to `CC-BY-4.0`
|
||||
* - When set to `false`, copyright is hidden, but can be overridden in article frontmatter.copyright
|
||||
*/
|
||||
type CopyrightOptions = boolean | string | CopyrightLicense | {
|
||||
/**
|
||||
* Copyright license
|
||||
*/
|
||||
license?: CopyrightLicense | {
|
||||
name: CopyrightLicense | string
|
||||
url: string
|
||||
}
|
||||
/**
|
||||
* Copyright owner. If not configured, defaults to obtaining from git commit records
|
||||
*/
|
||||
author?: {
|
||||
name: string
|
||||
url?: string
|
||||
}
|
||||
/**
|
||||
* Creation type: original, translation, or repost
|
||||
* @default 'original'
|
||||
*/
|
||||
creation?: 'original' | 'translate' | 'reprint'
|
||||
}
|
||||
```
|
||||
|
||||
::: warning Global configuration only applies to original articles. For non-original articles,
|
||||
you should configure copyright information in the article frontmatter.
|
||||
:::
|
||||
|
||||
## Article Frontmatter Configuration
|
||||
|
||||
You can configure copyright information for individual articles in the article frontmatter to override global configuration:
|
||||
|
||||
```md
|
||||
---
|
||||
title: My Article
|
||||
copyright: CC-BY-4.0
|
||||
---
|
||||
```
|
||||
|
||||
**Configuration Type:**
|
||||
|
||||
```ts
|
||||
/**
|
||||
* When set to `false`, copyright is hidden
|
||||
* When set to `true`, defaults to the global copyright configuration
|
||||
*/
|
||||
export type CopyrightFrontmatter = boolean | string | CopyrightLicense | {
|
||||
/**
|
||||
* Copyright license
|
||||
*/
|
||||
license?: CopyrightLicense | { name: string, url: string }
|
||||
|
||||
/**
|
||||
* Copyright owner
|
||||
* - For original articles, defaults to the first contributor
|
||||
* - For non-original articles, the copyright owner must be declared
|
||||
*/
|
||||
author?: string | { name: string, url?: string }
|
||||
|
||||
/**
|
||||
* Article creation type: original, translation, or repost
|
||||
* @default 'original'
|
||||
*/
|
||||
creation?: 'original' | 'translate' | 'reprint'
|
||||
|
||||
/**
|
||||
* Original article URL. Must be declared for non-original works
|
||||
* @default ''
|
||||
*/
|
||||
source?: string
|
||||
}
|
||||
```
|
||||
|
||||
## Article Configuration Examples
|
||||
|
||||
### Original Article
|
||||
|
||||
```md
|
||||
---
|
||||
title: My Article
|
||||
copyright: CC-BY-4.0
|
||||
---
|
||||
```
|
||||
|
||||
<VPCopyright license="CC-BY-4.0" />
|
||||
|
||||
### Reposted Article
|
||||
|
||||
```md
|
||||
---
|
||||
title: Reposted Article
|
||||
copyright:
|
||||
creation: reprint
|
||||
license: CC-BY-4.0
|
||||
source: https://example.com/origin
|
||||
author:
|
||||
name: Reposter
|
||||
url: https://example.com/author
|
||||
---
|
||||
```
|
||||
|
||||
<VPCopyright
|
||||
license="CC-BY-4.0" source="https://example.com/origin" creation="reprint"
|
||||
:author="{name: 'Reposter', url: 'https://example.com/author'}"
|
||||
/>
|
||||
|
||||
### Translated Article
|
||||
|
||||
```md
|
||||
---
|
||||
title: Translated Article
|
||||
copyright:
|
||||
creation: translate
|
||||
license: CC-BY-4.0
|
||||
source: https://example.com/origin
|
||||
author:
|
||||
name: Original Author
|
||||
url: https://example.com/author
|
||||
---
|
||||
```
|
||||
|
||||
<VPCopyright
|
||||
license="CC-BY-4.0" source="https://example.com/origin" creation="translate"
|
||||
:author="{name: 'Original Author', url: 'https://example.com/author'}"
|
||||
/>
|
||||
|
||||
### Custom License
|
||||
|
||||
```md
|
||||
---
|
||||
title: My Article
|
||||
copyright:
|
||||
license:
|
||||
name: MIT
|
||||
url: https://example.com/mit
|
||||
---
|
||||
```
|
||||
|
||||
<VPCopyright :license="{name: 'MIT', url: 'https://example.com/mit'}" />
|
||||
167
docs/en/guide/features/encryption.md
Normal file
167
docs/en/guide/features/encryption.md
Normal file
@ -0,0 +1,167 @@
|
||||
---
|
||||
title: Encryption
|
||||
icon: mdi:encryption-outline
|
||||
createTime: 2025/10/08 15:58:48
|
||||
permalink: /en/guide/features/encryption/
|
||||
---
|
||||
|
||||
## Encryption
|
||||
|
||||
This theme supports multiple flexible encryption methods, including **full-site encryption** and **partial encryption**.
|
||||
|
||||
::: warning Note
|
||||
Due to the inherent limitations of `vuepress` as a static site generator,
|
||||
the **encryption** only makes content *appear* invisible and excludes the content from being pre-rendered
|
||||
into `html` during compilation. However, the content can still be accessed from the site's source files.
|
||||
|
||||
Therefore, the **encryption** feature should not be considered **secure and reliable**.
|
||||
|
||||
Avoid using the **encryption feature** for content that requires **strict confidentiality**.
|
||||
:::
|
||||
|
||||
**Unlocked articles are only visible within the current session.**
|
||||
|
||||
## Enabling Encryption
|
||||
|
||||
Add the `encrypt` option in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
encrypt: {
|
||||
// more options...
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Full-Site Encryption
|
||||
|
||||
In some cases, you may need to encrypt the entire site. Configure full-site encryption using the `encrypt.
|
||||
global` option, then set one or more passwords using the `encrypt.admin` option.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
encrypt: {
|
||||
global: true,
|
||||
admin: ['123456'],
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Partial Encryption
|
||||
|
||||
In most cases, you may only need to encrypt specific articles, directories, etc. Configure partial encryption using the `encrypt.rules` option.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
encrypt: {
|
||||
rules: {
|
||||
// Can be relative path to md file - encrypts this file
|
||||
'前端/基础.md': '123456',
|
||||
// Can be directory path - encrypts all articles under this directory
|
||||
'/notes/vuepress-theme-plume/': '123456',
|
||||
// Can be request path - encrypts all articles under this access path
|
||||
'/vuepress-theme-plume/': '123456',
|
||||
// Can be specific page request path - encrypts this page
|
||||
'/article/f8dnci3/': '123456',
|
||||
// If starting with `^`, pages matching this regex will also be encrypted
|
||||
'^/(a|b)/': '123456',
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
The **keys** in `encrypt.rules` serve as matching rules, and the **values** serve as passwords for those rules. You can set one or multiple passwords.
|
||||
|
||||
:::tip Notes
|
||||
|
||||
- Passwords must be plain strings.
|
||||
- If an entire directory is encrypted, unlocking applies to the entire directory, not individual articles within it.
|
||||
- `encrypt.admin` can also be used to unlock **partially encrypted** pages.
|
||||
- After unlocking with `encrypt.admin`, the user is considered an administrator and other locked pages are unlocked by default.
|
||||
:::
|
||||
|
||||
### Frontmatter
|
||||
|
||||
Use the `password` field in Markdown file `Frontmatter` to set article passwords.
|
||||
|
||||
```md
|
||||
---
|
||||
title: Encrypted Article
|
||||
password: 123456
|
||||
---
|
||||
```
|
||||
|
||||
You can also add the `passwordHint` option to set password hint information.
|
||||
|
||||
```md
|
||||
---
|
||||
title: Encrypted Article
|
||||
password: 123456
|
||||
passwordHint: The password is 123456
|
||||
---
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
Click to visit [Encrypted Article, Password: 123456](/article/enx7c9s/)
|
||||
|
||||
## Related Configuration
|
||||
|
||||
The following configurations support use in [multilingual configuration](../../config/locales.md).
|
||||
|
||||
### encryptGlobalText
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `'Only password can access this site'`
|
||||
- **Description**:
|
||||
|
||||
Prompt message for full-site encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords.
|
||||
|
||||
### encryptPageText
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `'Only password can access this page'`
|
||||
- **Description**:
|
||||
|
||||
Prompt message for partial encryption. Supports HTML. Useful if you want to provide contact information for visitors to obtain passwords.
|
||||
|
||||
### encryptButtonText
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `'Confirm'`
|
||||
- **Description**: Text for the confirmation button
|
||||
|
||||
### encryptPlaceholder
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `'Enter password'`
|
||||
- **Description**: Placeholder text for the password input field
|
||||
|
||||
### Example
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
locales: {
|
||||
'/': {
|
||||
encryptButtonText: 'Confirm',
|
||||
encryptPlaceholder: 'Enter password',
|
||||
encryptGlobalText: 'Only password can access this site',
|
||||
encryptPageText: 'Only password can access this page',
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
43
docs/en/guide/features/friend-links.md
Normal file
43
docs/en/guide/features/friend-links.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Friend Links Page
|
||||
icon: carbon:friendship
|
||||
createTime: 2025/10/08 22:44:28
|
||||
permalink: /en/guide/friend-links/
|
||||
---
|
||||
|
||||
## Friend Links
|
||||
|
||||
The friend links page is not automatically generated, but you can create it as needed.
|
||||
|
||||
Create any `*.md` file in your `{sourceDir}/` directory, such as `friends.md`. Then configure it using `frontmatter` in this file.
|
||||
|
||||
```md title="friends.md"
|
||||
---
|
||||
friends: true
|
||||
title: Friend Links
|
||||
description: Description text for friend links
|
||||
permalink: /friends/
|
||||
contentPosition: after
|
||||
list:
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: Even if slow, persist without stop; even if falling behind, even if failing, one must be able to reach the goal they are heading towards.
|
||||
-
|
||||
name: pengzhanbo
|
||||
link: https://github.com/pengzhanbo
|
||||
avatar: https://github.com/pengzhanbo.png
|
||||
desc: Even if slow, persist without stop; even if falling behind, even if failing, one must be able to reach the goal they are heading towards.
|
||||
---
|
||||
|
||||
Custom content <!-- Markdown content will be inserted into the friend links page -->
|
||||
```
|
||||
|
||||
The theme will generate the friend links page based on the configuration.
|
||||
|
||||
You need to manually configure the entry link for the friend links page in an appropriate location in the `navbar`.
|
||||
|
||||
### Configuration
|
||||
|
||||
View the [documentation](../../config/frontmatter/friend.md) for more configuration information.
|
||||
116
docs/en/guide/features/icon.md
Normal file
116
docs/en/guide/features/icon.md
Normal file
@ -0,0 +1,116 @@
|
||||
---
|
||||
title: Icons
|
||||
icon: raphael:smile2
|
||||
createTime: 2025/10/08 10:45:47
|
||||
permalink: /en/guide/features/icon/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The theme supports icons from the following sources:
|
||||
|
||||
- [iconify](https://iconify.design/) - Supported by default
|
||||
- [iconfont](https://www.iconfont.cn/) - Optional
|
||||
- [fontawesome](https://fontawesome.com/) - Optional
|
||||
|
||||
Icons are used in the same way across the following theme features:
|
||||
|
||||
- [Navbar Icons](../../config/navbar.md#configuration)
|
||||
- [Sidebar Icons](../../guide/document.md#sidebar-icons)
|
||||
- [File Tree Icons](../../guide/markdown/file-tree.md)
|
||||
- [Code Group Title Icons](../code/code-tabs.md#group-title-icons)
|
||||
|
||||
Provides syntax sugar and component support:
|
||||
|
||||
[Markdown Icon Syntax Sugar Support](../markdown/icons.md){.read-more}
|
||||
|
||||
[Icon Component Support](../components/icon.md){.read-more}
|
||||
|
||||
::: tip Theme Optimization for Icons
|
||||
The theme employs the same parsing strategy internally for all the different ways of using icons
|
||||
mentioned above. Even if you use the same icon in different locations, the same icon resources will not be loaded repeatedly.
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: { // [!code ++:3]
|
||||
icon: { provider: 'iconify' } // Supported by default
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### provider
|
||||
|
||||
- **Type**: `'iconify' | 'iconfont' | 'fontawesome'`
|
||||
- **Default**: `'iconify'`
|
||||
|
||||
Icon provider
|
||||
|
||||
### prefix
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `''` (Different icon providers have different default values)
|
||||
- **Details**:
|
||||
|
||||
Icon prefix
|
||||
|
||||
- When provider is `iconify`, defaults to `''`. Set the iconify collection as prefix, e.g., `mdi`.
|
||||
- When provider is `iconfont`, defaults to `'iconfont icon-'`
|
||||
- When provider is `fontawesome`, defaults to `'fas'`. Optional values are:
|
||||
|
||||
```ts
|
||||
type FontAwesomePrefix
|
||||
= | 'fas' | 's' // fa-solid fa-name
|
||||
| 'far' | 'r' // fa-regular fa-name
|
||||
| 'fal' | 'l' // fa-light fa-name
|
||||
| 'fat' | 't' // fa-thin fa-name
|
||||
| 'fads' | 'ds' // fa-duotone fa-solid fa-name
|
||||
| 'fass' | 'ss' // fa-sharp fa-solid fa-name
|
||||
| 'fasr' | 'sr' // fa-sharp fa-regular fa-name
|
||||
| 'fasl' | 'sl' // fa-sharp fa-light fa-name
|
||||
| 'fast' | 'st' // fa-sharp fa-thin fa-name
|
||||
| 'fasds' | 'sds' // fa-sharp-duotone fa-solid fa-name
|
||||
| 'fab' | 'b' // fa-brands fa-name
|
||||
```
|
||||
|
||||
### assets
|
||||
|
||||
- **Type**: `(string | FontAwesomeAssetBuiltin)[] | string | FontAwesomeAssetBuiltin`
|
||||
|
||||
```ts
|
||||
type FontAwesomeAssetBuiltin = 'fontawesome' | 'fontawesome-with-brands'
|
||||
```
|
||||
|
||||
- **Default**: `undefined`
|
||||
|
||||
- **Details**:
|
||||
|
||||
- For `iconify`: No configuration needed;
|
||||
- For `iconfont`: Set to the resource URL of iconfont;
|
||||
- For `fontawesome`: Set to the resource URL of fontawesome. Optional values are `fontawesome` or
|
||||
`fontawesome-with-brands`, or custom resource URLs.
|
||||
|
||||
### size
|
||||
|
||||
- **Type**: `string | number`
|
||||
- **Default**: `1em`
|
||||
- **Details**:
|
||||
|
||||
Default icon size
|
||||
|
||||
### color
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `'currentColor'`
|
||||
- **Details**:
|
||||
|
||||
Default icon color
|
||||
46
docs/en/guide/features/image-preview.md
Normal file
46
docs/en/guide/features/image-preview.md
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
title: Image Preview
|
||||
icon: ri:image-line
|
||||
createTime: 2025/10/08 20:46:17
|
||||
permalink: /en/guide/features/image-preview/
|
||||
---
|
||||
|
||||
In the theme, images support click-to-enlarge preview by default. A preview list is generated by scanning images within the document content.
|
||||
|
||||
This feature is powered by the [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/en/plugins/features/photo-swipe.html) plugin.
|
||||
|
||||
## Configuration
|
||||
|
||||
Image preview is enabled by default. The behavior can be modified through the following configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: {
|
||||
photoSwipe: {
|
||||
// Image selector
|
||||
selector: '.vp-doc :not(a) > img:not([no-view],.no-view,.ignore)',
|
||||
download: true, // Whether to show the download button
|
||||
fullscreen: true, // Whether to show the fullscreen button
|
||||
scrollToClose: true, // Whether to close the current image when scrolling
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
For more configuration options, please refer to [@vuepress/plugin-photo-swipe](https://ecosystem.vuejs.press/en/plugins/features/photo-swipe.html).
|
||||
|
||||
## Ignoring Image Preview
|
||||
|
||||
Image preview can be disabled by using the `no-view` or `ignore` class names, or the `no-view` attribute.
|
||||
|
||||
```md
|
||||
{.no-view}
|
||||
{.ignore}
|
||||
{no-view}
|
||||
|
||||
<img src="path/to/image" class="no-view">
|
||||
<img src="path/to/image" class="ignore">
|
||||
<img src="path/to/image" no-view>
|
||||
```
|
||||
268
docs/en/guide/features/replace-assets.md
Normal file
268
docs/en/guide/features/replace-assets.md
Normal file
@ -0,0 +1,268 @@
|
||||
---
|
||||
title: Replace Assets
|
||||
icon: lucide:replace
|
||||
createTime: 2025/10/08 11:45:17
|
||||
permalink: /en/guide/features/replace-assets/
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This feature is powered by the [@vuepress/plugin-replace-assets](https://ecosystem.vuejs.press/en/plugins/tools/replace-assets.html) plugin.
|
||||
|
||||
It replaces local asset links within the site, such as images, videos, audio, PDFs, and other resources, rewriting local asset paths to new addresses.
|
||||
|
||||
## Why is this feature needed?
|
||||
|
||||
Many users choose to store site assets on CDN services to accelerate site access and improve availability.
|
||||
|
||||
In this process, assets typically need to be uploaded to the CDN service first, then CDN links are obtained, and finally used in the site content.
|
||||
|
||||
This may seem straightforward, but in practice, it often requires repeatedly performing:
|
||||
|
||||
```txt
|
||||
Upload assets → Get asset links → Use full asset links in content
|
||||
```
|
||||
|
||||
During this process, content creation is frequently interrupted.
|
||||
|
||||
This feature aims to solve this problem. During content creation,
|
||||
you only need to use local asset paths directly, and the theme will handle the asset path replacement at the appropriate stage.
|
||||
|
||||
::: important This feature does not modify source files; replacements are only made in the compiled content.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
|
||||
The feature is disabled by default in the theme. You can enable it in the configuration:
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// ReplaceAssetsPluginOptions
|
||||
replaceAssets: 'https://cdn.example.com' // [!code ++]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
==It's recommended to enable asset path replacement only for production builds, using local asset paths directly during development=={.important}
|
||||
|
||||
```ts title=".vuepress/config.ts" twoslash
|
||||
import process from 'node:process'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production' // [!code ++]
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// Enable only in production environment
|
||||
replaceAssets: isProd ? 'https://cdn.example.com' : false // [!code ++]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Asset Management
|
||||
|
||||
**You should store assets in the [.vuepress/public](https://v2.vuepress.vuejs.org/guide/assets.html#public-files) directory**:
|
||||
|
||||
```sh
|
||||
./docs
|
||||
├── .vuepress
|
||||
│ └── public # [!code hl:6]
|
||||
│ ├── images
|
||||
│ │ ├── foo.jpg
|
||||
│ │ └── bar.jpg
|
||||
│ └── medias
|
||||
│ └── foo.mp4
|
||||
└── README.md
|
||||
```
|
||||
|
||||
::: tip Why store assets in this directory?
|
||||
When the site is compiled and ready for deployment, we can easily upload files from this directory directly to the CDN.
|
||||
:::
|
||||
|
||||
In markdown, use local asset paths directly:
|
||||
|
||||
```md
|
||||

|
||||
|
||||
<img src="/images/foo.jpg">
|
||||
```
|
||||
|
||||
In `javascript`:
|
||||
|
||||
```js
|
||||
const foo = '/images/foo.jpg'
|
||||
|
||||
const img = document.createElement('img')
|
||||
img.src = '/images/foo.jpg'
|
||||
```
|
||||
|
||||
And in style files:
|
||||
|
||||
```css
|
||||
.foo {
|
||||
background: url('/images/foo.jpg');
|
||||
}
|
||||
```
|
||||
|
||||
The plugin will correctly identify these assets and replace them in the compiled content.
|
||||
|
||||
:::warning The plugin does not support identifying concatenated paths like `'/images/' + 'foo.jpg'`.
|
||||
:::
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
```ts
|
||||
/**
|
||||
* Asset link replacement configuration
|
||||
*/
|
||||
type ReplaceAssetsPluginOptions
|
||||
= | Replacement
|
||||
| ReplacementRule
|
||||
| ReplacementRule[]
|
||||
| ReplaceAssetsOptions
|
||||
|
||||
/**
|
||||
* - `string`: Prepended to the original asset link
|
||||
* - `function`: Returns the replaced asset link
|
||||
*/
|
||||
type Replacement = string | ((url: string) => string)
|
||||
|
||||
interface ReplacementRule {
|
||||
/**
|
||||
* Match asset links
|
||||
*/
|
||||
find: RegExp | string
|
||||
/**
|
||||
* Asset link replacement
|
||||
*/
|
||||
replacement: Replacement
|
||||
}
|
||||
|
||||
interface ReplaceAssetsOptions {
|
||||
/**
|
||||
* Custom asset replacement rules
|
||||
*/
|
||||
rules?: ReplacementRule | ReplacementRule[]
|
||||
/**
|
||||
* Replacement for built-in asset matching rules
|
||||
*/
|
||||
all?: Replacement
|
||||
/**
|
||||
* Replacement for built-in image asset matching rules
|
||||
*/
|
||||
image?: Replacement
|
||||
/**
|
||||
* Replacement for built-in media asset matching rules
|
||||
*/
|
||||
media?: Replacement
|
||||
}
|
||||
```
|
||||
|
||||
## Built-in Asset Matching Rules
|
||||
|
||||
For convenience, the theme plugin provides built-in asset matching rules that you can use directly.
|
||||
|
||||
- `image`: Finds image assets, including local image resource links with formats `['apng','bmp','png','jpeg','jpg','jfif','pjpeg','pjp','gif','svg','ico','webp','avif','cur','jxl']`
|
||||
- `media`: Finds media assets, including local media resource links with formats `['mp4','webm','ogg','mp3','wav','flac','aac','opus','mov','m4a','vtt','pdf']`
|
||||
- `all`: Finds both image and media assets, combining both `image` and `media` rules
|
||||
|
||||
When directly passing a **asset link prefix** or **asset link replacement function**, the theme uses the `all` rule to replace asset links.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import process from 'node:process'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// replaceAssets: 'https://cdn.example.com' // [!code hl]
|
||||
replaceAssets: url => `https://cdn.example.com${url}` // [!code ++]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also apply different asset link prefixes or replacement functions to different built-in rules:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import process from 'node:process'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// replaceAssets: { // [!code hl:4]
|
||||
// image: 'https://image.cdn.com/',
|
||||
// media: 'https://media.cdn.com/'
|
||||
// },
|
||||
replaceAssets: { // [!code ++:4]
|
||||
image: url => `https://image.cdn.com${url}`,
|
||||
media: url => `https://media.cdn.com${url}`
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Custom Asset Matching Rules
|
||||
|
||||
You can also define custom asset matching rules:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import process from 'node:process'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
replaceAssets: { // [!code ++:4]
|
||||
find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/,
|
||||
replacement: url => `https://image.cdn.com${url}`
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also define multiple matching rules:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import process from 'node:process'
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
replaceAssets: [ // [!code ++:12]
|
||||
// Find image assets
|
||||
{
|
||||
find: /^\/images\/.*\.(jpg|jpeg|png|gif|svg|webp|avif)$/,
|
||||
replacement: 'https://image.cdn.com'
|
||||
},
|
||||
// Find media assets
|
||||
{
|
||||
find: /^\/medias\/.*\.(mp4|webm|ogg|mp3|wav|flac|aac|m3u8|m3u|flv|pdf)$/,
|
||||
replacement: url => `https://media.cdn.com${url}`
|
||||
},
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**`find` Field Explanation**
|
||||
|
||||
The `find` field is used to match asset links and can be a **regular expression** or **string**.
|
||||
|
||||
When a `string` is provided, if it starts with `^` or ends with `$`, it will be automatically converted to a **regular expression**.
|
||||
Otherwise, it will check if the asset link ends with `find` or starts with `find`.
|
||||
|
||||
```txt
|
||||
'^/images/foo.jpg' -> /^\/images\/foo.jpg/
|
||||
'/images/foo.jpg$' -> /^\/images\/foo.jpg$/
|
||||
```
|
||||
|
||||
::: important All matched asset paths start with `/`.
|
||||
:::
|
||||
234
docs/en/guide/features/search.md
Normal file
234
docs/en/guide/features/search.md
Normal file
@ -0,0 +1,234 @@
|
||||
---
|
||||
title: Content Search
|
||||
icon: material-symbols:search
|
||||
createTime: 2025/10/08 09:58:39
|
||||
permalink: /en/guide/features/content-search/
|
||||
---
|
||||
|
||||
The theme provides two approaches for content search:
|
||||
|
||||
- Local Content Search
|
||||
- Algolia DocSearch
|
||||
|
||||
Note: Do not configure both approaches simultaneously. When both are configured, only Local Content Search will take effect.
|
||||
|
||||
## Local Content Search
|
||||
|
||||
Local Content Search is powered by the
|
||||
[@vuepress-plume/plugin-search](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/plugins/plugin-search) plugin.
|
||||
|
||||
This plugin uses [minisearch](https://github.com/lucaong/minisearch) for content searching.
|
||||
|
||||
### Enabling
|
||||
|
||||
The theme enables Local Content Search by default. You can also customize its configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
search: { // [!code ++:4]
|
||||
provider: 'local',
|
||||
// more options
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
This plugin generates search indexes locally based on your pages, then loads the search index files when users visit your site.
|
||||
In other words, this is a lightweight built-in search capability that doesn't make any external requests.
|
||||
|
||||
However, when your site contains a large number of pages, the search index file can become very large and may slow down your page loading speed.
|
||||
In such cases, we recommend using a more robust solution - [Algolia DocSearch](#algolia-docsearch).
|
||||
|
||||
## Algolia DocSearch
|
||||
|
||||
Site content search powered by [Algolia DocSearch](https://docsearch.algolia.com/).
|
||||
|
||||
### Enabling
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
search: { // [!code ++:4]
|
||||
provider: 'algolia',
|
||||
// more options
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Obtaining Search Index
|
||||
|
||||
You need to [submit your website URL](https://docsearch.algolia.com/apply/) to join the DocSearch program.
|
||||
When your index is successfully created, the DocSearch team will send `apiKey` and `indexName` to your email.
|
||||
You can then configure the plugin to enable DocSearch in VuePress.
|
||||
|
||||
Alternatively, you can [run your own crawler](https://docsearch.algolia.com/docs/run-your-own/) to create the index,
|
||||
then use your own `appId`, `apiKey`, and `indexName` to configure the plugin.
|
||||
|
||||
Here's a crawler configuration example used by this theme. You can visit [Algolia Crawler](https://crawler.algolia.com/admin/crawlers/)
|
||||
and modify it according to your needs:
|
||||
|
||||
```ts
|
||||
new Crawler({
|
||||
appId: 'YOUR_APP_ID', // [!code highlight]
|
||||
apiKey: 'YOUR_API_KEY', // [!code highlight]
|
||||
rateLimit: 8,
|
||||
startUrls: [
|
||||
// These are the initial URLs where Algolia starts crawling your site
|
||||
// If your site is divided into several independent sections, you may need to set multiple entry links here
|
||||
'https://YOUR_WEBSITE_URL/', // [!code highlight]
|
||||
],
|
||||
renderJavaScript: false,
|
||||
sitemaps: [
|
||||
// The theme generates sitemap by default; replace with your domain link here
|
||||
'https://YOUR_WEBSITE_URL/sitemap.xml', // [!code highlight]
|
||||
],
|
||||
ignoreCanonicalTo: true,
|
||||
discoveryPatterns: [
|
||||
// This defines the scope of URLs that Algolia will crawl
|
||||
'https://YOUR_WEBSITE_URL/**', // [!code highlight]
|
||||
],
|
||||
// Crawler execution schedule; set according to your documentation update frequency
|
||||
schedule: 'at 02:00 every 1 day',
|
||||
actions: [
|
||||
// You can have multiple actions, especially when deploying multiple documentations under one domain
|
||||
{
|
||||
// Name your index appropriately
|
||||
indexName: 'YOUR_INDEX_NAME', // [!code highlight]
|
||||
// Paths where the index takes effect
|
||||
pathsToMatch: ['https://YOUR_WEBSITE_URL/**'], // [!code highlight]
|
||||
recordExtractor: ({ helpers }) => {
|
||||
// Options for vuepress-theme-plume
|
||||
return helpers.docsearch({
|
||||
recordProps: { // [!code highlight]
|
||||
lvl1: '.plume-content h1', // [!code highlight]
|
||||
content: '.plume-content p, .plume-content li', // [!code highlight]
|
||||
lvl0: { // [!code highlight]
|
||||
selectors: [ // [!code highlight]
|
||||
'.sidebar-item.is-active p', // [!code highlight]
|
||||
'.content-container .page-title', // [!code highlight]
|
||||
], // [!code highlight]
|
||||
defaultValue: 'Documentation', // [!code highlight]
|
||||
}, // [!code highlight]
|
||||
lvl2: '.plume-content h2', // [!code highlight]
|
||||
lvl3: '.plume-content h3', // [!code highlight]
|
||||
lvl4: '.plume-content h4', // [!code highlight]
|
||||
lvl5: '.plume-content h5', // [!code highlight]
|
||||
}, // [!code highlight]
|
||||
indexHeadings: true, // [!code highlight]
|
||||
aggregateContent: true, // [!code highlight]
|
||||
recordVersion: 'v3', // [!code highlight]
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
initialIndexSettings: {
|
||||
// Controls how the index is initialized; only effective when the index hasn't been generated yet
|
||||
// You may need to manually delete and regenerate the index after modifications
|
||||
YOUR_INDEX_NAME: { // [!code highlight]
|
||||
attributesForFaceting: ['type', 'lang'], // [!code highlight]
|
||||
attributesToRetrieve: [
|
||||
'hierarchy',
|
||||
'content',
|
||||
'anchor',
|
||||
'url',
|
||||
'url_without_anchor',
|
||||
'type',
|
||||
],
|
||||
attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
|
||||
attributesToSnippet: ['content:10'],
|
||||
camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
|
||||
searchableAttributes: [
|
||||
'unordered(hierarchy_radio_camel.lvl0)',
|
||||
'unordered(hierarchy_radio.lvl0)',
|
||||
'unordered(hierarchy_radio_camel.lvl1)',
|
||||
'unordered(hierarchy_radio.lvl1)',
|
||||
'unordered(hierarchy_radio_camel.lvl2)',
|
||||
'unordered(hierarchy_radio.lvl2)',
|
||||
'unordered(hierarchy_radio_camel.lvl3)',
|
||||
'unordered(hierarchy_radio.lvl3)',
|
||||
'unordered(hierarchy_radio_camel.lvl4)',
|
||||
'unordered(hierarchy_radio.lvl4)',
|
||||
'unordered(hierarchy_radio_camel.lvl5)',
|
||||
'unordered(hierarchy_radio.lvl5)',
|
||||
'unordered(hierarchy_radio_camel.lvl6)',
|
||||
'unordered(hierarchy_radio.lvl6)',
|
||||
'unordered(hierarchy_camel.lvl0)',
|
||||
'unordered(hierarchy.lvl0)',
|
||||
'unordered(hierarchy_camel.lvl1)',
|
||||
'unordered(hierarchy.lvl1)',
|
||||
'unordered(hierarchy_camel.lvl2)',
|
||||
'unordered(hierarchy.lvl2)',
|
||||
'unordered(hierarchy_camel.lvl3)',
|
||||
'unordered(hierarchy.lvl3)',
|
||||
'unordered(hierarchy_camel.lvl4)',
|
||||
'unordered(hierarchy.lvl4)',
|
||||
'unordered(hierarchy_camel.lvl5)',
|
||||
'unordered(hierarchy.lvl5)',
|
||||
'unordered(hierarchy_camel.lvl6)',
|
||||
'unordered(hierarchy.lvl6)',
|
||||
'content',
|
||||
],
|
||||
distinct: true,
|
||||
attributeForDistinct: 'url',
|
||||
customRanking: [
|
||||
'desc(weight.pageRank)',
|
||||
'desc(weight.level)',
|
||||
'asc(weight.position)',
|
||||
],
|
||||
ranking: [
|
||||
'words',
|
||||
'filters',
|
||||
'typo',
|
||||
'attribute',
|
||||
'proximity',
|
||||
'exact',
|
||||
'custom',
|
||||
],
|
||||
highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
|
||||
highlightPostTag: '</span>',
|
||||
minWordSizefor1Typo: 3,
|
||||
minWordSizefor2Typos: 7,
|
||||
allowTyposOnNumericTokens: false,
|
||||
minProximity: 1,
|
||||
ignorePlurals: true,
|
||||
advancedSyntax: true,
|
||||
attributeCriteriaComputedByMinProximity: true,
|
||||
removeWordsIfNoResults: 'allOptional',
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
The `recordProps` section contains configuration options used by this theme for index crawling.
|
||||
|
||||
### Configuration Options
|
||||
|
||||
For complete configuration, please refer to the [documentation](https://ecosystem.vuejs.press/en/plugins/search/docsearch.html).
|
||||
|
||||
### Configuration Example
|
||||
|
||||
Here's the configuration used by this theme:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
search: { // [!code ++:6]
|
||||
provider: 'algolia',
|
||||
appId: 'YOUR_APP_ID',
|
||||
apiKey: 'YOUR_API_KEY',
|
||||
indexName: 'YOUR_INDEX_NAME',
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
111
docs/en/guide/features/seo.md
Normal file
111
docs/en/guide/features/seo.md
Normal file
@ -0,0 +1,111 @@
|
||||
---
|
||||
title: SEO
|
||||
icon: tabler:seo
|
||||
createTime: 2025/10/08 14:46:25
|
||||
permalink: /en/guide/seo/
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
The theme provides out-of-the-box configuration to enable SEO optimization features for your site.
|
||||
To enable it, configure the following:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
hostname: 'http://your_site_url',
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
For custom SEO optimization, you can configure it through `plugins.seo`:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: {
|
||||
seo: {
|
||||
// ... SEO configuration
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
For complete configuration options, please refer to the [documentation](https://ecosystem.vuejs.press/en/plugins/seo/seo/config.html).
|
||||
|
||||
::: note
|
||||
This example is forked from [@vuepress/plugin-seo](https://ecosystem.vuejs.press/en/plugins/seo/seo/),
|
||||
licensed under [MIT](https://github.com/vuepress/ecosystem/blob/main/LICENSE).
|
||||
:::
|
||||
|
||||
## Guide
|
||||
|
||||
The theme enhances your site's search engine optimization by injecting tags into the website's `<head>` section,
|
||||
making it fully compliant with the [Open Graph Protocol (OGP)](https://ogp.me/)
|
||||
and [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/).
|
||||
|
||||
By default, the plugin reads site configuration, theme configuration, and page frontmatter to automatically generate
|
||||
metadata. Elements such as site name, page title, page type, writing date, last update date, and article tags are automatically generated.
|
||||
|
||||
## Default OGP Generation Logic
|
||||
|
||||
| Property Name | Value |
|
||||
| :------------ | :---- |
|
||||
| `og:url` | `options.hostname` + `path` |
|
||||
| `og:site_name` | `siteConfig.title` |
|
||||
| `og:title` | `page.title` |
|
||||
| `og:description` | `page.frontmatter.description` \|\| auto-generated (when `autoDescription` is `true` in plugin options) |
|
||||
| `og:type` | `"article"` |
|
||||
| `og:image` | `options.hostname` + `page.frontmatter.image` \|\| first image in page \|\| `fallbackImage` from plugin options |
|
||||
| `og:updated_time` | `page.git.updatedTime` |
|
||||
| `og:locale` | `page.lang` |
|
||||
| `og:locale:alternate` | Other languages included in `siteData.locales` |
|
||||
| `twitter:card` | `"summary_large_image"` (only when image is found) |
|
||||
| `twitter:image:alt` | `page.title` (only when image is found) |
|
||||
| `article:author` | `page.frontmatter.author` \|\| `options.author` |
|
||||
| `article:tag` | `page.frontmatter.tags` \|\| `page.frontmatter.tag` |
|
||||
| `article:published_time` | `page.frontmatter.date` \|\| `page.git.createdTime` |
|
||||
| `article:modified_time` | `page.git.updatedTime` |
|
||||
|
||||
## Default JSON-LD Generation Logic
|
||||
|
||||
| Property Name | Value |
|
||||
| :------------ | :---- |
|
||||
| `@context` | `"https://schema.org"` |
|
||||
| `@type` | `"NewsArticle"` |
|
||||
| `headline` | `page.title` |
|
||||
| `image` | Images in page \|\| `options.hostname` + `page.frontmatter.image` |
|
||||
| `datePublished` | `page.frontmatter.date` \|\| `page.git.createdTime` |
|
||||
| `dateModified` | `page.git.updatedTime` |
|
||||
| `author` | `page.frontmatter.author` \|\| `options.author` |
|
||||
|
||||
## SEO Introduction
|
||||
|
||||
Search Engine Optimization (SEO) is a method of adjusting websites by understanding search engine operation rules
|
||||
to improve a target website's ranking in search engines. Since many studies have found that search engine users
|
||||
often only pay attention to the top few entries in search results, many websites hope to influence search engine
|
||||
rankings through various methods to achieve excellent search rankings for their sites.
|
||||
|
||||
The so-called "optimization for search engines" refers to making websites more easily accepted by search engines.
|
||||
Search engines compare the content between websites for relevance, and then browsers present this content to searchers
|
||||
in the fastest and most complete way possible. Search engine optimization follows search engine rules to create better
|
||||
user experiences, with the ultimate goal of providing excellent user experience.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Open Graph Protocol (OGP)](https://ogp.me/)
|
||||
|
||||
This plugin fully supports this protocol and automatically generates compliant `<meta>` tags.
|
||||
|
||||
- [JSON-LD 1.1](https://www.w3.org/TR/json-ld-api/)
|
||||
|
||||
This plugin generates NewsArticle type tags for article pages.
|
||||
|
||||
- [RDFa 1.1](https://www.w3.org/TR/rdfa-primer/)
|
||||
|
||||
RDFa primarily marks up HTML structure.
|
||||
|
||||
- [Schema.Org](https://schema.org/)
|
||||
|
||||
Schema definitions for structured markup sites.
|
||||
35
docs/en/guide/features/sitemap.md
Normal file
35
docs/en/guide/features/sitemap.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: sitemap
|
||||
icon: mdi:sitemap-outline
|
||||
createTime: 2025/10/08 16:47:00
|
||||
permalink: /en/guide/sitemap/
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
The theme provides out-of-the-box configuration to generate a `sitemap.xml` file for the site.
|
||||
To enable it, the following configuration is required:
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
hostname: 'http://your_site_url',
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
If customization of the sitemap is needed, it can be achieved through the `plugins.sitemap` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
plugins: {
|
||||
sitemap: {
|
||||
// ... sitemap configurations
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
Refer to the [documentation](https://ecosystem.vuejs.press/zh/plugins/seo/sitemap/config.html) for the complete configuration.
|
||||
194
docs/en/guide/features/watermark.md
Normal file
194
docs/en/guide/features/watermark.md
Normal file
@ -0,0 +1,194 @@
|
||||
---
|
||||
title: Article Watermark
|
||||
icon: material-symbols-light:branding-watermark-outline
|
||||
createTime: 2025/10/08 20:14:57
|
||||
permalink: /en/guide/features/watermark/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Article watermarking is powered by [@vuepress/plugin-watermark](https://ecosystem.vuejs.press/zh/plugins/features/watermark.html).
|
||||
|
||||
The theme supports adding watermarks to articles. Both full-page watermarks and content-area watermarks
|
||||
are supported, along with image watermarks and text watermarks.
|
||||
|
||||
## Enabling Watermark
|
||||
|
||||
Watermark functionality is disabled by default in the theme. You need to enable it in the theme configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
// watermark: true,
|
||||
watermark: {
|
||||
// enabled: false, // boolean type to control global enablement
|
||||
enabled: page => true, // function type to filter which pages enable watermark
|
||||
delay: 500, // Delay for adding watermark. In milliseconds.
|
||||
|
||||
/**
|
||||
* Whether to use full-page watermark, defaults to `true`.
|
||||
* When set to `false`, the watermark is only displayed in the content area.
|
||||
*/
|
||||
fullPage: true,
|
||||
|
||||
/** @see https://zhensherlock.github.io/watermark-js-plus/zh/config/ */
|
||||
watermarkOptions: {
|
||||
content: 'your watermark',
|
||||
// ...
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Global Enablement
|
||||
|
||||
When `plugins.watermark` is set to `true`, the theme enables watermark globally.
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
watermark: true,
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Partial Page Enablement
|
||||
|
||||
The theme provides two methods to control watermark enablement on specific pages.
|
||||
|
||||
#### watermark.enabled
|
||||
|
||||
```ts
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
watermark: {
|
||||
// Pages returning true will enable watermark, others will disable it
|
||||
enabled: page => page.path.includes('/article/'),
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
#### frontmatter.watermark
|
||||
|
||||
Add `frontmatter.watermark` as `true` in the md file:
|
||||
|
||||
```md
|
||||
---
|
||||
watermark: true
|
||||
---
|
||||
```
|
||||
|
||||
You can also customize the watermark configuration for the current page:
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
content: My Custom Content
|
||||
globalAlpha: 0.2
|
||||
rotate: 45
|
||||
---
|
||||
```
|
||||
|
||||
## Image Watermark
|
||||
|
||||
The theme supports using images as watermarks.
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
watermark: {
|
||||
watermarkOptions: {
|
||||
contentType: 'image',
|
||||
image: '/images/watermark.png',
|
||||
width: 200,
|
||||
height: 200,
|
||||
imageWidth: 100,
|
||||
imageHeight: 100,
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also add configuration in the md file to set watermark for the current page:
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
contentType: image
|
||||
image: /images/watermark.png
|
||||
width: 200
|
||||
height: 200
|
||||
imageWidth: 100
|
||||
imageHeight: 100
|
||||
---
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
[Image Watermark](/article/i4cuuonn/)
|
||||
|
||||
## Text Watermark
|
||||
|
||||
The theme supports using text as watermarks.
|
||||
|
||||
```ts
|
||||
import { defineUserConfig } from 'vuepress'
|
||||
import { plumeTheme } from 'vuepress-theme-plume'
|
||||
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
watermark: {
|
||||
watermarkOptions: {
|
||||
content: 'Custom Text',
|
||||
fontColor: '#fff', // Text color
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
You can also add configuration in the md file to set watermark for the current page:
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
content: Custom Text
|
||||
fontColor: #fff
|
||||
---
|
||||
```
|
||||
|
||||
## Frontmatter
|
||||
|
||||
The theme supports adding `frontmatter.watermark` in md files to set watermarks for individual pages.
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
content: My Custom Content
|
||||
---
|
||||
```
|
||||
|
||||
For supported configuration options, please refer to: [watermark-js-plus](https://zhensherlock.github.io/watermark-js-plus/zh/config/)
|
||||
|
||||
Additionally, `fullPage` is supported to control whether to display the watermark full-screen.
|
||||
|
||||
```md
|
||||
---
|
||||
watermark:
|
||||
fullPage: false
|
||||
---
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
- [Content Watermark](/article/2z59hh8g/)
|
||||
- [Full-page Watermark](/article/97s6ha1e/)
|
||||
@ -1,19 +1,19 @@
|
||||
---
|
||||
title: Abbreviation
|
||||
title: Abbreviations
|
||||
icon: mdi:tooltip-question-outline
|
||||
createTime: 2025/03/24 17:07:33
|
||||
createTime: 2025/10/08 10:48:15
|
||||
permalink: /en/guide/markdown/abbreviation/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Abbreviations** refer to short forms used in Markdown, such as technical terms like W3C and ECMA.
|
||||
**Abbreviations** refer to acronyms used in Markdown, such as professional terms like W3C, ECMA, etc.
|
||||
|
||||
When hovering over an abbreviation, the full term will be displayed along with its definition or explanation.
|
||||
When hovering over an abbreviation, the full name of the term is displayed, and it can also include the definition and explanation of the abbreviation.
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is disabled by default. Enable it in `theme` configuration:
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
@ -27,11 +27,12 @@ export default defineUserConfig({
|
||||
|
||||
## Syntax
|
||||
|
||||
In Markdown, define abbreviations using `*[ABBR]: Description` on separate lines. The description may include the abbreviation's definition, explanation, etc.
|
||||
In Markdown, use `*[Abbreviation]: Description` on a separate line to define an abbreviation.
|
||||
The description can include the definition, explanation, etc., of the abbreviation.
|
||||
|
||||
Place the abbreviation within `[]` and its description after `:`. The description supports Markdown inline syntax.
|
||||
Fill in the abbreviation within `[]`, and write the description after `:`. Markdown inline syntax can be used in the description.
|
||||
|
||||
If the Markdown plain text contains defined abbreviations, the explanation of the abbreviation will be automatically displayed when the mouse moves over it.
|
||||
If defined abbreviations appear in regular Markdown text, hovering over them will automatically display the abbreviation's explanation.
|
||||
|
||||
**Input:**
|
||||
|
||||
@ -50,5 +51,6 @@ The HTML specification is maintained by the W3C.
|
||||
*[W3C]: World Wide Web Consortium
|
||||
*[ECMA]: European Computer Manufacturers Association
|
||||
|
||||
::: warning Abbreviations should be standalone words or phrases. For Chinese abbreviations, add spaces around the term to ensure proper detection.
|
||||
::: warning
|
||||
Abbreviations should be independent words or phrases. For Chinese abbreviations, add spaces on both sides of the word to distinguish them.
|
||||
:::
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
---
|
||||
title: Annotation
|
||||
icon: iconamoon:comment-add-light
|
||||
createTime: 2025/03/24 17:19:13
|
||||
createTime: 2025/10/08 10:48:35
|
||||
permalink: /en/guide/markdown/annotation/
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
==Annotation== is a special Markdown syntax for adding extra information, explanations, or hints in documents.
|
||||
==Annotation== is a special syntax in Markdown used to add extra information, explanations, or hints to a document.
|
||||
|
||||
Annotations are not displayed directly in the document and require user interaction to be shown.
|
||||
Annotations are not directly displayed in the document; they require the user to manually click to be revealed.
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is not enabled by default. You need to enable it in the `theme` configuration.
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
@ -27,120 +27,128 @@ export default defineUserConfig({
|
||||
|
||||
## Syntax
|
||||
|
||||
==Annotation== syntax consists of two parts:
|
||||
The ==Annotation== syntax consists of two parts:
|
||||
|
||||
### Inline Annotation
|
||||
|
||||
Insert an annotation tag inline using the `[+label]` syntax.
|
||||
Insert an annotation marker inline using the `[+label]` syntax.
|
||||
|
||||
The annotation tag is composed of `[+` + `label` + `]`. To distinguish it from the content, there should be a space before `[+label]`.
|
||||
The annotation marker is composed of `[+` + `label` + `]`.
|
||||
To distinguish it clearly from the surrounding content, a space should be present at the left edge of `[+label]`.
|
||||
|
||||
`label` is the annotation tag and can be any string.
|
||||
`label` is the tag for the annotation and can be any string.
|
||||
|
||||
::: important The symbol `+` is required
|
||||
::: important The `+` symbol is required.
|
||||
:::
|
||||
|
||||
### Define Annotation
|
||||
### Defining Annotations
|
||||
|
||||
Define the annotation in a separate area of the document using the `[+label]:` syntax.
|
||||
Define annotations in a separate area of the document using the `[+label]:` syntax.
|
||||
|
||||
The annotation definition area is composed of `[+` + `label` + `]:` + `content`.
|
||||
The annotation definition area is composed of `[+` + `label` + `]:` + `Content`.
|
||||
|
||||
`label` should match the `[+label]` used earlier to mark the annotation.
|
||||
`label` should match the `[+label]` mentioned above and is used to identify the annotation tag.
|
||||
|
||||
**Content** can be written after the `:`:
|
||||
**Content** can be written directly after the `:`:
|
||||
|
||||
```md
|
||||
[+label]: Here is the content, which can use **Markdown** syntax.
|
||||
[+label]: This is the content. **Markdown** syntax can be used here.
|
||||
```
|
||||
|
||||
**Content** can also start on the next line with indentation, and should maintain consistent indentation for multiple lines.
|
||||
**Content** can also start on the next line, but it must be indented. Consistent indentation should be maintained for multiple lines.
|
||||
|
||||
```md
|
||||
[+label]:
|
||||
Here is the content.
|
||||
Indent consistently, this line is also part of the content.
|
||||
This is the content.
|
||||
The indentation is consistent, so this line is also part of the content.
|
||||
|
||||
Even if the previous line is blank, but this line's indentation is consistent, it is still part of the content.
|
||||
You can use **Markdown** syntax.
|
||||
Even with a blank line above, this line is still consistently indented, so it is also content.
|
||||
**Markdown** syntax can be used.
|
||||
|
||||
This line is no longer indented, so the annotation definition for this tag ends on the previous line.
|
||||
This line is no longer indented, so the annotation definition for this tag ended on the previous line.
|
||||
```
|
||||
|
||||
The content of the annotation definition is not rendered directly in the document, but is displayed when the `[+label]` inline annotation is clicked.
|
||||
The content of the annotation definition is not rendered directly in the document.
|
||||
It is presented only when the inline `[+label]` marker is clicked.
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
### Example 1
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
The site is powered by VuePress [+vuepress].
|
||||
This site is powered by VuePress [+vuepress].
|
||||
|
||||
[+vuepress]:
|
||||
VuePress is a [static site generator](https://en.wikipedia.org/wiki/Static_site_generator ) (SSG).
|
||||
Designed specifically for building fast, content-focused websites.
|
||||
VuePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG).
|
||||
It is specifically designed for building fast, content-centric sites.
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
The site is powered by VuePress [+vuepress].
|
||||
This site is powered by VuePress [+vuepress].
|
||||
|
||||
[+vuepress]:
|
||||
VuePress is a [static site generator](https://en.wikipedia.org/wiki/Static_site_generator ) (SSG).
|
||||
Designed specifically for building fast, content-focused websites.
|
||||
VuePress is a [Static Site Generator](https://en.wikipedia.org/wiki/Static_site_generator) (SSG).
|
||||
It is specifically designed for building fast, content-centric sites.
|
||||
|
||||
### Example 2
|
||||
|
||||
**Multiple annotations for the same `label`, rendered as a list.**
|
||||
**Multiple annotations defined with the same `label` are rendered as a list.**
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
The Four Great Classical Novels of ancient China [+classics] are widely known.
|
||||
The ancient Chinese **Four Great Classical Novels** [+novels] are household names.
|
||||
|
||||
[+classics]:
|
||||
**Romance of the Three Kingdoms:**
|
||||
[+novels]:
|
||||
**"Romance of the Three Kingdoms":**
|
||||
|
||||
Set against the history of the Three Kingdoms period, it depicts the political and military struggles among the Wei, Shu, and Wu kingdoms, creating numerous historical figures like Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
|
||||
Set against the backdrop of the Three Kingdoms period in Chinese history, it depicts the political and military struggles between the states of Wei, Shu, and Wu, shaping the images of numerous historical figures such as Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
|
||||
|
||||
[+classics]:
|
||||
**Journey to the West:**
|
||||
[+novels]:
|
||||
**"Journey to the West":**
|
||||
|
||||
Tells the story of Tang僧 and his four disciples (Sun Wukong, Zhu Bajie, Sha僧, and White Dragon Horse) on their pilgrimage to the West for Buddhist scriptures, filled with mythological elements and fantastic adventures.
|
||||
Tells the story of the monk Xuanzang and his three disciples (Sun Wukong, Zhu Bajie, Sha Wujing, and the White Dragon Horse) on their journey to the West to obtain sacred Buddhist texts, filled with mythological elements and fantastical adventures.
|
||||
|
||||
[+classics]:
|
||||
**Dream of the Red Chamber:**
|
||||
[+novels]:
|
||||
**"Dream of the Red Chamber":**
|
||||
|
||||
Set against the rise and fall of the four major families (Jia, Shi, Wang, and Xue), it depicts the love tragedy of Jia Baoyu, Lin Daiyu, and Xue Baochai, showcasing the decadence and decline of feudal society.
|
||||
Set against the backdrop of the decline of the four major families Jia, Shi, Wang, and Xue, it depicts the love tragedy between Jia Baoyu, Lin Daiyu, and Xue Baochai, revealing the corruption and decay of feudal society.
|
||||
|
||||
[+classics]:
|
||||
**Water Margin:**
|
||||
[+novels]:
|
||||
**"Water Margin":**
|
||||
|
||||
Depicts the story of 108 heroes led by Song Jiang gathering at Liangshan泊 to resist the court during the late Northern Song Dynasty, revealing the social reality of oppression leading to rebellion.
|
||||
Depicts the story of 108 outlaws, led by Song Jiang, who gather at Liangshan Marsh during the late Northern Song Dynasty to rebel against the imperial government, showcasing the social reality of oppression leading to rebellion.
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
The Four Great Classical Novels of ancient China [+classics] are widely known.
|
||||
The ancient Chinese **Four Great Classical Novels** [+novels] are household names.
|
||||
|
||||
[+classics]:
|
||||
**Romance of the Three Kingdoms:**
|
||||
[+novels]:
|
||||
**"Romance of the Three Kingdoms":**
|
||||
|
||||
Set against the history of the Three Kingdoms period, it depicts the political and military struggles among the Wei, Shu, and Wu kingdoms, creating numerous historical figures like Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
|
||||
Set against the backdrop of the Three Kingdoms period in Chinese history,
|
||||
it depicts the political and military struggles between the states of Wei, Shu, and Wu,
|
||||
shaping the images of numerous historical figures such as Zhuge Liang, Cao Cao, Guan Yu, and Liu Bei.
|
||||
|
||||
[+classics]:
|
||||
**Journey to the West:**
|
||||
[+novels]:
|
||||
**"Journey to the West":**
|
||||
|
||||
Tells the story of Tang僧 and his four disciples (Sun Wukong, Zhu Bajie, Sha僧, and White Dragon Horse) on their pilgrimage to the West for Buddhist scriptures, filled with mythological elements and fantastic adventures.
|
||||
Tells the story of the monk Xuanzang and his three disciples (Sun Wukong, Zhu Bajie, Sha Wujing,
|
||||
and the White Dragon Horse) on their journey to the West to obtain sacred Buddhist texts,
|
||||
filled with mythological elements and fantastical adventures.
|
||||
|
||||
[+classics]:
|
||||
**Dream of the Red Chamber:**
|
||||
[+novels]:
|
||||
**"Dream of the Red Chamber":**
|
||||
|
||||
Set against the rise and fall of the four major families (Jia, Shi, Wang, and Xue), it depicts the love tragedy of Jia Baoyu, Lin Daiyu, and Xue Baochai, showcasing the decadence and decline of feudal society.
|
||||
Set against the backdrop of the decline of the four major families Jia, Shi, Wang, and Xue,
|
||||
it depicts the love tragedy between Jia Baoyu, Lin Daiyu, and Xue Baochai, revealing the corruption and decay of feudal society.
|
||||
|
||||
[+classics]:
|
||||
**Water Margin:**
|
||||
[+novels]:
|
||||
**"Water Margin":**
|
||||
|
||||
Depicts the story of 108 heroes led by Song Jiang gathering at Liangshan泊 to resist the court during the late Northern Song Dynasty, revealing the social reality of oppression leading to rebellion.
|
||||
Depicts the story of 108 outlaws, led by Song Jiang, who gather at Liangshan Marsh during the late
|
||||
Northern Song Dynasty to rebel against the imperial government, showcasing the social reality of oppression leading to rebellion.
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
---
|
||||
title: Can I Use
|
||||
createTime: 2025/03/24 22:10:32
|
||||
createTime: 2025/10/08 14:50:55
|
||||
icon: streamline:desktop-help
|
||||
permalink: /en/guide/markdown/caniuse/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
When writing articles, you can embed the support status of [can-i-use](https://caniuse.com/) WEB features across platforms.
|
||||
When writing articles, this feature provides the functionality to embed platform support information for WEB features from [can-i-use](https://caniuse.com/).
|
||||
|
||||
This makes it easier to describe the support level of a particular WEB feature.
|
||||
This allows for a more intuitive representation of a feature's support level when describing a specific WEB feature.
|
||||
|
||||
## Configuration
|
||||
|
||||
This feature is not enabled by default. You can enable it in the configuration file.
|
||||
This feature is disabled by default. You can enable it in the configuration file.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
@ -25,17 +25,18 @@ export default defineUserConfig({
|
||||
})
|
||||
```
|
||||
|
||||
In your Markdown file, use the following format:
|
||||
In your article's markdown file, use the following format:
|
||||
|
||||
```md
|
||||
``` md
|
||||
@[caniuse](feature)
|
||||
```
|
||||
|
||||
For convenience, the theme provides a tool: [caniuse feature search](../../../../../notes/tools/caniuse.md), which can help generate the Markdown code.
|
||||
For ease of use, the theme provides tool support: [caniuse Feature Search](../../../tools/caniuse.md).
|
||||
You can use this tool directly to help generate the markdown code.
|
||||
|
||||
## Syntax
|
||||
|
||||
```md
|
||||
``` md
|
||||
@[caniuse](feature)
|
||||
@[caniuse{browser_versions}](feature)
|
||||
@[caniuse embed_type](feature)
|
||||
@ -44,19 +45,19 @@ For convenience, the theme provides a tool: [caniuse feature search](../../../..
|
||||
|
||||
- `feature`
|
||||
|
||||
Required. For correct values, refer to [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN)
|
||||
Required. For correct values, please refer to [caniuse-embed.vercel.app](https://caniuse-embed.vercel.app/zh-CN).
|
||||
|
||||
- `{browser_versions}`
|
||||
|
||||
Optional. The support status of the feature across multiple browser versions.
|
||||
Optional. Specifies the support status of the current feature across multiple browser versions.
|
||||
|
||||
Default value: `{-2,1}`
|
||||
|
||||
Format: `{past,future}` with values ranging from `-5 ~ 3`
|
||||
Format: `{past,future}` Value range: `-5 ~ 3`
|
||||
|
||||
- Less than `0` indicates support below the current browser version
|
||||
- `0` indicates support at the current browser version
|
||||
- Greater than `0` indicates support above the current browser version
|
||||
- Values less than `0` indicate support status for browser versions lower than the current one.
|
||||
- `0` indicates the support status for the current browser version.
|
||||
- Values greater than `0` indicate support status for browser versions higher than the current one.
|
||||
|
||||
- `embed_type`
|
||||
|
||||
@ -67,37 +68,40 @@ For convenience, the theme provides a tool: [caniuse feature search](../../../..
|
||||
Default value: `'embed'`
|
||||
|
||||
:::caution
|
||||
The use of image type is no longer recommended. Instead, use the embed type, as the theme has changed the embed implementation, offering faster loading, smaller size, and better interaction.
|
||||
The `image` type is no longer recommended. It is advised to use the `embed` type.
|
||||
The theme has changed the implementation technology for the embed component.
|
||||
The current `embed` type now offers significant advantages over the `image` type,
|
||||
including faster loading speed, smaller size, and better interactive experience.
|
||||
:::
|
||||
|
||||
## Examples
|
||||
|
||||
**Get the browser support status for the CSS pseudo-class selector `:dir()`:**
|
||||
**Get the browser support for the CSS pseudo-class selector `:dir()`:**
|
||||
|
||||
```md
|
||||
@[caniuse](css-matches-pseudo)
|
||||
```
|
||||
|
||||
Effect:
|
||||
Result:
|
||||
|
||||
@[caniuse](css-matches-pseudo)
|
||||
|
||||
**Get the browser support status for the CSS pseudo-class selector `:dir()` as an image:**
|
||||
**Get the browser support for the CSS pseudo-class selector `:dir()` as an image:**
|
||||
|
||||
```md
|
||||
@[caniuse image](css-matches-pseudo)
|
||||
```
|
||||
|
||||
Effect:
|
||||
Result:
|
||||
|
||||
@[caniuse image](css-matches-pseudo)
|
||||
|
||||
**Get the browser support status for the CSS pseudo-class selector `:dir()` for specific browser versions:**
|
||||
**Get the browser support for the CSS pseudo-class selector `:dir()` for a specific range of browser versions:**
|
||||
|
||||
```md
|
||||
@[caniuse{-2,3}](css-matches-pseudo)
|
||||
```
|
||||
|
||||
Effect:
|
||||
Result:
|
||||
|
||||
@[caniuse{-2,3}](css-matches-pseudo)
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
---
|
||||
title: Card
|
||||
createTime: 2025/03/24 19:46:13
|
||||
createTime: 2025/10/08 14:37:40
|
||||
icon: solar:card-broken
|
||||
permalink: /en/guide/markdown/card/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
To highlight content, place it in a card container `::: card`.
|
||||
Content that needs to be highlighted can be placed within a card container `::: card`.
|
||||
|
||||
To display multiple cards side by side when space allows, use the `card-grid` container around multiple cards.
|
||||
When multiple cards need to be displayed side-by-side when space permits, use the `card-grid` container to wrap multiple cards.
|
||||
|
||||
## Syntax
|
||||
|
||||
```md
|
||||
<!-- Single card -->
|
||||
<!-- Single Card -->
|
||||
::: card title="Title" icon="twemoji:astonished-face"
|
||||
|
||||
This is the card content.
|
||||
:::
|
||||
|
||||
<!-- Multiple cards -->
|
||||
<!-- Multiple Cards -->
|
||||
:::: card-grid
|
||||
|
||||
::: card title="Card Title 1" icon="twemoji:astonished-face"
|
||||
@ -36,9 +36,18 @@ This is the card content.
|
||||
::::
|
||||
```
|
||||
|
||||
Cards support optional `title` and `icon`. The icon can be an image URL or an Iconify icon name.
|
||||
## Props
|
||||
|
||||
## Example
|
||||
:::: field-group
|
||||
::: field name="title" type="string" optional default="''"
|
||||
Card title
|
||||
:::
|
||||
|
||||
::: field name="icon" type="string" optional
|
||||
Card icon. Supports image URLs and [iconify](https://icon-sets.iconify.design/) icon names.
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
@ -87,5 +96,5 @@ This is the card content.
|
||||
::::
|
||||
|
||||
::: info
|
||||
If you prefer to use cards via components, you can check out the [Card Component](/en/guide/features/component/#card).
|
||||
If you prefer using cards via components, you can check out the [Card Component](/guide/features/component/#card).
|
||||
:::
|
||||
|
||||
123
docs/en/guide/markdown/chat.md
Normal file
123
docs/en/guide/markdown/chat.md
Normal file
@ -0,0 +1,123 @@
|
||||
---
|
||||
title: Chat Records
|
||||
icon: cil:chat-bubble
|
||||
createTime: 2025/10/08 21:40:18
|
||||
permalink: /en/guide/markdown/chat/
|
||||
---
|
||||
|
||||
## Preface
|
||||
|
||||
::: chat title="User B"
|
||||
{:2025-03-24 10:15:00}
|
||||
|
||||
{User B}
|
||||
Putting chat screenshots in the documentation still looks pretty bad, is there a better way? \[doge\]
|
||||
|
||||
{.}
|
||||
Sure there is, bro, definitely sure
|
||||
|
||||
{.}
|
||||
But is it really okay to post chat records like this?
|
||||
|
||||
{User B}
|
||||
Proof of our fiery debates is worth keeping \[doge\]
|
||||
|
||||
{:2025-03-24 15:32:00}
|
||||
|
||||
{.}
|
||||
Good news: the docs now support chat records!
|
||||
|
||||
{.}
|
||||
Bad news: I've used you as the example \[doge\]
|
||||
|
||||
{User B}
|
||||
???
|
||||
:::
|
||||
|
||||
## Overview
|
||||
|
||||
In Markdown, wrapping specially formatted text content within a `:: chat` container allows you to display ==chat records== within the documentation.
|
||||
|
||||
::: warning This is a feature you likely won't need most of the time.
|
||||
Please consider carefully whether you should use it when the need arises.
|
||||
Filter out any private or sensitive content yourself.
|
||||
:::
|
||||
|
||||
## Enable
|
||||
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
chat: true, // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Within a `::: chat` container, use specific markers to identify the sender and timestamp of messages,
|
||||
which will then render the chat record in the documentation.
|
||||
|
||||
```md
|
||||
::: chat title="Title"
|
||||
{:date} <!-- Mark the starting timestamp -->
|
||||
|
||||
{username} <!-- Mark the sender -->
|
||||
xxx <!-- The sender's message content -->
|
||||
|
||||
{.} <!-- Mark as sent by the current user -->
|
||||
xxx <!-- The current user's message content -->
|
||||
:::
|
||||
```
|
||||
|
||||
- `{:date}` Marks the starting timestamp (Optional). Use the format `{:` + date + `}`. `date` can be in common date formats.
|
||||
|
||||
The theme does not process `date` in any way; it simply renders it.
|
||||
|
||||
- `{username}` Marks the sender of the subsequent content. Use the format `{` + username + `}`. `username` can be any string.
|
||||
|
||||
- `{.}` Marks the message as sent by the current user.
|
||||
|
||||
## Example
|
||||
|
||||
__Input:__
|
||||
|
||||
``` md
|
||||
::: chat title="Title"
|
||||
{:2025-03-24 10:15:00}
|
||||
|
||||
{User 1}
|
||||
Message from User 1
|
||||
|
||||
{.}
|
||||
Message from the current user
|
||||
|
||||
{User 2}
|
||||
Message from User 2
|
||||
|
||||
{.}
|
||||
Message from the current user
|
||||
:::
|
||||
```
|
||||
|
||||
__Output:__
|
||||
|
||||
::: chat title="Title"
|
||||
{:2025-03-24 10:15:00}
|
||||
|
||||
{User 1}
|
||||
Message from User 1
|
||||
|
||||
{.}
|
||||
Message from the current user
|
||||
|
||||
{User 2}
|
||||
Message from User 2
|
||||
|
||||
{.}
|
||||
Message from the current user
|
||||
:::
|
||||
170
docs/en/guide/markdown/code-tree.md
Normal file
170
docs/en/guide/markdown/code-tree.md
Normal file
@ -0,0 +1,170 @@
|
||||
---
|
||||
title: Code Tree
|
||||
icon: stash:side-peek
|
||||
createTime: 2025/10/08 05:59:44
|
||||
permalink: /en/guide/markdown/code-tree/
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In Markdown, use the `::: code-tree` container or `@[code-tree](dir_path)` syntax to display a code block area with a file tree.
|
||||
|
||||
Compared to code block grouping, code trees can more clearly present the organizational structure of code files and their dependency relationships.
|
||||
|
||||
## Enable
|
||||
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
codeTree: true, // [!code ++]
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The theme provides two usage methods:
|
||||
|
||||
### code-tree Container
|
||||
|
||||
````md
|
||||
::: code-tree title="Project Name" height="400px" entry="filepath"
|
||||
```lang title="filepath" :active
|
||||
<!-- code content-->
|
||||
```
|
||||
|
||||
```lang title="filepath"
|
||||
<!-- code content-->
|
||||
```
|
||||
<!-- More code blocks -->
|
||||
:::
|
||||
````
|
||||
|
||||
Use the `::: code-tree` container to wrap multiple code blocks.
|
||||
|
||||
- Use `title="Project Name"` after `::: code-tree` to declare the code tree title
|
||||
- Use `height="400px"` after `::: code-tree` to declare the code tree height
|
||||
- Use `entry="filepath"` after `::: code-tree` to declare the default expanded file path
|
||||
- Use `title="filepath"` after the code block <code>\`\`\` lang</code> to declare the current code block's file path
|
||||
- If `entry="filepath"` is not declared in `::: code-tree`, you can use `:active` after the code block
|
||||
<code>\`\`\` lang</code> to declare the current code block as expanded
|
||||
- If no expanded file path is specified, the first file will be expanded by default
|
||||
|
||||
::: details Why use `title="filepath"` instead of `filepath="filepath"` on code blocks?
|
||||
Because the theme already [supports title syntax on code blocks](../code/features.md#code-block-titles).
|
||||
Continuing to use the existing syntax support reduces the learning curve.
|
||||
:::
|
||||
|
||||
**Input:**
|
||||
|
||||
````md :collapsed-lines
|
||||
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
|
||||
```vue title="src/components/HelloWorld.vue"
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>Hello World</h1>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```vue title="src/App.vue"
|
||||
<template>
|
||||
<div id="app">
|
||||
<h3>vuepress-theme-plume</h3>
|
||||
<HelloWorld />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```ts title="src/main.ts"
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
```
|
||||
|
||||
```json title="package.json"
|
||||
{
|
||||
"name": "Vue App",
|
||||
"scripts": {
|
||||
"dev": "vite"
|
||||
}
|
||||
}
|
||||
```
|
||||
:::
|
||||
````
|
||||
|
||||
**Output:**
|
||||
|
||||
::: code-tree title="Vue App" height="400px" entry="src/main.ts"
|
||||
|
||||
```vue title="src/components/HelloWorld.vue"
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>Hello World</h1>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```vue title="src/App.vue"
|
||||
<template>
|
||||
<div id="app">
|
||||
<h3>vuepress-theme-plume</h3>
|
||||
<HelloWorld />
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
```ts title="src/main.ts"
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
```
|
||||
|
||||
```json title="package.json"
|
||||
{
|
||||
"name": "Vue App",
|
||||
"scripts": {
|
||||
"dev": "vite"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Importing code-tree from Directory
|
||||
|
||||
The theme supports importing `code-tree` from a directory using the following syntax:
|
||||
|
||||
```md
|
||||
<!-- Simple import -->
|
||||
@[code-tree](dir_path)
|
||||
|
||||
<!-- With additional configuration -->
|
||||
@[code-tree title="Project Name" height="400px" entry="filepath"](dir_path)
|
||||
```
|
||||
|
||||
- **dir_path**:
|
||||
When an absolute path is provided (starting with `/`), the search begins from the source directory of the documentation site.
|
||||
When a relative path is provided (starting with `.`), it is relative to the current Markdown file.
|
||||
|
||||
- **title**: Code tree title, optional, defaults to empty
|
||||
- **height**: Code tree height, optional, defaults to empty
|
||||
- **entry**: Default expanded file path, optional, defaults to the first file
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
<!-- This directory is the theme repository's `docs/.vuepress/collections/` -->
|
||||
@[code-tree title="Collections Configuration" height="400px" entry="index.ts"](/.vuepress/collections)
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
@[code-tree title="Collections Configuration" height="400px" entry="index.ts"](/.vuepress/collections)
|
||||
@ -1,22 +1,19 @@
|
||||
---
|
||||
title: Collapsible panel
|
||||
title: Collapse Panel
|
||||
icon: carbon:collapse-categories
|
||||
createTime: 2025/03/25 10:13:04
|
||||
createTime: 2025/10/08 22:27:22
|
||||
permalink: /en/guide/markdown/collapse/
|
||||
badge:
|
||||
type: tip
|
||||
text: 1.0.0-rc.137 +
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In Markdown, the `::: collapse` container, combined with Markdown unordered list syntax, can be used to create ==collapsible panels==.
|
||||
In markdown, use the `::: collapse` container with markdown unordered list syntax to implement ==collapse panels==.
|
||||
|
||||
- It supports setting the mode to **accordion** using the `accordion` option.
|
||||
- Supports ==accordion== mode via the `accordion` setting
|
||||
|
||||
## Enable
|
||||
|
||||
This feature is not enabled by default. You need to enable it in the `theme` configuration.
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
@ -30,12 +27,12 @@ export default defineUserConfig({
|
||||
|
||||
## Usage
|
||||
|
||||
In Markdown, use the `::: collapse` container with Markdown unordered list syntax, where each item represents a separate collapsible area.
|
||||
In markdown, use the `::: collapse` container with markdown unordered list syntax. Each item represents a separate collapsible section.
|
||||
|
||||
```md title="collapse.md"
|
||||
::: collapse
|
||||
- Title 1 <!-- Title, click to control expand/collapse -->
|
||||
<!-- There must be an empty line between the title and the content -->
|
||||
<!-- Must have an empty line between title and content -->
|
||||
Content <!-- Content, the collapsible area -->
|
||||
|
||||
- Title 2
|
||||
@ -44,225 +41,227 @@ In Markdown, use the `::: collapse` container with Markdown unordered list synta
|
||||
:::
|
||||
```
|
||||
|
||||
For each item in the list:
|
||||
For each list item:
|
||||
|
||||
- From the **first line** to the **first empty line** is the **title**.
|
||||
- **After the first empty line**: The main content.
|
||||
- Everything from the __first line__ to the __first empty line__ is considered the __title__
|
||||
|
||||
:::important Please note the correct indentation
|
||||
- __After the first empty line__: Content
|
||||
|
||||
:::important Please ensure correct indentation
|
||||
:::
|
||||
|
||||
**A simple example:**
|
||||
__A simple example:__
|
||||
|
||||
**Input:**
|
||||
__Input:__
|
||||
|
||||
```md
|
||||
::: collapse
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
||||
After the `::: collapse` container syntax, you can add configuration options:
|
||||
After the `::: collapse` container syntax, follow with configuration options:
|
||||
|
||||
- `accordion`: Sets the collapsible panels to ==accordion== mode. In accordion mode, only one panel can be expanded at a time. Clicking another panel will close the previously opened one.
|
||||
- `expand`: Expands all panels by default. This option is invalid in accordion mode.
|
||||
- `accordion`: Sets the collapse panel to ==accordion== mode. In accordion mode,
|
||||
only one panel can be expanded at a time; clicking other panels will close the previously opened panel.
|
||||
- `expand`: Expands panels by default. Invalid in accordion mode.
|
||||
|
||||
Before the title of each list item, you can use special markers `:+` or `:-` to set the initial state of the item to **expanded** or **collapsed**.
|
||||
In list items, before the title, use special markers `:+` / `:-` to set the initial state of the current item to __expanded / collapsed__.
|
||||
|
||||
## Examples
|
||||
|
||||
### Basic Usage
|
||||
|
||||
**Input:**
|
||||
__Input:__
|
||||
|
||||
```md
|
||||
::: collapse
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
:::
|
||||
Content
|
||||
:::
|
||||
|
||||
### Expand All by Default
|
||||
|
||||
Add the `expand` option to expand all panels by default.
|
||||
|
||||
**Input:**
|
||||
__Input:__
|
||||
|
||||
```md /expand/
|
||||
::: collapse expand
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse expand
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
:::
|
||||
Content
|
||||
:::
|
||||
|
||||
### Accordion Mode
|
||||
|
||||
Add the `accordion` option to set the mode to accordion, allowing only one panel to be expanded at a time. Clicking another panel will close the previously opened one.
|
||||
Add the `accordion` option to set accordion mode, where only one panel can be expanded at a time.
|
||||
|
||||
```md /accordion/
|
||||
::: collapse accordion
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 3
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse accordion
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 3
|
||||
|
||||
Main content
|
||||
:::
|
||||
Content
|
||||
:::
|
||||
|
||||
### Expand Items with `:+`
|
||||
### `:+` Mark Item as Expanded
|
||||
|
||||
By default, all collapsible panels are closed. You can use the `:+` marker to set the initial state of an item to expanded.
|
||||
Collapse panels are closed by default. Use `:+` to mark items with an initial expanded state.
|
||||
|
||||
**Input:**
|
||||
__Input:__
|
||||
|
||||
```md /:+/
|
||||
::: collapse
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :+ Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :+ Title 3
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :+ Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :+ Title 3
|
||||
|
||||
Main content
|
||||
:::
|
||||
Content
|
||||
:::
|
||||
|
||||
### Collapse Items with `:-`
|
||||
### `:-` Mark Item as Collapsed
|
||||
|
||||
When the `expand` option is configured, all panels are expanded by default. You can use the `:-` marker to set the initial state of an item to collapsed.
|
||||
When collapse panel is configured with `expand`, all panels are expanded by default. Use `:-` to mark items with an initial collapsed state.
|
||||
|
||||
**Input:**
|
||||
__Input:__
|
||||
|
||||
```md /:-/
|
||||
::: collapse expand
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 3
|
||||
|
||||
Main content
|
||||
Content
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
__Output:__
|
||||
|
||||
::: collapse expand
|
||||
|
||||
- Title 1
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- :- Title 2
|
||||
|
||||
Main content
|
||||
Content
|
||||
|
||||
- Title 3
|
||||
|
||||
Main content
|
||||
:::
|
||||
Content
|
||||
:::
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Demo Wrapper
|
||||
createTime: 2025/03/24 21:49:01
|
||||
title: Demo Container
|
||||
createTime: 2025/10/08 14:47:12
|
||||
icon: icon-park-outline:eyes
|
||||
permalink: /en/guide/markdown/demo-wrapper/
|
||||
outline: 2
|
||||
@ -8,27 +8,27 @@ outline: 2
|
||||
|
||||
## Overview
|
||||
|
||||
Sometimes, you may need to add examples in your content but want them to be presented separately from other content.
|
||||
The theme supports adding demo wrapper in Markdown files.
|
||||
Sometimes you may need to supplement your content with examples but want them to be presented
|
||||
separately from other content. The theme supports adding demo containers in Markdown files.
|
||||
|
||||
## Syntax
|
||||
|
||||
````md
|
||||
::: demo-wrapper
|
||||
Add your example here
|
||||
Add your demo here
|
||||
:::
|
||||
````
|
||||
|
||||
## Options
|
||||
|
||||
- `title="xxx"`: Title
|
||||
- `no-padding`: No padding
|
||||
- `img`: Use when only containing an image
|
||||
- `no-padding`: Remove padding
|
||||
- `img`: Use when containing only images
|
||||
- `height="xxx"`: Height
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
Image only:
|
||||
Containing only images:
|
||||
|
||||
```md
|
||||
::: demo-wrapper img no-padding
|
||||
@ -41,25 +41,25 @@ Image only:
|
||||

|
||||
:::
|
||||
|
||||
Markdown content:
|
||||
Containing markdown syntax:
|
||||
|
||||
```md
|
||||
::: demo-wrapper title="Title"
|
||||
### Third-level heading
|
||||
### Level 3 Heading
|
||||
|
||||
This is the content within the demo wrapper.
|
||||
This is content inside the demo container.
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
::: demo-wrapper title="Title"
|
||||
|
||||
### Third-level heading
|
||||
### Level 3 Heading
|
||||
|
||||
This is the content within the demo wrapper.
|
||||
This is content inside the demo container.
|
||||
:::
|
||||
|
||||
HTML/Vue code:
|
||||
Containing HTML/Vue code:
|
||||
|
||||
```md
|
||||
::: demo-wrapper
|
||||
@ -80,7 +80,7 @@ HTML/Vue code:
|
||||
**Output:**
|
||||
::: demo-wrapper
|
||||
|
||||
<h1 class="your-demo-title">This is a title</h1>
|
||||
<h1 class="your-demo-title">This is a heading</h1>
|
||||
<p class="your-demo-paragraph">This is a paragraph</p>
|
||||
|
||||
<style>
|
||||
|
||||
150
docs/en/guide/markdown/field.md
Normal file
150
docs/en/guide/markdown/field.md
Normal file
@ -0,0 +1,150 @@
|
||||
---
|
||||
title: Field Container
|
||||
icon: solar:text-field-linear
|
||||
createTime: 2025/10/08 09:55:17
|
||||
permalink: /en/guide/markdown/field/
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In Markdown, use the `::: field` container to describe field information, including field name,
|
||||
field type, whether it's required, default value, description, and other details.
|
||||
|
||||
It's suitable for describing fields in configurations, component Props, and similar scenarios.
|
||||
|
||||
You can also use the additional `:::: field-group` container to group multiple `::: field` containers.
|
||||
|
||||
## Enable
|
||||
|
||||
This feature is disabled by default. You need to enable it in the `theme` configuration.
|
||||
|
||||
```ts title=".vuepress/config.ts"
|
||||
export default defineUserConfig({
|
||||
theme: plumeTheme({
|
||||
markdown: {
|
||||
field: true, // [!code ++]
|
||||
},
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Syntax
|
||||
|
||||
```md
|
||||
<!-- Single Field -->
|
||||
::: field name="Field Name" type="Type" required default="Default Value"
|
||||
Field description information
|
||||
:::
|
||||
|
||||
<!-- Field Group -->
|
||||
:::: field-group
|
||||
|
||||
::: field name="Field Name" type="Type" required default="Default Value"
|
||||
Field description information
|
||||
:::
|
||||
|
||||
::: field name="Field Name" type="Type" required default="Default Value"
|
||||
Field description information
|
||||
:::
|
||||
|
||||
::::
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
:::: field-group
|
||||
::: field name="name" required type="string"
|
||||
Field name
|
||||
:::
|
||||
|
||||
::: field name="type" type="string" optional
|
||||
Field type
|
||||
:::
|
||||
|
||||
::: field name="required" type="boolean" optional
|
||||
Whether the field is required
|
||||
:::
|
||||
|
||||
::: field name="optional" type="boolean" optional
|
||||
Whether the field is optional
|
||||
:::
|
||||
|
||||
::: field name="deprecated" type="boolean" optional
|
||||
Whether the field is deprecated
|
||||
:::
|
||||
|
||||
::: field name="default" type="string" optional
|
||||
Default value. If it's an empty string, use `default="''"`
|
||||
:::
|
||||
::::
|
||||
|
||||
## Examples
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
::: field name="theme" type="ThemeConfig" required default="{}"
|
||||
Theme configuration
|
||||
:::
|
||||
|
||||
::: field name="enabled" type="boolean" optional default="true"
|
||||
Whether enabled
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
::: field name="theme" type="ThemeConfig" required default="{}"
|
||||
Theme configuration
|
||||
:::
|
||||
|
||||
::: field name="enabled" type="boolean" optional default="true"
|
||||
Whether enabled
|
||||
:::
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
:::: field-group
|
||||
::: field name="theme" type="ThemeConfig" required default="{ base: '/' }"
|
||||
Theme configuration
|
||||
:::
|
||||
|
||||
::: field name="enabled" type="boolean" optional default="true"
|
||||
Whether enabled
|
||||
:::
|
||||
|
||||
::: field name="callback" type="(...args: any[]) => void" optional default="() => {}"
|
||||
<Badge type="tip" text="v1.0.0 New" />
|
||||
Callback function
|
||||
:::
|
||||
|
||||
::: field name="other" type="string" deprecated
|
||||
<Badge type="danger" text="v0.9.0 Deprecated" />
|
||||
Deprecated property
|
||||
:::
|
||||
::::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
:::: field-group
|
||||
::: field name="theme" type="ThemeConfig" required default="{ base: '/' }"
|
||||
Theme configuration
|
||||
:::
|
||||
|
||||
::: field name="enabled" type="boolean" optional default="true"
|
||||
Whether enabled
|
||||
:::
|
||||
|
||||
::: field name="callback" type="(...args: any[]) => void" optional default="() => {}"
|
||||
<Badge type="tip" text="v1.0.0 New" />
|
||||
Callback function
|
||||
:::
|
||||
|
||||
::: field name="other" type="string" deprecated
|
||||
<Badge type="danger" text="v0.9.0 Deprecated" />
|
||||
Deprecated property
|
||||
:::
|
||||
::::
|
||||
@ -1,35 +1,38 @@
|
||||
---
|
||||
title: File Tree
|
||||
createTime: 2025/03/24 20:15:12
|
||||
createTime: 2025/10/08 14:41:57
|
||||
icon: mdi:file-tree
|
||||
permalink: /en/guide/markdown/file-tree/
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
In Markdown, you can use the `file-tree` container to display a directory structure with file icons and collapsible subdirectories.
|
||||
In Markdown, you can use the `file-tree` container to display directory structures with file icons and collapsible subdirectories.
|
||||
|
||||
## Syntax
|
||||
|
||||
In the `::: file-tree` container, use the built-in **Markdown unordered list syntax** to specify the organization of files and directories.
|
||||
Use nested list items to create subdirectories; if you want a directory to not display specific content, simply add a slash `/` at the end of the list item.
|
||||
Within the `::: file-tree` container, use the built-in **Markdown unordered list syntax** to specify the organization of files and directories.
|
||||
Use nested list items to create subdirectories; to indicate that a directory's contents should not be
|
||||
displayed, simply add a slash `/` at the end of the list item.
|
||||
|
||||
The following syntax can be used to customize the appearance of the file tree:
|
||||
|
||||
- Highlight files or directories by bolding their names, e.g., `**README.md**`
|
||||
- Add annotations to files or directories by appending additional text after the name
|
||||
- Use `...` or `…` as names to add placeholder files and directories.
|
||||
- Adding `icon="simple"` or `icon="colored"` after `:::file-tree` can switch to simple icons or colored icons, with colored icons being the default.
|
||||
- Emphasize file or directory names by making them bold, e.g., `**README.md**`
|
||||
- Add comments to files or directories by adding additional text after the name
|
||||
- Mark files or directories as **added** or **deleted** by prefixing the name with `++` or `--`
|
||||
- Use `...` or `…` as the name to add placeholder files and directories.
|
||||
- Add `icon="simple"` or `icon="colored"` after `:::file-tree` to switch to simple icons or colored icons. The default is colored icons.
|
||||
- Add `title="xxxx"` after `:::file-tree` to add a title to the file tree.
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
```md /++/ /--/
|
||||
::: file-tree
|
||||
|
||||
- docs
|
||||
- .vuepress
|
||||
- config.ts
|
||||
- page1.md
|
||||
- ++ config.ts
|
||||
- -- page1.md
|
||||
- README.md
|
||||
- theme A **theme** directory
|
||||
- client
|
||||
@ -55,8 +58,8 @@ The following syntax can be used to customize the appearance of the file tree:
|
||||
|
||||
- docs
|
||||
- .vuepress
|
||||
- config.ts
|
||||
- page1.md
|
||||
- ++ config.ts
|
||||
- -- page1.md
|
||||
- README.md
|
||||
- theme A **theme** directory
|
||||
- client
|
||||
@ -73,7 +76,7 @@ The following syntax can be used to customize the appearance of the file tree:
|
||||
- .gitignore
|
||||
- README.md
|
||||
- …
|
||||
:::
|
||||
:::
|
||||
|
||||
## Using Simple Icons
|
||||
|
||||
@ -100,11 +103,11 @@ The following syntax can be used to customize the appearance of the file tree:
|
||||
- page1.md
|
||||
- README.md
|
||||
- package.json
|
||||
:::
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
||||
You can configure the default icon type for the file tree in the `plugins.mdPower.fileTree` option:
|
||||
You can configure the default icon type for file trees in the `markdown.fileTree` option:
|
||||
|
||||
::: code-tabs
|
||||
@tab .vuepress/config.ts
|
||||
@ -123,9 +126,14 @@ export default defineUserConfig({
|
||||
|
||||
:::
|
||||
|
||||
::: tip Worried that colored icons will affect the build package size?
|
||||
You don't need to worry. The colored icons for the file tree are also parsed from `iconify`. We recommend that you install the `@iconify/json` project locally.
|
||||
The theme will automatically parse the icon data from `@iconify/json` into local icon resources. Even if you use them multiple times on different pages, including the navbar, sidebar, icon components, etc., the same icon will only exist as one resource!
|
||||
::: tip Concerned about colored icons affecting build bundle size?
|
||||
You don't need to worry. The colored icons for the file tree are also resolved from `iconify`.
|
||||
We recommend installing the `@iconify/json` package locally in your project.
|
||||
The theme will automatically parse the icon data from `@iconify/json` into local icon resources.
|
||||
Even if you use the same icon multiple times across different pages
|
||||
(including navigation bars, sidebars, icon components, etc.), only one copy of the resource will exist for each icon!
|
||||
|
||||
Each colored icon is approximately between `1kb ~ 2kb` in size. Even if your file tree uses 100+ different icons, the impact on the final build package size will not be significant.
|
||||
Each colored icon is approximately `1kb ~ 2kb` in size.
|
||||
Even if your file tree extensively uses 100+ different icons, the impact on the final build bundle size
|
||||
will not be significant.
|
||||
:::
|
||||
|
||||
130
docs/en/guide/markdown/flex.md
Normal file
130
docs/en/guide/markdown/flex.md
Normal file
@ -0,0 +1,130 @@
|
||||
---
|
||||
title: Flex Container
|
||||
icon: material-symbols-light:flex-no-wrap
|
||||
createTime: 2025/10/08 17:56:39
|
||||
permalink: /en/guide/markdown/flex/
|
||||
badge: New
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Flex container `::: flex` provides a convenient way to apply Flexbox layout to block-level content in markdown.
|
||||
|
||||
## Usage
|
||||
|
||||
```md
|
||||
::: flex [center|between|around] [start|center|end] [gap="20"] [column]
|
||||
|
||||
<!-- Block content 1 -->
|
||||
|
||||
<!-- Block content 2 -->
|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
- On the main axis, use `center` / `between` / `around` to specify alignment;
|
||||
- On the cross axis, use `start` / `center` / `end` to specify alignment;
|
||||
- Use `gap="20"` to specify spacing;
|
||||
- Use `column` to set the main axis direction to vertical.
|
||||
|
||||
## Examples
|
||||
|
||||
### Centered Table Alignment
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
::: flex center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
::: flex center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
|
||||
### Two Tables with Left-Right Alignment
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
::: flex between center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
::: flex between center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
|
||||
### Evenly Spaced Tables
|
||||
|
||||
**Input:**
|
||||
|
||||
```md
|
||||
::: flex around center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
```
|
||||
|
||||
**Output:**
|
||||
|
||||
::: flex around center
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
| Column 1 | Column 2 | Column 3 |
|
||||
| -------- | -------- | -------- |
|
||||
| 1 | 2 | 3 |
|
||||
| 4 | 5 | 6 |
|
||||
|
||||
:::
|
||||
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