diff --git a/404.html b/404.html new file mode 100644 index 0000000000..b03f2044f3 --- /dev/null +++ b/404.html @@ -0,0 +1,37 @@ + + +
+ + + + + +This plugin will listen to page scroll event. When the page scrolls to a certain header anchor, this plugin will change the route hash to that header anchor if there is a corresponding header link.
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
npm i -D @vuepress/plugin-active-header-links@next
+
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
+
+export default {
+ plugins: [
+ activeHeaderLinksPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string
Default: 'a.sidebar-item'
Details:
Selector of header link.
If a header anchor does not have a corresponding header link, this plugin won't change the route hash to that anchor when scrolling to it.
Type: number
Default: 200
Details:
The delay of the debounced scroll event listener.
Type: number
Default: 5
Details:
Even if you click the link of the header anchor directly, the scrollTop
might not be exactly equal to offsetTop
of the header anchor, so we add an offset to avoid the error.
该插件会监听页面滚动事件。当页面滚动至某个 标题锚点 后,如果存在对应的 标题链接 ,那么该插件会将路由 Hash 更改为该 标题锚点 。
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
npm i -D @vuepress/plugin-active-header-links@next
+
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
+
+export default {
+ plugins: [
+ activeHeaderLinksPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: string
默认值: 'a.sidebar-item'
详情:
标题链接 的选择器。
如果一个 标题锚点 没有对应的 标题链接 ,那么即使滚动到这个 标题锚点 ,该插件也不会更改路由 Hash 。
类型: number
默认值: 200
详情:
滚动事件监听器的 Debounce 延迟。
类型: number
默认值: 5
详情:
即便直接点击 标题锚点 的链接, scrollTop
也可能不会完全等于 标题锚点 的 offsetTop
,所以我们添加一个 Offset 偏移量来避免这个误差。
This plugin will add a back to top button to your site. The button will be displayed in the bottom right corner of the page when scrolling down. By clicking the button, the page will scroll to the top.
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-back-to-top@next
+
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'
+
+export default {
+ plugins: [backToTopPlugin()],
+}
+
number
100
boolean
true
You can customize the style of the back to top button via CSS variables:
:root {
+ --back-to-top-z-index: 5;
+ --back-to-top-icon: url("back-to-top.svg");
+ --back-to-top-bg-color: #fff;
+ --back-to-top-color: #3eaf7c;
+ --back-to-top-color-hover: #71cda3;
+ --back-to-top-shadow: rgb(0 0 0 / 20%);
+}
+
该插件会给你的站点添加一个 返回顶部 按钮。当页面向下滚动时,该按钮会显示在页面的右下角,点击它就会滚动到页面顶部。
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-back-to-top@next
+
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'
+
+export default {
+ plugins: [backToTopPlugin()],
+}
+
数字
100
布尔值
true
你可以通过 CSS 变量来自定义 返回顶部 按钮的样式:
:root {
+ --back-to-top-z-index: 5;
+ --back-to-top-icon: url("back-to-top.svg");
+ --back-to-top-bg-color: #fff;
+ --back-to-top-color: #3eaf7c;
+ --back-to-top-color-hover: #71cda3;
+ --back-to-top-shadow: rgb(0 0 0 / 20%);
+}
+
channel
插件选项用于配置 feed 的频道。
string
SiteConfig.title
频道的标题
string
options.hostname
和 context.base
生成)频道地址
string
SiteConfig.description
频道描述信息
string
siteConfig.locales['/'].locales
"en-US"
频道使用的语言
string
author.name
生成 Copyright by $author
频道版权信息
string
(需是合法的 Date ISOString)频道内容的发布时间
string
(需是合法的 Date ISOString)频道内容的上次更新时间
number
内容有效时间,即获取后保持缓存而不进行新获取的时间
string
这是一个会在频道中使用的图片,建议设置正方形图片、尺寸最好不小于 512×512。
string
一个代表频道的图标,建议设置正方形图片、尺寸最好不小于 128×128,背景色透明。
FeedAuthor
频道的作者。
interface FeedAuthor {
+ /** 作者姓名 */
+ name: string
+ /** 作者电子邮箱 */
+ email?: string
+ /** 作者网站 */
+ url?: string
+ /**
+ * 作者头像地址
+ *
+ * 正方形,最好不小于 128×128,透明背景
+ */
+ avatar?: string
+}
+
string
Websub 的链接。Websub 需要服务器后端,与 VuePress 主旨不符,如无特殊需要忽略即可。
`,39),d={class:"custom-container tip"},h=n("p",{class:"custom-container-title"},"WebSub",-1),u={href:"https://w3c.github.io/websub/#subscription-migration",target:"_blank",rel:"noopener noreferrer"};function b(g,m){const e=l("ExternalLinkIcon");return i(),c("div",null,[p,n("div",d,[h,n("p",null,[a("有关信息,详见 "),n("a",u,[a("Websub"),o(e)]),a("。")])])])}const y=s(r,[["render",b],["__file","channel.html.vue"]]);export{y as default}; diff --git a/assets/channel.html-Yo0Atm8m.js b/assets/channel.html-Yo0Atm8m.js new file mode 100644 index 0000000000..8a0230529e --- /dev/null +++ b/assets/channel.html-Yo0Atm8m.js @@ -0,0 +1 @@ +const l=JSON.parse('{"key":"v-87c134a0","path":"/zh/plugins/feed/channel.html","title":"频道设置","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"channel.title","slug":"channel-title","link":"#channel-title","children":[]},{"level":2,"title":"channel.link","slug":"channel-link","link":"#channel-link","children":[]},{"level":2,"title":"channel.description","slug":"channel-description","link":"#channel-description","children":[]},{"level":2,"title":"channel.language","slug":"channel-language","link":"#channel-language","children":[]},{"level":2,"title":"channel.copyright","slug":"channel-copyright","link":"#channel-copyright","children":[]},{"level":2,"title":"channel.pubDate","slug":"channel-pubdate","link":"#channel-pubdate","children":[]},{"level":2,"title":"channel.lastUpdated","slug":"channel-lastupdated","link":"#channel-lastupdated","children":[]},{"level":2,"title":"channel.ttl","slug":"channel-ttl","link":"#channel-ttl","children":[]},{"level":2,"title":"channel.image","slug":"channel-image","link":"#channel-image","children":[]},{"level":2,"title":"channel.icon","slug":"channel-icon","link":"#channel-icon","children":[]},{"level":2,"title":"channel.author","slug":"channel-author","link":"#channel-author","children":[]},{"level":2,"title":"channel.hub","slug":"channel-hub","link":"#channel-hub","children":[]}],"git":{"updatedTime":1706801200000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"filePathRelative":"zh/plugins/feed/channel.md"}');export{l as data}; diff --git a/assets/channel.html-k1lKhm8T.js b/assets/channel.html-k1lKhm8T.js new file mode 100644 index 0000000000..8343042e77 --- /dev/null +++ b/assets/channel.html-k1lKhm8T.js @@ -0,0 +1,15 @@ +import{_ as l,r as i,o as t,c,b as e,d as n,a as o,e as a}from"./app-GUhkEPRO.js";const r={},p=a('The channel plugin option is used to config the feed channel.
string
SiteConfig.title
Channel title
string
options.hostname
and context.base
)Channel address
string
SiteConfig.description
Channel description
Type: string
Default:
siteConfig.locales['/'].lang
"en-US"
The language of the channel
Type: string
Default:
author.name
in channel options, and fall back to Copyright by $author
Recommended to set manually: Yes
Channel copyright information
string
(must be a valid Date ISOString)Publish date of the Channel
string
(must be a valid Date ISOString)Last update time of channel content
number
The effective time of the content. It's the time to keep the cache after request without making new requests.
string
A picture presenting the channel. A square picture with a size not smaller than 512×512 is recommended.
string
An icon representing a channel, a square picture, with not less than 128×128 in size, and transparent background color is recommended.
FeedAuthor
The author of the channel.
',35),d={class:"custom-container details"},h=a(`interface FeedAuthor {
+ /** Author name */
+ name: string
+ /** Author's email */
+ email?: string
+ /** Author's site */
+ url?: string
+ /**
+ * Author's avatar address
+ *
+ * Square, preferably not less than 128×128 with transparent background
+ */
+ avatar?: string
+}
+
string
Link to Websub. Websub requires a server backend, which is inconsistent with VuePress, so ignore it if there is no special need.
`,5),u={class:"custom-container tip"},m=e("p",{class:"custom-container-title"},"WebSub",-1),g={href:"https://w3c.github.io/websub/#subscription-migration",target:"_blank",rel:"noopener noreferrer"};function b(y,f){const s=i("ExternalLinkIcon");return t(),c("div",null,[p,e("details",d,[h,e("div",u,[m,e("p",null,[n("For details, see "),e("a",g,[n("Websub"),o(s)]),n(".")])])])])}const D=l(r,[["render",b],["__file","channel.html.vue"]]);export{D as default}; diff --git a/assets/channel.html-uSvMSuIK.js b/assets/channel.html-uSvMSuIK.js new file mode 100644 index 0000000000..435297e3f5 --- /dev/null +++ b/assets/channel.html-uSvMSuIK.js @@ -0,0 +1 @@ +const l=JSON.parse('{"key":"v-34d6c4ff","path":"/plugins/feed/channel.html","title":"Channel Config","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"channel.title","slug":"channel-title","link":"#channel-title","children":[]},{"level":2,"title":"channel.link","slug":"channel-link","link":"#channel-link","children":[]},{"level":2,"title":"channel.description","slug":"channel-description","link":"#channel-description","children":[]},{"level":2,"title":"channel.language","slug":"channel-language","link":"#channel-language","children":[]},{"level":2,"title":"channel.copyright","slug":"channel-copyright","link":"#channel-copyright","children":[]},{"level":2,"title":"channel.pubDate","slug":"channel-pubdate","link":"#channel-pubdate","children":[]},{"level":2,"title":"channel.lastUpdated","slug":"channel-lastupdated","link":"#channel-lastupdated","children":[]},{"level":2,"title":"channel.ttl","slug":"channel-ttl","link":"#channel-ttl","children":[]},{"level":2,"title":"channel.image","slug":"channel-image","link":"#channel-image","children":[]},{"level":2,"title":"channel.icon","slug":"channel-icon","link":"#channel-icon","children":[]},{"level":2,"title":"channel.author","slug":"channel-author","link":"#channel-author","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"filePathRelative":"plugins/feed/channel.md"}');export{l as data}; diff --git a/assets/components.html-5eAAqCkE.js b/assets/components.html-5eAAqCkE.js new file mode 100644 index 0000000000..8055b03289 --- /dev/null +++ b/assets/components.html-5eAAqCkE.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-54b6b4ae","path":"/themes/default/components.html","title":"Built-in Components","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Badge","slug":"badge","link":"#badge","children":[]},{"level":2,"title":"CodeGroup","slug":"codegroup","link":"#codegroup","children":[]},{"level":2,"title":"CodeGroupItem","slug":"codegroupitem","link":"#codegroupitem","children":[]}],"git":{"updatedTime":1706625181000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"filePathRelative":"themes/default/components.md"}');export{e as data}; diff --git a/assets/components.html-CQjk7rXv.js b/assets/components.html-CQjk7rXv.js new file mode 100644 index 0000000000..8eccceea92 --- /dev/null +++ b/assets/components.html-CQjk7rXv.js @@ -0,0 +1,32 @@ +import{_ as u,r as l,o as m,c as v,a as n,b as e,d as s,w as a,e as i}from"./app-GUhkEPRO.js";const D={},b=e("h1",{id:"built-in-components",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#built-in-components"},[e("span",null,"Built-in Components")])],-1),h={id:"badge",tabindex:"-1"},g={class:"header-anchor",href:"#badge"},y=i(`Props:
'tip' | 'warning' | 'danger'
'tip'
string
''
'top' | 'middle' | 'bottom' | undefined
undefined
Example:
Input
- VuePress - <Badge type="tip" text="v2" vertical="top" />
+- VuePress - <Badge type="warning" text="v2" vertical="middle" />
+- VuePress - <Badge type="danger" text="v2" vertical="bottom" />
+
Output
`,4),_=i(`Details:
Wrapper of the CodeGroupItem components.
Props:
string
true
boolean
false
Details:
This component must be placed inside a CodeGroup component.
Use the active
prop to set the initial active item, or the first item will be activated by default.
Example:
Input
<CodeGroup>
+ <CodeGroupItem title="pnpm">
+
+\`\`\`bash:no-line-numbers
+pnpm install
+\`\`\`
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="yarn">
+
+\`\`\`bash:no-line-numbers
+yarn install
+\`\`\`
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="npm" active>
+
+\`\`\`bash:no-line-numbers
+npm install
+\`\`\`
+
+ </CodeGroupItem>
+</CodeGroup>
+
Output
`,7),C=e("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[e("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[e("code",null,[e("span",{class:"line"},[e("span",{style:{color:"#DCDCAA"}},"pnpm"),e("span",{style:{color:"#CE9178"}}," install")]),s(` +`),e("span",{class:"line"})])])],-1),f=e("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[e("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[e("code",null,[e("span",{class:"line"},[e("span",{style:{color:"#DCDCAA"}},"yarn"),e("span",{style:{color:"#CE9178"}}," install")]),s(` +`),e("span",{class:"line"})])])],-1),k=e("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[e("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[e("code",null,[e("span",{class:"line"},[e("span",{style:{color:"#DCDCAA"}},"npm"),e("span",{style:{color:"#CE9178"}}," install")]),s(` +`),e("span",{class:"line"})])])],-1),x={class:"custom-container warning"},E=e("p",{class:"custom-container-title"},"WARNING",-1),q=e("p",null,[s("You must add an empty line between the starting tag of "),e("code",null,"Props:
'tip' | 'warning' | 'danger'
'tip'
string
''
'top' | 'middle' | 'bottom' | undefined
undefined
示例:
输入
- VuePress - <Badge type="tip" text="v2" vertical="top" />
+- VuePress - <Badge type="warning" text="v2" vertical="middle" />
+- VuePress - <Badge type="danger" text="v2" vertical="bottom" />
+
输出
`,4),y=i(`详情:
CodeGroupItem 组件的 Wrapper 。
Props:
string
true
boolean
false
详情:
该组件必须放置在 CodeGroup 组件的内部。
可以通过 active
Prop 来设置初始激活的元素。如果不设置,默认激活第一个元素。
示例:
输入
<CodeGroup>
+ <CodeGroupItem title="pnpm">
+
+\`\`\`bash:no-line-numbers
+pnpm install
+\`\`\`
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="yarn">
+
+\`\`\`bash:no-line-numbers
+yarn install
+\`\`\`
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="npm" active>
+
+\`\`\`bash:no-line-numbers
+npm install
+\`\`\`
+
+ </CodeGroupItem>
+</CodeGroup>
+
输出
`,7),C=s("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#DCDCAA"}},"pnpm"),s("span",{style:{color:"#CE9178"}}," install")]),n(` +`),s("span",{class:"line"})])])],-1),k=s("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#DCDCAA"}},"yarn"),s("span",{style:{color:"#CE9178"}}," install")]),n(` +`),s("span",{class:"line"})])])],-1),E=s("div",{class:"language-bash","data-ext":"sh","data-title":"sh"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#DCDCAA"}},"npm"),s("span",{style:{color:"#CE9178"}}," install")]),n(` +`),s("span",{class:"line"})])])],-1),x={class:"custom-container warning"},f=s("p",{class:"custom-container-title"},"注意",-1),q=s("p",null,[n("你必须在 "),s("code",null,"Type: string
Required: Yes
Details:
Deploy hostname.
Type: Author
type AuthorName = string
+
+interface AuthorInfo {
+ /**
+ * Author name
+ */
+ name: string
+
+ /**
+ * Author website
+ */
+ url?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+}
+
+type Author = AuthorName | AuthorName[] | AuthorInfo | AuthorInfo[]
+
Required: No
Details:
Default author.
Type: boolean
Default: true
Details:
Whether generate description automatically
Type: string | ((page: Page) => string | null)
Details:
Canonical link
Type: string
Details:
Fallback Image link when no image are found
Type: string
Details:
The age rating of the content, the format is [int]+
, such as "13+"
.
Type: string
Details:
Fill in your twitter username.
Type: (page: Page) => boolean
Details:
Use this option to judge whether the page is an article.
Type:
function ogp(
+ /** OGP info inferred by plugin */
+ ogp: SeoContent,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
Required: No
Details:
Custom OPG Generator.
You can use this options to edit OGP tags.
Type:
function jsonLd(
+ /** JSON-LD Object inferred by plugin */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
Required: No
Details:
Custom JSON-LD Generator.
You can use this options to edit JSON-LD properties.
Type:
function customHead(
+ /** Head tag config */
+ head: HeadConfig[],
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
Required: No
Details:
You can use this options to edit tags injected to <head>
.
string
The domain name of the deployment site.
boolean
false
Whether to output Atom syntax files.
boolean
false
Whether output JSON syntax files.
boolean
false
Whether to output RSS syntax files.
string
A large image/icon of the feed, probably used as banner.
string
A small icon of the feed, probably used as favicon.
number
100
Set the maximum number of items in the feed. After all pages are sorted, the first count
items will be intercepted.
If your site has a lot of articles, you may consider this option to reduce feed file size.
(RegExp | string)[] | (tagName: string) => boolean
Custom element or component which should be preserved in feed.
By default, all unknown tags will be removed.
Type: (page: Page)=> boolean
Default:
;({ frontmatter, filePathRelative }: Page): boolean =>
+ !(
+ frontmatter.home ||
+ !filePathRelative ||
+ frontmatter.article === false ||
+ frontmatter.feed === false
+ )
+
A custom filter function, used to filter feed items.
Type: (pageA: Page, pageB: Page)=> number
Default:
// dateSorter is from @vuepress/helper
+;(pageA: Page, pageB: Page): number =>
+ dateSorter(
+ pageA.data.git?.createdTime
+ ? new Date(pageA.data.git?.createdTime)
+ : pageA.frontmatter.date,
+ pageB.data.git?.createdTime
+ ? new Date(pageB.data.git?.createdTime)
+ : pageB.frontmatter.date,
+ )
+
Custom sorter function for feed items.
The default sorting behavior is by file adding time coming from git (needs @vuepress/plugin-git
).
TIP
You should enable @vuepress/plugin-git
to get the newest created pages as feed items. Otherwise, the feed items will be sorted by the default order of pages in VuePress.
channel
option is used to config Feed Channels.
boolean
false
Whether enabled in devServer.
TIP
For performance reasons, we do not provide hot reload. Reboot your devServer to sync your changes.
string
"http://localhost:${port}"
Hostname to use in devServer
string
"atom.xml"
Atom syntax output filename, relative to dest folder.
string
@vuepress/plugin-feed/templates/atom.xsl
Atom xsl template file content.
string
"atom.xsl"
Atom xsl filename, relative to dest folder.
string
"feed.json"
JSON syntax output filename, relative to dest folder.
string
"rss.xml"
RSS syntax output filename, relative to dest folder.
string
@vuepress/plugin-feed/templates/rss.xsl
RSS xsl template file content.
string
"rss.xsl"
RSS syntax xsl filename, relative to dest folder.
类型:string
必填:是
详情:
当前网站部署到的域名,插件需要此选项才能工作。
类型:string[]
详情:
需要额外包含的网址。
如果你有一些不包含在 VuePress 路由中的链接 (如: 存放在 public 文件夹下的页面或其他插件或工具直接生成的页面),你可能需要设置此项。
示例:['/about.html', '/api/']
类型:string[]
默认值:['/404.html']
详情:
不需要收录的页面路径,请以绝对路径开头。
默认情况下 VuePress 自动生成的所有路径 (除 404 页) 都会被添加进 Sitemap。
类型:boolean
默认值:false
详情:
是否在开发服务器中启用
提示
由于性能原因,我们不提供热更新。重启开发服务器以同步你的变更。
类型:string
默认值:"http://localhost:${port}"
详情:
开发服务器使用的主机名
类型:string
默认值:"sitemap.xml"
详情:
输出的文件名,相对于输出目录。
类型:string
默认值:"sitemap.xsl"
详情:
输出的 xsl 文件名,相对于输出目录。
类型:string
默认值:"@vuepress-plugin/sitemap/templates/sitemap.xsl"
详情:
用作模板的 XSL 文件内容
类型:number
默认值:0.5
详情:
页面优先级,范围 0
至 1
。
类型:(page: Page, app: App) => string
详情:
最后修改事件的获得器,需要返回一个 ISO 字符形式的时间,默认会自动通过 Git 插件生成。
Type: string
Required: Yes
Details:
The domain name where the current site is deployed, the plugin needs this option to work.
Type: string[]
Details:
Extra link to be included.
If you have some links not including in VuePress Router (normally in public directory or generated by other tools directly), you may need this option.
Example: ['/about.html', '/api/']
Type: string[]
Default: ['/404.html']
Details:
Urls excluding from sitemap, starting with absolute path.
By default, all the urls generated by VuePress (excluding 404 page) will be added into sitemap.
Type: boolean
Default: false
Details:
Whether enabled in devServer.
TIP
For performance reasons, we do not provide hot reload. Reboot your devServer to sync your changes.
Type: string
Default: "http://localhost:${port}"
Details:
Hostname to use in devServer
Type: string
Default value: "sitemap.xml"
Details:
The output filename, relative to output directory.
Type: string
Default value: "sitemap.xsl"
Details:
Output xsl filename, relative to dest folder.
Type: string
Default value: "@vuepress/plugin-sitemap/templates/sitemap.xsl"
Details:
XSL content used as template.
Type: number
Default: 0.5
Details:
Page priority, from 0
to 1
.
Type: (page: Page, app: App) => string
Details:
Last modify time getter. By default, the plugin will use the timestamp generated by git plugin.
Type: string
Details:
Hostname to be deployed, e.g.: https://example.com
Config of this section can be used as normal config, and can also be used in the locales option.
Type: boolean
Default: true
Details:
Enable color mode switching or not.
If set to true
, a button to switch color mode will be displayed in the navbar.
Type: string
Default: /
Details:
Specify the path of the homepage.
This will be used for:
Type: false | (NavbarItem | NavbarGroup | string)[]
Default: []
Details:
Configuration of navbar.
Set to false
to disable navbar.
To configure the navbar items, you can set it to a navbar array, each item of which could be a NavbarItem
object, a NavbarGroup
object, or a string:
NavbarItem
object should have a text
field and a link
field, could have an optional activeMatch
field.NavbarGroup
object should have a text
field and a children
field. The children
field should be a navbar array, too.NavbarItem
object, using the page title as text
, and the page route path as link
.Example 1:
export default {
+ theme: defaultTheme({
+ navbar: [
+ // NavbarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ },
+ // NavbarGroup
+ {
+ text: 'Group',
+ children: ['/group/foo.md', '/group/bar.md'],
+ },
+ // string - page file path
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ navbar: [
+ // nested group - max depth is 2
+ {
+ text: 'Group',
+ children: [
+ {
+ text: 'SubGroup',
+ children: ['/group/sub/foo.md', '/group/sub/bar.md'],
+ },
+ ],
+ },
+ // control when should the item be active
+ {
+ text: 'Group 2',
+ children: [
+ {
+ text: 'Always active',
+ link: '/',
+ // this item will always be active
+ activeMatch: '/',
+ },
+ {
+ text: 'Active on /foo/',
+ link: '/not-foo/',
+ // this item will be active when current route path starts with /foo/
+ // regular expression is supported
+ activeMatch: '^/foo/',
+ },
+ ],
+ },
+ ],
+ }),
+}
+
Type: null | string
Details:
Specify the url of logo image.
The logo image will be displayed at the left end of the navbar.
Set to null
to disable logo.
Example:
export default {
+ theme: defaultTheme({
+ // public file path
+ logo: '/hero.png',
+ // url
+ logo: 'https://vuejs.org/images/logo.png',
+ }),
+}
+
Type: null | string
Details:
Specify the url of logo image to be used in dark mode.
You can make use of this option if you want to use different logo config in dark mode.
Set to null
to disable logo in dark mode. Omit this option to use logo in dark mode.
Also see:
Type: null | string
Details:
Specify the alt text of the logo image.
If not specified, defaults to be the same as the site title.
Type: string
Details:
Specify the repository url of your project.
This will be used as the link of the repository link, which will be displayed as the last item of the navbar.
export default {
+ theme: defaultTheme({
+ // If you set it in the form of \`organization/repository\`
+ // we will take it as a GitHub repo
+ repo: 'vuejs/vuepress',
+ // You can also set it to a URL directly
+ repo: 'https://gitlab.com/foo/bar',
+ }),
+}
+
Set to false
to disable sidebar.
If you set it to 'auto'
, the sidebar will be automatically generated from the page headers.
To configure the sidebar items manually, you can set this option to a sidebar array, each item of which could be a SidebarItem
object or a string:
SidebarItem
object should have a text
field, could have an optional link
field, an optional children
field and an optional collapsible
field. The children
field should be a sidebar array. The collapsible
field controls whether the item is collapsible.SidebarItem
object, whose text
is the page title, link
is the page route path, and children
is automatically generated from the page headers.If you want to set different sidebar for different sub paths, you can set this option to a sidebar object:
'heading'
to automatically generate the sidebar from the page headers for just the corresponding path.export default {
+ theme: defaultTheme({
+ // sidebar array
+ // all pages will use the same sidebar
+ sidebar: [
+ // SidebarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ children: [
+ // SidebarItem
+ {
+ text: 'github',
+ link: 'https://github.com',
+ children: [],
+ },
+ // string - page file path
+ '/foo/bar.md',
+ ],
+ },
+ // string - page file path
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // sidebar object
+ // pages under different sub paths will use different sidebar
+ sidebar: {
+ '/guide/': [
+ {
+ text: 'Guide',
+ children: ['/guide/introduction.md', '/guide/getting-started.md'],
+ },
+ ],
+ '/reference/': 'heading',
+ },
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // collapsible sidebar
+ sidebar: {
+ '/reference/': [
+ {
+ text: 'VuePress Reference',
+ collapsible: true,
+ children: ['/reference/cli.md', '/reference/config.md'],
+ },
+ {
+ text: 'Bundlers Reference',
+ collapsible: true,
+ children: [
+ '/reference/bundler/vite.md',
+ '/reference/bundler/webpack.md',
+ ],
+ },
+ ],
+ },
+ }),
+}
+
Details:
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
0
to disable all levels of headers.1
to include <h2>
headers.2
to include <h2>
and <h3>
headers.Type: string
Details:
Specify the pattern of the edit this page link.
This will be used for generating the edit this page link.
If you don't set this option, the pattern will be inferred from the docsRepo option. But if your documentation repository is not hosted on a common platform, for example, GitHub, GitLab, Bitbucket, Gitee, etc., you have to set this option explicitly to make the edit this page link work.
Usage:
Pattern | Description |
---|---|
:repo | The docs repo url, i.e. docsRepo |
:branch | The docs repo branch, i.e. docsBranch |
:path | The path of the page source file, i.e. docsDir joins the relative path of the page file |
Example:
export default {
+ theme: defaultTheme({
+ docsRepo: 'https://gitlab.com/owner/name',
+ docsBranch: 'master',
+ docsDir: 'docs',
+ editLinkPattern: ':repo/-/edit/:branch/:path',
+ }),
+}
+
The generated link will look like 'https://gitlab.com/owner/name/-/edit/master/docs/path/to/file.md'
.
Type: string
Details:
Specify the repository url of your documentation source files.
This will be used for generating the edit this page link.
If you don't set this option, it will use the repo option by default. But if your documentation source files are in a different repository, you will need to set this option.
Type: string
Default: 'main'
Details:
Specify the repository branch of your documentation source files.
This will be used for generating the edit this page link.
Type: string
Default: ''
Details:
Specify the directory of your documentation source files in the repository.
This will be used for generating the edit this page link.
类型:string
必填:是
详情:
部署域名
类型:Author
type AuthorName = string
+
+interface AuthorInfo {
+ /**
+ * 作者姓名
+ */
+ name: string
+
+ /**
+ * 作者网站
+ */
+ url?: string
+
+ /**
+ * 作者 Email
+ */
+ email?: string
+}
+
+type Author = AuthorName | AuthorName[] | AuthorInfo | AuthorInfo[]
+
详情:
默认作者
类型:boolean
默认值:true
详情:
是否自动生成描述
类型:string | ((page: Page) => string | null)
详情:
首选链接
类型:string
详情:
当找不到图片时的回退图片链接
类型:string
详情:
内容的年龄分级,格式为 [int]+
,如 "13+"
类型:string
详情:
你的 twitter 用户名
类型:(page: Page) => boolean
详情:
你可以使用此选项判断一个页面是否是文章。
类型:
function ogp(
+ /** 插件推断的 OGP 信息 */
+ ogp: SeoContent,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
详情:
自定义 OGP 生成器
你可以使用此选项来注入新的或覆盖掉默认生成的 OGP 标签。
类型:
function jsonLd(
+ /** 由插件推断出的 JSON-LD 对象 */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
详情:
自定义 JSON-LD 生成器
你可以使用此选项来注入新的或覆盖掉默认生成的 JSON-LD 标签。
类型:
function customHead(
+ /** head 标签配置 */
+ head: HeadConfig[],
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
详情:
你可以使用此选项来直接注入任意格式的标签到 <head>
。
string
部署网站的域名。
boolean
false
是否启用 Atom 格式输出。
boolean
false
是否启用 JSON 格式输出。
boolean
false
是否启用 RSS 格式输出。
string
一个大的图片,用作 feed 展示。
string
一个小的图标,显示在订阅列表中。
number
100
设置 feed 的最大项目数量。在所有页面排序好后,插件会截取前 count 个项目。
如果你的站点文章很多,你应该考虑设置这个选项以减少 feed 文件大小。
(RegExp | string)[] | (tagName:string) => boolean
应在 Feed 中保留的自定义元素或组件。
默认情况下,所有未知标签均会被移除。
类型:(page: Page)=> boolean
默认值:
;({ frontmatter, filePathRelative }: Page): boolean =>
+ !(
+ frontmatter.home ||
+ !filePathRelative ||
+ frontmatter.article === false ||
+ frontmatter.feed === false
+ )
+
自定义的过滤函数,用于过滤哪些项目在 feed 中显示。
类型: (pageA: Page, pageB: Page)=> number
默认值:
// dateSorter 来源于 @vuepress/helper
+;(pageA, pageB): number =>
+ dateSorter(
+ pageA.data.git?.createdTime
+ ? new Date(pageA.data.git?.createdTime)
+ : pageA.frontmatter.date,
+ pageB.data.git?.createdTime
+ ? new Date(pageB.data.git?.createdTime)
+ : pageB.frontmatter.date,
+ )
+
Feed 项目的排序器。
默认的排序行为是通过 Git 的文件添加日期 (需要 @vuepress/plugin-git
)。
提示
你应该启用 @vuepress/plugin-git
来获取最新创建的页面作为 feed 项目。否则,feed 项目将按照 VuePress 中页面的默认顺序排序。
channel
选项用于配置 Feed 频道。
boolean
false
是否在开发服务器中启用
提示
由于性能原因,我们不提供热更新。重启开发服务器以同步你的变更。
string
"http://localhost:${port}"
开发服务器使用的主机名
string
"atom.xml"
Atom 格式输出路径,相对于输出路径。
string
@vuepress/plugin-feed/templates/atom.xsl
的内容Atom xsl 模板文件没人陪美国
string
"atom.xsl"
Atom xsl 输出路径,相对于输出路径。
string
"feed.json"
JSON 格式输出路径,相对于输出路径。
string
"rss.xml"
RSS 格式输出路径,相对于输出路径。
string
@vuepress/plugin-feed/templates/rss.xsl
的内容RSS xsl 模板文件内容。
string
"rss.xsl"
RSS xsl 输出路径,相对于输出路径。
类型: string
详情:
部署的域名,例如 https://example.com
该章节内的配置项可以作为一般配置使用,也可以使用在 locales 内。
类型: boolean
默认值: true
详情:
是否启用切换颜色模式的功能。
如果设置为 true
,将会在导航栏展示一个切换颜色模式的按钮。
类型: string
默认值: /
详情:
首页的路径。
它将被用于:
类型: false | (NavbarItem | NavbarGroup | string)[]
默认值: []
详情:
导航栏配置。
设置为 false
可以禁用导航栏。
为了配置导航栏元素,你可以将其设置为 导航栏数组 ,其中的每个元素是 NavbarItem
对象、 NavbarGroup
对象、或者字符串:
NavbarItem
对象应该有一个 text
字段和一个 link
字段,还有一个可选的 activeMatch
字段。NavbarGroup
对象应该有一个 text
字段和一个 children
字段。 children
字段同样是一个 导航栏数组 。NavbarItem
对象,将页面标题作为 text
,将页面路由路径作为 link
。示例 1:
export default {
+ theme: defaultTheme({
+ navbar: [
+ // NavbarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ },
+ // NavbarGroup
+ {
+ text: 'Group',
+ children: ['/group/foo.md', '/group/bar.md'],
+ },
+ // 字符串 - 页面文件路径
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ navbar: [
+ // 嵌套 Group - 最大深度为 2
+ {
+ text: 'Group',
+ children: [
+ {
+ text: 'SubGroup',
+ children: ['/group/sub/foo.md', '/group/sub/bar.md'],
+ },
+ ],
+ },
+ // 控制元素何时被激活
+ {
+ text: 'Group 2',
+ children: [
+ {
+ text: 'Always active',
+ link: '/',
+ // 该元素将一直处于激活状态
+ activeMatch: '/',
+ },
+ {
+ text: 'Active on /foo/',
+ link: '/not-foo/',
+ // 该元素在当前路由路径是 /foo/ 开头时激活
+ // 支持正则表达式
+ activeMatch: '^/foo/',
+ },
+ ],
+ },
+ ],
+ }),
+}
+
类型: null | string
详情:
Logo 图片的 URL。
Logo 图片将会显示在导航栏的左端。
设置为 null
可以禁用 Logo 。
示例:
export default {
+ theme: defaultTheme({
+ // Public 文件路径
+ logo: '/images/hero.png',
+ // URL
+ logo: 'https://vuejs.org/images/logo.png',
+ }),
+}
+
类型: null | string
详情:
在夜间模式中使用的 Logo 图片的 URL。
如果你想在夜间模式中使用不同的 Logo 图片,就可以使用该配置项。
设置为 null
可以在夜间模式下禁用 Logo 。忽略该配置项将会在夜间模式中使用 logo 配置。
参考:
类型:null | string
详情:
指定 Logo 图片的替代文字。
当未指定时,将默认与站点标题相同。
类型: string
详情:
项目仓库的 URL。
它将被用作 仓库链接 的链接。仓库链接 将会显示为导航栏的最后一个元素。
export default {
+ theme: defaultTheme({
+ // 如果你按照 \`organization/repository\` 的格式设置它
+ // 我们会将它作为一个 GitHub 仓库
+ repo: 'vuejs/vuepress',
+ // 你也可以直接将它设置为一个 URL
+ repo: 'https://gitlab.com/foo/bar',
+ }),
+}
+
设置为 false
可以禁用侧边栏。
如果你设置为 'auto'
,侧边栏会根据页面标题自动生成。
为了手动配置侧边栏元素,你可以将其设置为 侧边栏数组 ,其中的每个元素是一个 SidebarItem
对象或者一个字符串:
SidebarItem
对象应该有一个 text
字段,有一个可选的 link
字段、一个可选的 children
字段和一个可选的 collapsible
字段。 children
字段同样是一个 侧边栏数组 。 collapsible
字段来控制它是否可折叠。SidebarItem
对象,将页面标题作为 text
,将页面路由路径作为 link
,并根据页面小标题自动生成 children
。如果你想在不同子路径中使用不同的侧边栏,你可以将该配置项设置为 侧边栏对象 :
"heading"
以自动为相应路径生成基于标题的侧边栏。export default {
+ theme: defaultTheme({
+ // 侧边栏数组
+ // 所有页面会使用相同的侧边栏
+ sidebar: [
+ // SidebarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ children: [
+ // SidebarItem
+ {
+ text: 'github',
+ link: 'https://github.com',
+ children: [],
+ },
+ // 字符串 - 页面文件路径
+ '/foo/bar.md',
+ ],
+ },
+ // 字符串 - 页面文件路径
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // 侧边栏对象
+ // 不同子路径下的页面会使用不同的侧边栏
+ sidebar: {
+ '/guide/': [
+ {
+ text: 'Guide',
+ children: ['/guide/introduction.md', '/guide/getting-started.md'],
+ },
+ ],
+ '/reference/': 'heading',
+ },
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // 可折叠的侧边栏
+ sidebar: {
+ '/reference/': [
+ {
+ text: 'VuePress Reference',
+ collapsible: true,
+ children: ['/reference/cli.md', '/reference/config.md'],
+ },
+ {
+ text: 'Bundlers Reference',
+ collapsible: true,
+ children: [
+ '/reference/bundler/vite.md',
+ '/reference/bundler/webpack.md',
+ ],
+ },
+ ],
+ },
+ }),
+}
+
详情:
设置根据页面标题自动生成的侧边栏的最大深度。
0
来禁用所有级别的页面标题。1
来包含 <h2>
标题。2
来包含 <h2>
和 <h3>
标题。类型: string
详情:
编辑此页 链接的 Pattern 。
它将会用于生成 编辑此页 的链接。
如果你不设置该选项,则会根据 docsRepo 配置项来推断 Pattern 。但是如果你的文档仓库没有托管在常用的平台上,比如 GitHub 、 GitLab 、 Bitbucket 、 Gitee 等,那么你必须设置该选项才能使 编辑此页 链接正常工作。
用法:
Pattern | 描述 |
---|---|
:repo | 文档仓库 URL ,即 docsRepo |
:branch | 文档仓库分支 ,即 docsBranch |
:path | 页面源文件的路径,即 docsDir 拼接上页面文件的相对路径 |
示例:
export default {
+ theme: defaultTheme({
+ docsRepo: 'https://gitlab.com/owner/name',
+ docsBranch: 'master',
+ docsDir: 'docs',
+ editLinkPattern: ':repo/-/edit/:branch/:path',
+ }),
+}
+
则会生成类似于 'https://gitlab.com/owner/name/-/edit/master/docs/path/to/file.md'
的链接。
类型: string
详情:
文档源文件的仓库 URL 。
它将会用于生成 编辑此页 的链接。
如果你不设置该选项,则默认会使用 repo 配置项。但是如果你的文档源文件是在一个不同的仓库内,你就需要设置该配置项了。
类型: string
默认值: 'main'
详情:
文档源文件的仓库分支。
它将会用于生成 编辑此页 的链接。
类型: string
默认值: ''
详情:
文档源文件存放在仓库中的目录名。
它将会用于生成 编辑此页 的链接。
npm i -D @vuepress/plugin-container@next
+
import { containerPlugin } from '@vuepress/plugin-container'
+
+export default {
+ plugins: [
+ containerPlugin({
+ // 配置项
+ }),
+ ],
+}
+
::: <type> [info]
+[content]
+:::
+
type
是必需的,应通过 type 配置项来指定。info
是可选的,其默认值可以通过 locales 的 defaultInfo
配置项来指定。content
可是任何合法的 Markdown 内容。提示
该插件可以被多次使用,以便支持不同类型的容器。
类型: Record<string, { defaultInfo: string }>
详情:
容器在不同 locales 下的默认 info
。
如果没有指定该配置项,默认 info
会使用大写的 type 。
示例:
export default {
+ plugins: [
+ containerPlugin({
+ type: 'tip',
+ locales: {
+ '/': {
+ defaultInfo: 'TIP',
+ },
+ '/zh/': {
+ defaultInfo: '提示',
+ },
+ },
+ }),
+ ],
+}
+
类型: (info: string) => string
默认值:
(info: string): string =>
+ \`<div class="custom-container \${type}">\${info ? \`<p class="custom-container-title">\${info}</p>\` : ''}\\n\`
+
类型: (info: string) => string
默认值:
(): string => '</div>\\n'
+
type MarkdownItContainerRenderFunction = (
+ tokens: Token[],
+ index: number,
+ options: any,
+ env: MarkdownEnv,
+ self: Renderer,
+) => string
+
npm i -D @vuepress/plugin-container@next
+
import { containerPlugin } from '@vuepress/plugin-container'
+
+export default {
+ plugins: [
+ containerPlugin({
+ // options
+ }),
+ ],
+}
+
::: <type> [info]
+[content]
+:::
+
type
is required and should be specified via type option.info
is optional, and the default value can be specified via defaultInfo
in locales option.content
can be any valid markdown content.TIP
This plugin can be used multiple times to support different types of containers.
Type: Record<string, { defaultInfo: string }>
Details:
The default info
of the container in different locales.
If this option is not specified, the default info
will fallback to the uppercase of the type option.
Example:
export default {
+ plugins: [
+ containerPlugin({
+ type: 'tip',
+ locales: {
+ '/': {
+ defaultInfo: 'TIP',
+ },
+ '/zh/': {
+ defaultInfo: '提示',
+ },
+ },
+ }),
+ ],
+}
+
Type: (info: string) => string
Default:
(info: string): string =>
+ \`<div class="custom-container \${type}">\${info ? \`<p class="custom-container-title">\${info}</p>\` : ''}\\n\`
+
Details:
A function to render the starting tag of the container.
The first param is the info
part of container syntax.
This option will not take effect if you don't specify the after option.
Type: (info: string) => string
Default:
(): string => '</div>\\n'
+
Details:
A function to render the ending tag of the container.
The first param is the info
part of container syntax.
This option will not take effect if you don't specify the before option.
type MarkdownItContainerRenderFunction = (
+ tokens: Token[],
+ index: number,
+ options: any,
+ env: MarkdownEnv,
+ self: Renderer,
+) => string
+
This plugin will automatically add a copy button to the top right corner of each code block on PC devices.
The default selector matches @vuepress/theme-default
, so you might need to change it when integrating your own theme.
npm i -D @vuepress/plugin-copy-code@next
+
import { copyCodePlugin } from '@vuepress/plugin-copy-code'
+
+export default {
+ plugins: [
+ copyCodePlugin({
+ // options
+ }),
+ ],
+}
+
Type: string | string[]
Default: '.theme-default-content div[class*="language-"] pre'
Details:
Code block selector
Type: boolean
Default: false
Details:
Whether to display copy button on the mobile device
Type: number
Default: 2000
Details:
Hint display time, setting it to 0
will disable the hint.
Type: number
Default: 800
Details:
The delay of registering copy code buttons, in ms.
If the theme you are using has a switching animation, it is recommended to configure this option to Switch animation duration + 200
.
Type: CopyCodeLocaleConfig
interface CopyCodeLocaleData {
+ /**
+ * Copy text
+ */
+ copy: string
+
+ /**
+ * Copied text
+ */
+ copied: string
+}
+
+interface CopyCodeLocaleConfig {
+ [localePath: string]: CopyCodeLocaleData
+}
+
Required: No
Details:
Locales config for copy code plugin.
Example:
import { copyCodePlugin } from 'vuepress-plugin-copy-code2'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyCodePlugin({
+ locales: {
+ '/': {
+ // Override copy button label text
+ copy: 'Copy Codes from code block',
+ },
+
+ '/xx/': {
+ // Complete locale config for \`mm-NN\` language here
+ },
+ },
+ }),
+ ],
+}
+
You can customize the icon of the copy button via CSS variables:
:root {
+ --code-copy-icon: url("copy-button.svg");
+ --code-copied-icon: url("copied-button.svg");
+ --copy-code-color: var(--code-ln-color, #9e9e9e);
+ --copy-code-hover: var(--code-hl-bg-color, rgb(0 0 0 / 66%));
+}
+
此插件会自动在 PC 设备上为每个代码块右上角添加复制按钮。
默认选择器匹配 @vuepress/theme-default
,所以在你自己的主题中集成时可能需要调整它。
npm i -D @vuepress/plugin-copy-code@next
+
import { copyCodePlugin } from '@vuepress/plugin-copy-code'
+
+export default {
+ plugins: [
+ copyCodePlugin({
+ // options
+ }),
+ ],
+}
+
类型:string | string[]
默认值:'.theme-default-content div[class*="language-"] pre'
详情:
代码块选择器
类型:boolean
默认值:false
详情:
是否展示在移动端
类型:number
默认值:2000
详情:
提示消息显示时间,设置为 0
会禁用提示。
类型:number
默认值:800
详情:
注册复制按钮的延时,单位 ms。
如果你使用的主题有切换动画,建议配置此选项为 切换动画时长 + 200
类型:CopyCodeLocaleConfig
interface CopyCodeLocaleData {
+ /**
+ * 复制文字
+ */
+ copy: string
+
+ /**
+ * 已复制文字
+ */
+ copied: string
+}
+
+interface CopyCodeLocaleConfig {
+ [localePath: string]: CopyCodeLocaleData
+}
+
必填:否
详情:
复制按钮插件的国际化配置。
示例:
import { copyCodePlugin } from 'vuepress-plugin-copy-code2'
+
+export default {
+ locales: {
+ '/': {
+ // 这是一个支持的语言
+ lang: 'zh-CN',
+ },
+ '/xx/': {
+ // 这是一个没有收到插件支持的语言
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyCodePlugin({
+ locales: {
+ '/': {
+ // 覆盖复制按钮标签文字
+ copy: '复制此段代码',
+ },
+
+ '/xx/': {
+ // 在这里完整设置 \`mm-NN\` 的多语言配置
+ },
+ },
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义复制按钮的样式:
:root {
+ --code-copy-icon: url("copy-button.svg");
+ --code-copied-icon: url("copied-button.svg");
+ --copy-code-color: var(--code-ln-color, #9e9e9e);
+ --copy-code-hover: var(--code-hl-bg-color, rgb(0 0 0 / 66%));
+}
+
此插件可以在访问者从你的站点复制内容时,自动追加版权信息,也可以禁止站点的复制或者选择。
npm i -D @vuepress/plugin-copyright@next
+
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ plugins: [
+ copyrightPlugin({
+ // options
+ }),
+ ],
+}
+
此插件默认全局禁用。你可以:
copy: true
手动开启。global: true
让其全局生效,并在页面的 frontmatter 中设置 copy: false
禁用它。处于不打扰用户的考虑,默认配置下仅当复制长度超过 100 时才会追加版权信息。如果你希望改变这个触发值,你可以插件选项中设置 triggerLength
,或在页面 frontmatter 单独设置 copy.triggerLength
。
你可以通过插件的 author
和 license
选项设置全局作者和协议信息。
如果文档的不同部分拥有不同的作者和协议,你可以通过 authorGetter
和 licenseGetter
传入一个使用当前页面对象作为参数的函数 (page: Page) => string
并通过它返回相应信息。
插件会默认通过模板从作者、协议和页面链接生成版权信息,并在复制时追加。如果你认为这不够灵活,你可以设置 copyrightGetter
返回一个完全由你自定义的版权信息,或返回 null 以使用默认模板。
如果你希望禁止用户复制较长内容,你可以在插件选项中设置 maxLength
控制这个临界值,或在页面 frontmatter 单独设置 copy.maxLength
。
disableCopy
或在页面 frontmatter 中设置 copy.disableCopy
来禁用复制,后者具有更高优先级。disableSelection
或在页面 frontmatter 中设置 copy.disableSelection
来禁用文字选择。此选项具有更高优先级string
string
(page: Page) => string | null
(page: Page) => string | null
(page: Page) => string | null
number
100
number
0
0
意味着无限制。boolean
false
boolean
false
boolean
false
类型:string
详情:
首选部署位置。
例子
如果你在 https://myblog.com
和 https://blog.com/username/
下部署相同的内容,你可能希望选择一个站点作为首选链接。
canonical
设置为 https://myblog.com
canonical
设置为 https://blog.com/username/
这样,在另一个站点触发的版权信息也会指向你的首选站点。
类型:CopyrightLocaleConfig
interface CopyrightLocaleData {
+ /**
+ * 作者文字
+ *
+ * @description \`:author\` 将会被作者替换
+ */
+ author: string
+
+ /**
+ * 协议文字
+ *
+ * @description \`:license\` 会被当前协议替换
+ */
+ license: string
+
+ /**
+ * 链接文字
+ *
+ * @description \`:link\` 会替换为当前页面链接
+ */
+ link: string
+}
+
+interface CopyrightLocaleConfig {
+ [localePath: string]: CopyrightLocaleData
+}
+
详情:版权插件的国际化配置。
示例:
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyrightPlugin({
+ locales: {
+ '/': {
+ // Override link text
+ link: 'Original posted at :link',
+ },
+
+ '/xx/': {
+ // Complete locale config for \`mm-NN\` language here
+ },
+ },
+ }),
+ ],
+}
+
number
100
number
0
0
意味着无限制。boolean
false
boolean
false
This plugin can automatically append copyright information when visitors copy content from your site, and can also prohibit site copying or selection.
npm i -D @vuepress/plugin-copyright@next
+
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ plugins: [
+ copyrightPlugin({
+ // options
+ }),
+ ],
+}
+
This plugin is disabled globally by default, you can:
copy: true
in page frontmatterglobal: true
in plugin options to enable it globally, and set copy: false
in page frontmatter to disable it.To avoid disturbing visitors, copyright information will be appended only when the copied content length is greater than 100. Set triggerLength
in plugin options if you want to change this threshold, or via copy.triggerLength
in page frontmatter.
You can set default author and license information via author
and license
in plugin options.
If your site have different authors and license in different pages, you can set authorGetter
and licenseGetter
with function (page: Page) => string
that takes the current page object as parameter and returns the corresponding information.
The plugin will generate copyright information from author, license, and page link via template by default, and append it when copying. If you think that this is not flexible enough, you can set copyrightGetter
option to return a completely customized information with Page object or return null to use the default template.
If you want to prevent users copying long content, you can set maxLength
in plugin options to customize this limit, or via copy.maxLength
in page frontmatter.
disableCopy
in plugin options or copy.disableCopy
in page frontmatter, the latter has higher priority.disableSelection
in plugin options or copy.disableSelection
in page frontmatter. This option has higher priority.string
string
(page: Page) => string | null
(page: Page) => string | null
(page: Page) => string | null
number
100
number
0
0
means no limit.boolean
false
boolean
false
boolean
false
string
Example
If you are deploying same content under https://myblog.com
and https://blog.com/username/
, you may want to prefer one site as reference link.
canonical
to https://myblog.com
canonical
to https://blog.com/username/
So copyright message triggered on another site also points to your preferred site.
Type: CopyrightLocaleConfig
interface CopyrightLocaleData {
+ /**
+ * Author text
+ *
+ * @description \`:author\` will be replaced by author
+ */
+ author: string
+
+ /**
+ * License text
+ *
+ * @description \`:license\` will be replaced by current license
+ */
+ license: string
+
+ /**
+ * Link text
+ *
+ * @description \`:link\` will be replaced by current page link
+ */
+ link: string
+}
+
+interface CopyrightLocaleConfig {
+ [localePath: string]: CopyrightLocaleData
+}
+
Details: Locale config for copyright plugin.
Example:
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyrightPlugin({
+ locales: {
+ '/': {
+ // Override link text
+ link: 'Original posted at :link',
+ },
+
+ '/xx/': {
+ // Complete locale config for \`mm-NN\` language here
+ },
+ },
+ }),
+ ],
+}
+
number
100
number
0
0
means no limit.boolean
false
boolean
false
提示
当你正确配置该插件后,默认主题会把 DocSearch 按钮添加到导航栏。
该插件不一定能在其他主题中直接使用,因此你应参考主题本身的文档来获取更多信息。
npm i -D @vuepress/plugin-docsearch@next
+
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
+
+export default {
+ plugins: [
+ docsearchPlugin({
+ // 配置项
+ }),
+ ],
+}
+
new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ startUrls: [
+ // 这是 Algolia 开始抓取网站的初始地址
+ // 如果你的网站被分为数个独立部分,你可能需要在此设置多个入口链接
+ 'https://YOUR_WEBSITE_URL/',
+ ],
+ sitemaps: [
+ // 如果你在使用 Sitemap 插件 (如: @vuepress-plugin/sitemap),你可以提供 Sitemap 链接
+ 'https://YOUR_WEBSITE_URL/sitemap.xml',
+ ],
+ ignoreCanonicalTo: false,
+ exclusionPatterns: [
+ // 你可以通过它阻止 Algolia 抓取某些 URL
+ ],
+ discoveryPatterns: [
+ // 这是 Algolia 抓取 URL 的范围
+ 'https://YOUR_WEBSITE_URL/**',
+ ],
+ // 爬虫执行的计划时间,可根据文档更新频率设置
+ schedule: 'at 02:00 every 1 day',
+ actions: [
+ // 你可以拥有多个 action,特别是你在一个域名下部署多个文档时
+ {
+ // 使用适当的名称为索引命名
+ indexName: 'YOUR_INDEX_NAME',
+ // 索引生效的路径
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ // 控制 Algolia 如何抓取你的站点
+ recordExtractor: ({ $, helpers }) => {
+ // @vuepress/theme-default 的选项
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ lvl6: '.theme-default-content h6',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ })
+ },
+ },
+ ],
+ initialIndexSettings: {
+ // 控制索引如何被初始化,这仅当索引尚未生成时有效
+ // 你可能需要在修改后手动删除并重新生成新的索引
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ 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',
+ },
+ },
+})
+
上述 recordProps
是用于默认主题的配置,你可以根据你使用的主题来修改它们。
注意 initialIndexSettings.YOUR_INDEX_NAME.attributesForFaceting
字段必须包含 'lang'
,否则该插件将无法正常工作。
类型: Record<string, DocsearchPluginOptions>
详情:
在不同 locales 下对该插件进行不同的配置。
该插件的所有其他选项都可以在 locale 中进行配置。
示例:
export default {
+ plugins: [
+ docsearchPlugin({
+ appId: '<APP_ID>',
+ apiKey: '<API_KEY>',
+ indexName: '<INDEX_NAME>',
+ locales: {
+ '/': {
+ placeholder: 'Search Documentation',
+ translations: {
+ button: {
+ buttonText: 'Search Documentation',
+ },
+ },
+ },
+ '/zh/': {
+ placeholder: '搜索文档',
+ translations: {
+ button: {
+ buttonText: '搜索文档',
+ },
+ },
+ },
+ },
+ }),
+ ],
+}
+
类型: boolean
默认值: true
详情:
是否注入 DocSearch 的默认样式。
如果你认为 DocSearch 的默认样式和你的站点不兼容,你可以尝试覆盖默认样式,或者将该选项设置为 false
来完全移除默认样式。
当该选项被禁用时,你需要为 DocSearch 引入你自己的样式。同时要注意,你也无法再使用 样式 章节中提到的样式自定义能力。
:root {
+ --docsearch-primary-color: rgb(84, 104, 255);
+ --docsearch-text-color: rgb(28, 30, 33);
+ --docsearch-spacing: 12px;
+ --docsearch-icon-stroke-width: 1.4;
+ --docsearch-highlight-color: var(--docsearch-primary-color);
+ --docsearch-muted-color: rgb(150, 159, 175);
+ --docsearch-container-background: rgba(101, 108, 133, 0.8);
+ --docsearch-logo-color: rgba(84, 104, 255);
+
+ /* modal */
+ --docsearch-modal-width: 560px;
+ --docsearch-modal-height: 600px;
+ --docsearch-modal-background: rgb(245, 246, 247);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px
+ 8px 0 rgba(85, 90, 100, 1);
+
+ /* searchbox */
+ --docsearch-searchbox-height: 56px;
+ --docsearch-searchbox-background: rgb(235, 237, 240);
+ --docsearch-searchbox-focus-background: #fff;
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
+
+ /* hit */
+ --docsearch-hit-height: 56px;
+ --docsearch-hit-color: rgb(68, 73, 80);
+ --docsearch-hit-active-color: #fff;
+ --docsearch-hit-background: #fff;
+ --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225);
+
+ /* key */
+ --docsearch-key-gradient: linear-gradient(
+ -225deg,
+ rgb(213, 219, 228) 0%,
+ rgb(248, 248, 248) 100%
+ );
+ --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px
+ #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4);
+
+ /* footer */
+ --docsearch-footer-height: 44px;
+ --docsearch-footer-background: #fff;
+ --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
+}
+
详情:
该插件会全局注册一个 <Docsearch />
组件,你可以不传入任何 Props 来使用它。
将该组件放置在你想要显示 docsearch 按钮的地方。例如,默认主题将这个组件放在了导航栏的末尾。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
TIP
Default theme will add DocSearch to the navbar once you configure this plugin correctly.
This plugin may not be used directly in other themes, so you'd better refer to the documentation of your theme for more details.
npm i -D @vuepress/plugin-docsearch@next
+
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
+
+export default {
+ plugins: [
+ docsearchPlugin({
+ // options
+ }),
+ ],
+}
+
new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ startUrls: [
+ // These are urls which algolia start to craw
+ // If your site is divided in to mutiple parts,
+ // you may want to set mutiple entry links
+ 'https://YOUR_WEBSITE_URL/',
+ ],
+ sitemaps: [
+ // if you are using sitemap plugins (e.g.: @vuepress-plugin/sitemap), you may provide one
+ 'https://YOUR_WEBSITE_URL/sitemap.xml',
+ ],
+ ignoreCanonicalTo: false,
+ exclusionPatterns: [
+ // You can use this to stop algolia crawing some paths
+ ],
+ discoveryPatterns: [
+ // These are urls which algolia looking for,
+ 'https://YOUR_WEBSITE_URL/**',
+ ],
+ // Crawler schedule, set it according to your docs update frequency
+ schedule: 'at 02:00 every 1 day',
+ actions: [
+ // you may have mutiple actions, especially when you are deploying mutiple docs under one domain
+ {
+ // name the index with name you like
+ indexName: 'YOUR_INDEX_NAME',
+ // paths where the index take effect
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ // controls how algolia extracts records from your site
+ recordExtractor: ({ $, helpers }) => {
+ // options for @vuepress/theme-default
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ lvl6: '.theme-default-content h6',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ })
+ },
+ },
+ ],
+ initialIndexSettings: {
+ // controls how index are initialized
+ // only has effects before index are initialize
+ // you may need to delete your index and recraw after modification
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ 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 above recordProps
is the configuration used for the default theme. You can modify them according to the theme you are using.
Notice that the initialIndexSettings.YOUR_INDEX_NAME.attributesForFaceting
fields must include 'lang'
to make this plugin work properly.
Type: Record<string, DocsearchPluginOptions>
Details:
Options of this plugin in different locales.
All other options of this plugin are acceptable in locale config.
Example:
export default {
+ plugins: [
+ docsearchPlugin({
+ appId: '<APP_ID>',
+ apiKey: '<API_KEY>',
+ indexName: '<INDEX_NAME>',
+ locales: {
+ '/': {
+ placeholder: 'Search Documentation',
+ translations: {
+ button: {
+ buttonText: 'Search Documentation',
+ },
+ },
+ },
+ '/zh/': {
+ placeholder: '搜索文档',
+ translations: {
+ button: {
+ buttonText: '搜索文档',
+ },
+ },
+ },
+ },
+ }),
+ ],
+}
+
Type: boolean
Default: true
Details:
Whether to inject the default styles of DocSearch or not.
If you think the default styles of DocSearch is not compatible with your site, you can try to override the default styles, or set this option to false
to totally exclude the default styles.
When this option is disabled, you need to import your own styles for DocSearch. Also notice that all styles customization in Styles section would be unavailable.
:root {
+ --docsearch-primary-color: rgb(84, 104, 255);
+ --docsearch-text-color: rgb(28, 30, 33);
+ --docsearch-spacing: 12px;
+ --docsearch-icon-stroke-width: 1.4;
+ --docsearch-highlight-color: var(--docsearch-primary-color);
+ --docsearch-muted-color: rgb(150, 159, 175);
+ --docsearch-container-background: rgba(101, 108, 133, 0.8);
+ --docsearch-logo-color: rgba(84, 104, 255);
+
+ /* modal */
+ --docsearch-modal-width: 560px;
+ --docsearch-modal-height: 600px;
+ --docsearch-modal-background: rgb(245, 246, 247);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px
+ 8px 0 rgba(85, 90, 100, 1);
+
+ /* searchbox */
+ --docsearch-searchbox-height: 56px;
+ --docsearch-searchbox-background: rgb(235, 237, 240);
+ --docsearch-searchbox-focus-background: #fff;
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
+
+ /* hit */
+ --docsearch-hit-height: 56px;
+ --docsearch-hit-color: rgb(68, 73, 80);
+ --docsearch-hit-active-color: #fff;
+ --docsearch-hit-background: #fff;
+ --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225);
+
+ /* key */
+ --docsearch-key-gradient: linear-gradient(
+ -225deg,
+ rgb(213, 219, 228) 0%,
+ rgb(248, 248, 248) 100%
+ );
+ --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px
+ #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4);
+
+ /* footer */
+ --docsearch-footer-height: 44px;
+ --docsearch-footer-background: #fff;
+ --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
+}
+
Details:
This plugin will register a <Docsearch />
component globally, and you can use it without any props.
Put this component to where you want to place the docsearch button. For example, default theme puts this component to the end of the navbar.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
VuePress 默认主题有着大量的用户,因此我们对它进行了一些便于继承的设计,以便用户轻松进行定制化。
默认主题的 Layout
布局提供了一些插槽:
navbar
navbar-before
navbar-after
sidebar
sidebar-top
sidebar-bottom
page
page-top
page-bottom
page-content-top
page-content-bottom
在它们的帮助下,你可以很容易地添加或替换内容。下面通过一个示例来介绍一下如何使用布局插槽来继承默认主题。
首先,创建一个客户端配置文件 .vuepress/client.ts
:
import { defineClientConfig } from 'vuepress/client'
+import Layout from './layouts/Layout.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout,
+ },
+})
+
接下来,创建 .vuepress/layouts/Layout.vue
,并使用由默认主题的 Layout
布局提供的插槽:
<script setup>
+import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'
+</script>
+
+<template>
+ <ParentLayout>
+ <template #page-bottom>
+ <div class="my-footer">This is my custom page footer</div>
+ </template>
+ </ParentLayout>
+</template>
+
+<style lang="css">
+.my-footer {
+ text-align: center;
+}
+</style>
+
此时默认的 Layout
布局已经被你的本地布局覆盖,将会在除了首页外的所有页面添加一个自定义的页脚:
布局插槽十分实用,但有时候你可能会觉得它不够灵活。默认主题同样提供了替换单个组件的能力。
',14),d={href:"https://github.com/vuepress/ecosystem/tree/main/themes/theme-default/src/client/components",target:"_blank",rel:"noopener noreferrer"},y=n("code",null,"@theme",-1),C={href:"https://v2.vuepress.vuejs.org/zh/reference/plugin-api.html#alias",target:"_blank",rel:"noopener noreferrer"},v=n("code",null,"HomeFooter.vue",-1),u=n("code",null,"@theme/HomeFooter.vue",-1),m=e(`接下来,如果你想要替换 HomeFooter.vue
组件,只需要在配置文件 .vuepress/config.ts
中覆盖这个别名即可:
import { defaultTheme } from '@vuepress/theme-default'
+import { getDirname, path } from 'vuepress/utils'
+import { defineUserConfig } from 'vuepress'
+
+const __dirname = getDirname(import.meta.url)
+
+export default defineUserConfig({
+ theme: defaultTheme(),
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+})
+
除了在 .vuepress/config.ts
和 .vuepress/client.ts
中直接扩展默认主题以外,你可以通过继承默认主题来开发一个你自己的主题:
import { defaultTheme, type DefaultThemeOptions } from '@vuepress/theme-default'
+import type { Theme } from 'vuepress/core'
+import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export const childTheme = (options: DefaultThemeOptions): Theme => {
+ return {
+ name: 'vuepress-theme-child',
+ extends: defaultTheme(options),
+
+ // 在子主题的客户端配置文件中覆盖布局
+ // 注意,你在发布到 NPM 之前会将 TS 构建为 JS ,因此这里需要设置为 JS 文件的路径
+ clientConfigFile: path.resolve(__dirname, './client.js'),
+
+ // 覆盖组件别名
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+ }
+}
+
VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
Default theme's Layout
provides some slots:
navbar
navbar-before
navbar-after
sidebar
sidebar-top
sidebar-bottom
page
page-top
page-bottom
page-content-top
page-content-bottom
With the help of them, you can add or replace content easily. Here comes an example to introduce how to extend default theme with layout slots.
Firstly, create a client config file .vuepress/client.ts
:
import { defineClientConfig } from 'vuepress/client'
+import Layout from './layouts/Layout.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout,
+ },
+})
+
Next, create the .vuepress/layouts/Layout.vue
, and make use of the slots that provided by the Layout
of default theme:
<script setup>
+import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'
+</script>
+
+<template>
+ <ParentLayout>
+ <template #page-bottom>
+ <div class="my-footer">This is my custom page footer</div>
+ </template>
+ </ParentLayout>
+</template>
+
+<style lang="css">
+.my-footer {
+ text-align: center;
+}
+</style>
+
Then the default Layout
layout has been overridden by your own local layout, which will add a custom footer to every normal pages in default theme (excluding homepage):
The layout slots are useful, but sometimes you might find it's not flexible enough. Default theme also provides the ability to replace a single component.
',14),D={href:"https://v2.vuepress.vuejs.org/plugin-api.html#alias",target:"_blank",rel:"noopener noreferrer"},y={href:"https://github.com/vuepress/ecosystem/tree/main/themes/theme-default/src/client/components",target:"_blank",rel:"noopener noreferrer"},u=n("code",null,"@theme",-1),m=n("code",null,"HomeFooter.vue",-1),v=n("code",null,"@theme/HomeFooter.vue",-1),C=l(`Then, if you want to replace the HomeFooter.vue
component, just override the alias in your config file .vuepress/config.ts
:
import { defaultTheme } from '@vuepress/theme-default'
+import { getDirname, path } from 'vuepress/utils'
+import { defineUserConfig } from 'vuepress'
+
+const __dirname = getDirname(import.meta.url)
+
+export default defineUserConfig({
+ theme: defaultTheme(),
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+})
+
Instead of extending the default theme directly in .vuepress/config.ts
and .vuepress/client.ts
, you can also develop your own theme extending the default theme:
import { defaultTheme, type DefaultThemeOptions } from '@vuepress/theme-default'
+import type { Theme } from 'vuepress/core'
+import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export const childTheme = (options: DefaultThemeOptions): Theme => {
+ return {
+ name: 'vuepress-theme-child',
+ extends: defaultTheme(options),
+
+ // override layouts in child theme's client config file
+ // notice that you would build ts to js before publishing to npm,
+ // so this should be the path to the js file
+ clientConfigFile: path.resolve(__dirname, './client.js'),
+
+ // override component alias
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+ }
+}
+
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-external-link-icon@next
+
import { externalLinkIconPlugin } from '@vuepress/plugin-external-link-icon'
+
+export default {
+ plugins: [
+ externalLinkIconPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, { openInNewWindow: string }>
Details:
The a11y text of the external link icon in different locales.
If this option is not specified, it will fallback to default text.
Example:
export default {
+ plugins: [
+ externalLinkIconPlugin({
+ locales: {
+ '/': {
+ openInNewWindow: 'open in new window',
+ },
+ '/zh/': {
+ openInNewWindow: '在新窗口打开',
+ },
+ },
+ }),
+ ],
+}
+
Type: boolean
Details:
Whether to append an external link icon to external links in current page.
You can customize the style of the external link icon via CSS variables:
:root {
+ --external-link-icon-color: #aaa;
+}
+
Details:
This plugin will register a <ExternalLinkIcon />
component globally, and you can use it without any props.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-external-link-icon@next
+
import { externalLinkIconPlugin } from '@vuepress/plugin-external-link-icon'
+
+export default {
+ plugins: [
+ externalLinkIconPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, { openInNewWindow: string }>
详情:
外部链接图标在不同 locales 下的 A11y 文字。
如果没有指定该配置项,它会降级使用默认文字。
示例:
export default {
+ plugins: [
+ externalLinkIconPlugin({
+ locales: {
+ '/': {
+ openInNewWindow: 'open in new window',
+ },
+ '/zh/': {
+ openInNewWindow: '在新窗口打开',
+ },
+ },
+ }),
+ ],
+}
+
类型: boolean
详情:
是否在当前页面的外部链接的后面添加外部链接图标。
你可以通过 CSS 变量来自定义外部链接图标的样式:
:root {
+ --external-link-icon-color: #aaa;
+}
+
详情:
该插件会全局注册一个 <ExternalLinkIcon />
组件,你可以不传入任何 Props 来使用它。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
你可以通过配置每个页面的 Frontmatter,来对每个 Feed 项目生成进行单独的控制。
默认情况下,所有文章均会被添加至 feed 流。如果你想在 feed 中移除特定页面,你可以在 frontmatter 中设置 feed: false
。
string
由 VuePress 自动生成,默认为页面的 h1 内容
string
页面描述
Date
页面的发布日期
boolean
该页面是否是文章
如果此项设置为
false
,则该页不会包含在最终的 feed 中。
string
页面版权信息
string
页面的封面/分享图,需为完整链接或绝对链接。
string
Feed 项目的标题
string
Feed 项目的描述
string
Feed 项目的内容
FeedAuthor[] | FeedAuthor
Feed 项目的作者
interface FeedAuthor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
FeedContributor[] | FeedContributor
Feed 项目的贡献者
interface FeedContributor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
string
Feed 项目的标识符,用于标识 Feed 项目。
你应该确保每个 Feed 项目有全局唯一的 guid。
类型: string
详情:
为当前页面添加额外的类名。
示例:
---
+pageClass: custom-page-class
+---
+
然后你可以在 .vuepress/styles/index.scss
文件中为这个页面添加自定义样式:
.theme-container.custom-page-class {
+ /* 页面样式 */
+}
+
本章节中的 Frontmatter 只会在首页中生效。
类型: boolean
详情:
设定该页面是首页还是普通页面。
如果你不设置该 Frontmatter 或将其设为 false
,则该页面会是一个 普通页面
示例:
---
+home: true
+---
+
类型: string
详情:
首页图片的 URL 。
示例:
---
+# Public 文件路径
+heroImage: /images/hero.png
+# URL
+heroImage: https://vuejs.org/images/logo.png
+---
+
类型: string
详情:
首页图片的 alt
属性。
如果不设置,则默认使用 heroText 。
Array<{
+ text: string
+ link: string
+ type?: 'primary' | 'secondary'
+}>
+
详情:
配置首页按钮。
示例:
---
+actions:
+ - text: 快速上手
+ link: /zh/guide/getting-started.html
+ type: primary
+ - text: 项目简介
+ link: /zh/guide/introduction.html
+ type: secondary
+---
+
Array<{
+ title: string
+ details: string
+}>
+
详情:
配置首页特性列表。
示例:
---
+features:
+ - title: 简洁至上
+ details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。
+ - title: Vue 驱动
+ details: 享受 Vue 的开发体验,可以在 Markdown 中使用 Vue 组件,又可以使用 Vue 来开发自定义主题。
+ - title: 高性能
+ details: VuePress 会为每个页面预渲染生成静态的 HTML,同时,每个页面被加载的时候,将作为 SPA 运行。
+---
+
类型: string
详情:
首页的页脚。
类型: boolean
详情:
是否允许页脚中使用 HTML 。
如果设置为 true
,那么 footer 会被作为 HTML 代码处理。
本章节中的 Frontmatter 只会在普通页面中生效。
类型: NavLink | string
详情:
上一个页面的链接。
如果你不设置该 Frontmatter ,该链接会自动根据侧边栏配置进行推断。
为了手动配置上一页面的链接,你可以将其设置为一个 NavLink
对象或者一个字符串:
NavLink
对象应该有一个 text
字段和一个 link
字段。NavLink
对象,将页面标题作为 text
,将页面路由路径作为 link
。示例:
---
+# NavLink
+prev:
+ text: Get Started
+ link: /guide/getting-started.html
+
+# NavLink - 外部 URL
+prev:
+ text: GitHub
+ link: https://github.com
+
+# 字符串 - 页面文件路径
+prev: /guide/getting-started.md
+
+# 字符串 - 页面文件相对路径
+prev: ../../guide/getting-started.md
+---
+
类型: NavLink | string
详情:
下一个页面的链接。
如果你不设置该 Frontmatter ,该链接会自动根据侧边栏配置进行推断。
类型和 prev Frontmatter 相同。
类型:SitemapFrontmatterOptions | false
详情:
false
表示将页面排除在 sitemap 之外。
类型:number
默认值:0.5
详情:
页面优先级,范围 0
至 1
。
Type: SitemapFrontmatterOptions | false
Details:
false
means exclude the page from sitemap.
Type: number
Default: 0.5
Details:
Page priority, range from 0
to 1
.
Type: string
Details:
Add extra class name to this page.
Example:
---
+pageClass: custom-page-class
+---
+
Then you can customize styles of this page in .vuepress/styles/index.scss
file:
.theme-container.custom-page-class {
+ /* page styles */
+}
+
Frontmatter in this section will only take effect in home pages.
Type: boolean
Details:
Specify whether the page is homepage or a normal page.
If you don't set this frontmatter or set it to false
, the page would be a normal page.
Example:
---
+home: true
+---
+
Type: string
Details:
Specify the url of the hero image.
Example:
---
+# public file path
+heroImage: /images/hero.png
+# url
+heroImage: https://vuejs.org/images/logo.png
+---
+
Type: string
Details:
Specify the alt
attribute of the hero image.
This will fallback to the heroText.
Array<{
+ text: string
+ link: string
+ type?: 'primary' | 'secondary'
+}>
+
Details:
Configuration of the action buttons.
Example:
---
+actions:
+ - text: Get Started
+ link: /guide/getting-started.html
+ type: primary
+ - text: Introduction
+ link: /guide/introduction.html
+ type: secondary
+---
+
Array<{
+ title: string
+ details: string
+}>
+
Details:
Configuration of the features list.
Example:
---
+features:
+ - title: Simplicity First
+ details: Minimal setup with markdown-centered project structure helps you focus on writing.
+ - title: Vue-Powered
+ details: Enjoy the dev experience of Vue, use Vue components in markdown, and develop custom themes with Vue.
+ - title: Performant
+ details: VuePress generates pre-rendered static HTML for each page, and runs as an SPA once a page is loaded.
+---
+
Type: string
Details:
Specify the content of the footer.
Type: boolean
Details:
Allow HTML in footer or not.
If you set it to true
, the footer will be treated as HTML code.
Frontmatter in this section will only take effect in normal pages.
Type: NavLink | string
Details:
Specify the link of the previous page.
If you don't set this frontmatter, the link will be inferred from the sidebar config.
To configure the prev link manually, you can set this frontmatter to a NavLink
object or a string:
NavLink
object should have a text
field and a link
field.NavLink
object, whose text
is the page title, and link
is the page route path.Example:
---
+# NavLink
+prev:
+ text: Get Started
+ link: /guide/getting-started.html
+
+# NavLink - external url
+prev:
+ text: GitHub
+ link: https://github.com
+
+# string - page file path
+prev: /guide/getting-started.md
+
+# string - page file relative path
+prev: ../../guide/getting-started.md
+---
+
Type: NavLink | string
Details:
Specify the link of the next page.
If you don't set this frontmatter, the link will be inferred from the sidebar config.
The type is the same as prev frontmatter.
You can control each feed item generation by setting page frontmatter.
By default, all articles are added to the feed stream. Set feed: false
in frontmatter to remove a page from feed.
string
Automatically generated by VuePress, defaults to the h1 content of the page
string
Description of the page
Date
Date when the page was published
boolean
Whether the page is an article
If this is set to
false
, the page will not be included in the final feed.
string
Page copyright information
string
Image used as page cover , should be full link or absolute link.
string
The title of the feed item
string
Description of the feed item
string
The content of the feed item
FeedAuthor[] | FeedAuthor
The author of the feed item
interface FeedAuthor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
FeedContributor[] | FeedContributor
Contributors to feed item
interface FeedContributor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
string
The identifier of feed item, used to identify the feed item.
You should ensure every feed has a unique guid.
你可以通过控制插件选项中的 getter
来完全控制 Feed 项目的生成。
(page: Page) => string
项目标题获取器
(page: Page) => string
项目链接获取器
(page: Page) => string | undefined
项目描述获取器
提示
因为 Atom 在摘要中支持 HTML,所以如果可能的话,你可以在这里返回 HTML 内容,但内容必须以标记 html:
开头。
(page: Page) => string
项目内容获取器
(page: Page) => FeedAuthor[]
项目作者获取器。
获取器应在作者信息缺失时返回空数组。
interface FeedAuthor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => FeedCategory[] | undefined
项目分类获取器。
interface FeedCategory {
+ /**
+ * 分类名称
+ */
+ name: string
+
+ /**
+ * 标识分类法的字符串
+ *
+ * @description rss format only
+ */
+ domain?: string
+
+ /**
+ * URI 标识的分类 scheme
+ *
+ * @description atom format only
+ */
+ scheme?: string
+}
+
(page: Page) => FeedEnclosure | undefined
项目附件获取器。
interface FeedEnclosure {
+ /**
+ * Enclosure 地址
+ */
+ url: string
+
+ /**
+ * 类型
+ *
+ * @description 应为一个标准的 MIME 类型,rss format only
+ */
+ type: string
+
+ /**
+ * 按照字节数计算的大小
+ *
+ * @description rss format only
+ */
+ length?: number
+}
+
(page: Page) => Date | undefined
项目发布日期获取器
(page: Page) => Date
项目最后更新日期获取器
(page: Page) => string
项目图片获取器
确保返回一个完整的 URL。
(page: Page) => FeedContributor[]
项目贡献者获取器
获取器应在贡献者信息缺失时返回空数组。
interface FeedContributor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => string | undefined
项目版权获取器
`,46),p=[i];function c(r,t){return n(),a("div",null,p)}const d=s(l,[["render",c],["__file","getter.html.vue"]]);export{d as default}; diff --git a/assets/getter.html-QerCAQ7D.js b/assets/getter.html-QerCAQ7D.js new file mode 100644 index 0000000000..fa68e009bc --- /dev/null +++ b/assets/getter.html-QerCAQ7D.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5d533118","path":"/zh/plugins/feed/getter.html","title":"Feed 获取器","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"getter.title","slug":"getter-title","link":"#getter-title","children":[]},{"level":2,"title":"getter.link","slug":"getter-link","link":"#getter-link","children":[]},{"level":2,"title":"getter.description","slug":"getter-description","link":"#getter-description","children":[]},{"level":2,"title":"getter.content","slug":"getter-content","link":"#getter-content","children":[]},{"level":2,"title":"getter.author","slug":"getter-author","link":"#getter-author","children":[]},{"level":2,"title":"getter.category","slug":"getter-category","link":"#getter-category","children":[]},{"level":2,"title":"getter.enclosure","slug":"getter-enclosure","link":"#getter-enclosure","children":[]},{"level":2,"title":"getter.publishDate","slug":"getter-publishdate","link":"#getter-publishdate","children":[]},{"level":2,"title":"getter.lastUpdateDate","slug":"getter-lastupdatedate","link":"#getter-lastupdatedate","children":[]},{"level":2,"title":"getter.image","slug":"getter-image","link":"#getter-image","children":[]},{"level":2,"title":"getter.contributor","slug":"getter-contributor","link":"#getter-contributor","children":[]},{"level":2,"title":"getter.copyright","slug":"getter-copyright","link":"#getter-copyright","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"filePathRelative":"zh/plugins/feed/getter.md"}');export{e as data}; diff --git a/assets/getter.html-oPPSF0v5.js b/assets/getter.html-oPPSF0v5.js new file mode 100644 index 0000000000..2b59246ac6 --- /dev/null +++ b/assets/getter.html-oPPSF0v5.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-619e6245","path":"/plugins/feed/getter.html","title":"Feed Getter","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"getter.title","slug":"getter-title","link":"#getter-title","children":[]},{"level":2,"title":"getter.link","slug":"getter-link","link":"#getter-link","children":[]},{"level":2,"title":"getter.description","slug":"getter-description","link":"#getter-description","children":[]},{"level":2,"title":"getter.content","slug":"getter-content","link":"#getter-content","children":[]},{"level":2,"title":"getter.author","slug":"getter-author","link":"#getter-author","children":[]},{"level":2,"title":"getter.category","slug":"getter-category","link":"#getter-category","children":[]},{"level":2,"title":"getter.enclosure","slug":"getter-enclosure","link":"#getter-enclosure","children":[]},{"level":2,"title":"getter.publishDate","slug":"getter-publishdate","link":"#getter-publishdate","children":[]},{"level":2,"title":"getter.lastUpdateDate","slug":"getter-lastupdatedate","link":"#getter-lastupdatedate","children":[]},{"level":2,"title":"getter.image","slug":"getter-image","link":"#getter-image","children":[]},{"level":2,"title":"getter.contributor","slug":"getter-contributor","link":"#getter-contributor","children":[]},{"level":2,"title":"getter.copyright","slug":"getter-copyright","link":"#getter-copyright","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"filePathRelative":"plugins/feed/getter.md"}');export{e as data}; diff --git a/assets/getter.html-sACV4VqX.js b/assets/getter.html-sACV4VqX.js new file mode 100644 index 0000000000..00738cfeb1 --- /dev/null +++ b/assets/getter.html-sACV4VqX.js @@ -0,0 +1,91 @@ +import{_ as s,o as n,c as a,e}from"./app-GUhkEPRO.js";const l={},i=e(`You can take full control of feed items generation by setting getter
in the plugin options.
(page: Page) => string
Item title getter
(page: Page) => string
Item link getter
(page: Page) => string | undefined
Item description getter
TIP
Due to Atom support HTML in summary, so you can return HTML content here if possible, but the content must start with mark html:
.
(page: Page) => string
Item content getter
(page: Page) => FeedAuthor[]
Item author getter.
The getter should return an empty array when author information is missing.
interface FeedAuthor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => FeedCategory[] | undefined
Item category getter.
interface FeedCategory {
+ /**
+ * Category Name
+ */
+ name: string
+
+ /**
+ * A string that identifies a categorization taxonomy
+ *
+ * @description rss format only
+ */
+ domain?: string
+
+ /**
+ * the categorization scheme via a URI
+ *
+ * @description atom format only
+ */
+ scheme?: string
+}
+
(page: Page) => FeedEnclosure | undefined
Item enclosure getter.
interface FeedEnclosure {
+ /**
+ * Enclosure link
+ */
+ url: string
+
+ /**
+ * what its type is
+ *
+ * @description should be a standard MIME Type, rss format only
+ */
+ Type: string
+
+ /**
+ * Size in bytes
+ *
+ * @description rss format only
+ */
+ length?: number
+}
+
(page: Page) => Date | undefined
Item release date getter
(page: Page) => Date
Item last update date getter
(page: Page) => string
Item Image Getter
Ensure it's returning a full URL
(page: Page) => FeedContributor[]
Item Contributor Getter
The getter should return an empty array when contributor information is missing.
interface FeedContributor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => string | undefined
Item copyright getter
`,46),p=[i];function t(r,c){return n(),a("div",null,p)}const d=s(l,[["render",t],["__file","getter.html.vue"]]);export{d as default}; diff --git a/assets/git.html-2parGuCs.js b/assets/git.html-2parGuCs.js new file mode 100644 index 0000000000..5fc27739e3 --- /dev/null +++ b/assets/git.html-2parGuCs.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-1db67204","path":"/zh/plugins/git.html","title":"git","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"Git 仓库","slug":"git-仓库","link":"#git-仓库","children":[]},{"level":2,"title":"配置项","slug":"配置项","link":"#配置项","children":[{"level":3,"title":"createdTime","slug":"createdtime","link":"#createdtime","children":[]},{"level":3,"title":"updatedTime","slug":"updatedtime","link":"#updatedtime","children":[]},{"level":3,"title":"contributors","slug":"contributors","link":"#contributors","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"gitInclude","slug":"gitinclude","link":"#gitinclude","children":[]}]},{"level":2,"title":"页面数据","slug":"页面数据","link":"#页面数据","children":[{"level":3,"title":"git.createdTime","slug":"git-createdtime","link":"#git-createdtime","children":[]},{"level":3,"title":"git.updatedTime","slug":"git-updatedtime","link":"#git-updatedtime","children":[]},{"level":3,"title":"git.contributors","slug":"git-contributors","link":"#git-contributors","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"filePathRelative":"zh/plugins/git.md"}');export{t as data}; diff --git a/assets/git.html-72XjuwoH.js b/assets/git.html-72XjuwoH.js new file mode 100644 index 0000000000..f71a71ae59 --- /dev/null +++ b/assets/git.html-72XjuwoH.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-561922cf","path":"/plugins/git.html","title":"git","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Git Repository","slug":"git-repository","link":"#git-repository","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"createdTime","slug":"createdtime","link":"#createdtime","children":[]},{"level":3,"title":"updatedTime","slug":"updatedtime","link":"#updatedtime","children":[]},{"level":3,"title":"contributors","slug":"contributors","link":"#contributors","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"gitInclude","slug":"gitinclude","link":"#gitinclude","children":[]}]},{"level":2,"title":"Page Data","slug":"page-data","link":"#page-data","children":[{"level":3,"title":"git.createdTime","slug":"git-createdtime","link":"#git-createdtime","children":[]},{"level":3,"title":"git.updatedTime","slug":"git-updatedtime","link":"#git-updatedtime","children":[]},{"level":3,"title":"git.contributors","slug":"git-contributors","link":"#git-contributors","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"filePathRelative":"plugins/git.md"}');export{e as data}; diff --git a/assets/git.html-gfEIsrAW.js b/assets/git.html-gfEIsrAW.js new file mode 100644 index 0000000000..9a13fe6c93 --- /dev/null +++ b/assets/git.html-gfEIsrAW.js @@ -0,0 +1,30 @@ +import{_ as c,r as e,o as r,c as d,a as n,b as a,d as s,w as i,e as t}from"./app-GUhkEPRO.js";const u={},D=a("h1",{id:"git",tabindex:"-1"},[a("a",{class:"header-anchor",href:"#git"},[a("span",null,"git")])],-1),h=a("p",null,"该插件会收集你的页面的 Git 信息,包括创建和更新时间、贡献者等。",-1),m=t(`该插件主要用于开发主题,大部分情况下你不需要直接使用它。
npm i -D @vuepress/plugin-git@next
+
import { gitPlugin } from '@vuepress/plugin-git'
+
+export default {
+ plugins: [
+ gitPlugin({
+ // 配置项
+ }),
+ ],
+}
+
注意
该插件会显著降低准备数据的速度,特别是在你的页面数量很多的时候。你可以考虑在 dev
模式下禁用该插件来获取更好的开发体验。
类型: boolean
默认值: true
详情:
是否收集页面的创建时间。
类型: boolean
默认值: true
详情:
是否收集页面的更新时间。
类型: boolean
默认值: true
详情:
是否收集页面的贡献者。
类型: string[]
详情:
文件相对路径组成的数组,该数组中的文件会在计算页面数据时被包含在内。
示例:
---
+gitInclude:
+ - relative/path/to/file1
+ - relative/path/to/file2
+---
+
该插件会向页面数据中添加一个 git
字段。
在使用该插件后,可以在页面数据中获取该插件收集到的 Git 信息:
import type { GitPluginPageData } from '@vuepress/plugin-git'
+import { usePageData } from 'vuepress/client'
+
+export default {
+ setup() {
+ const page = usePageData<GitPluginPageData>()
+ console.log(page.value.git)
+ },
+}
+
类型: number
详情:
页面第一次提交的 Unix 毫秒时间戳。
该属性将取当前页面及 gitInclude 中所列文件的第一次提交的时间戳的最小值。
类型: number
详情:
页面最后一次提交的 Unix 毫秒时间戳。
该属性将取当前页面及 gitInclude 中所列文件的最后一次提交的时间戳的最大值。
GitContributor[]
interface GitContributor {
+ name: string
+ email: string
+ commits: number
+}
+
详情:
页面的贡献者信息。
该属性将会包含 gitInclude 所列文件的贡献者。
This plugin is mainly used to develop themes. You won't need to use it directly in most cases.
npm i -D @vuepress/plugin-git@next
+
import { gitPlugin } from '@vuepress/plugin-git'
+
+export default {
+ plugins: [
+ gitPlugin({
+ // options
+ }),
+ ],
+}
+
WARNING
This plugin will significantly slow down the speed of data preparation, especially when you have a lot of pages. You can consider disabling this plugin in dev
mode to get better development experience.
Type: boolean
Default: true
Details:
Whether to collect page created time or not.
Type: boolean
Default: true
Details:
Whether to collect page updated time or not.
Type: boolean
Default: true
Details:
Whether to collect page contributors or not.
Type: string[]
Details:
An array of relative paths to be included when calculating page data.
Example:
---
+gitInclude:
+ - relative/path/to/file1
+ - relative/path/to/file2
+---
+
This plugin will add a git
field to page data.
After using this plugin, you can get the collected git information in page data:
import type { GitPluginPageData } from '@vuepress/plugin-git'
+import { usePageData } from 'vuepress/client'
+
+export default {
+ setup() {
+ const page = usePageData<GitPluginPageData>()
+ console.log(page.value.git)
+ },
+}
+
Type: number
Details:
Unix timestamp in milliseconds of the first commit of the page.
This attribute would take the minimum of the first commit timestamps of the current page and the files listed in gitInclude.
Type: number
Details:
Unix timestamp in milliseconds of the last commit of the page.
This attribute would take the maximum of the last commit timestamps of the current page and the files listed in gitInclude.
GitContributor[]
interface GitContributor {
+ name: string
+ email: string
+ commits: number
+}
+
Details:
The contributors information of the page.
This attribute would also include contributors to the files listed in gitInclude.
npm i -D @vuepress/plugin-google-analytics@next
+
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'
+
+export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ // options
+ }),
+ ],
+}
+
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ }),
+ ],
+}
+
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ debug: true,
+ }),
+ ],
+}
+
npm i -D @vuepress/plugin-google-analytics@next
+
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'
+
+export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ }),
+ ],
+}
+
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ debug: true,
+ }),
+ ],
+}
+
本插件会为你的网站自动生成 Sitemap。为了使插件正常工作,你需要将部署的域名传递给插件的 hostname
选项。如果你想在开发服务器中预览,请配置 devServer
选项。
插件会自动根据页面的 Git 的时间戳生成页面的最后更新时间,同时会根据站点的多语言配置声明页面的其他语言版本替代地址。
默认情况下,所有除 404 页面以外的网站链接均会被添加进 Sitemap。
如果你希望在 VuePress 项目页面之外,添加其他页面链接到 Sitemap,请将它们变成数组传入插件的 extraUrls
选项。
如果你需要排除一些页面路径,你可以将它们变成数组传入到插件的 excludePaths
选项。你也可以在对应页面的 frontmatter 中,设置 sitemap
为 false
。
你还可以通过插件的 sitemapFilename
选项控制输出的地址,此地址相对于输出目录,默认为 sitemap.xml
。
页面默认的更新周期是 daily
(每天),如果你希望修改全部的页面周期,请在插件选项中设置 changefreq
。你也可以在页面的 frontmatter 中设置 sitemap.changefreq
,页面具有更高的优先级。
合法的频率有:
"always"
"hourly"
"daily"
"weekly"
"monthly"
"yearly"
"never"
你可以在插件中设置 priority
以提供一个默认值。同时你可以通过 frontmatter 中的 sitemap.priority
来为每个页面设置优先级。可接受的值为 0
到 1
的浮点数。
你可以通过插件的 modifyTimeGetter
来返回一个 ISO 字符串格式的时间,默认会通过 Git 插件生成。
以下是一个基于文件最后修改时间的例子。
// 基于文件最后修改时间
+({
+ modifyTimeGetter: (page, app) =>
+ fs.statSync(app.dir.source(page.filePathRelative)).mtime.toISOString();
+})
+
网站地图 (Sitemap) 提供搜索引擎优化 (SEO):
网站地图通过使所有页面可被找到来增强搜索引擎优化的效果。
大部分搜索引擎只跟踪页面内有限数量的链接,因此当网站非常大的时候,网站地图对于使搜索引擎和访问者可以访问网站中的所有内容就变得必不可少了。
Sitemaps 是站点管理员向搜索引擎爬虫公布站点可被抓取页面的协议,sitemap 文件内容必须遵循 XML 格式的定义。每个 URL 可以包含更新的周期和时间、URL 在整个站点中的优先级。这样可以让搜索引擎更佳有效的抓取网站内容。
同步配置 robots.txt
由于 Sitemap 面向搜索引擎,配合此插件使用时,你最好保证你在 .vuepress/public
文件夹下放置了有效的 robots.txt
,以允许搜索引擎收录。一个最简单的 robots.txt 如下 (允许所有搜索引擎访问所有路径)
User-agent: *
+
+Allow: /
+
This plugin will automatically generate a Sitemap for your site. To let this plugin work, you need to pass the deployed domain name to the hostname
option of the plugin. If you want to preview in devServer, set devServer
options.
The plugin will automatically generate the last update time of the page based on the Git timestamp of the page, and will also declare the alternative links of the page in other languages according to the locales' config.
By default, all site links except 404 page will be added to the Sitemap.
To add other pages to the Sitemap outside the VuePress project page, please turn them into an array and pass to the extraUrls
plugin option.
If you don't want certain pages to appear in the sitemap, you can turn their paths into an array and pass to the excludePaths
plugin option, or set sitemap
to false
in the frontmatter of the corresponding page.
You can also control the output link through the sitemapFilename
option of the plugin, the link is relative to output directory. By default, the plugin will use sitemap.xml
.
The default update cycle of the page is daily
(every day). To modify the entire page cycle, please set changefreq
in the plugin options. You can also set sitemap.changefreq
in the frontmatter of the page. Note that page has a higher priority.
The legal frequencies are:
"always"
"hourly"
"daily"
"weekly"
"monthly"
"yearly"
"never"
You can set priority
in the plugin to provide a default value. At the same time you can set the priority for each page through sitemap.priority
in frontmatter. Acceptable values are floating point numbers from 0
to 1
.
You can use option modifyTimeGetter
to return a time in ISO string format, which is generated by the Git plugin by default.
The following is an example based on the last modification time of a file.
// Based on file last modified time
+({
+ modifyTimeGetter: (page, app) =>
+ fs.statSync(app.dir.source(page.filePathRelative)).mtime.toISOString();
+})
+
Sitemaps provide SEO (Search Engine Optimization):
A sitemap enhances SEO by making all pages findable.
Most search engines only follow a limited number of links within a page, so when the site is very large, a sitemap becomes essential to make everything on the site accessible to search engines and visitors.
Sitemaps is a protocol for site administrators to publish pages that can be crawled on a site to search engine spiders. The content of sitemap files must follow the definition in XML format. Each URL can contain the update period and last update time, the priority of the URL across the site. This allows search engines to crawl site content better and more efficiently.
Together with robots.txt
Sitemap is basically used by search engines, when using this plugin, you'd better ensure that you have a valid robots.txt
in the .vuepress/public
directory to allow search engines spiders to visit your site. The simplest robots.txt is as follows (allow all search engines to access all paths)
User-agent: *
+
+Allow: /
+
插件开箱即用,在不做任何配置的情况下,会尽可能通过页面内容,提取对应的信息补全 OGP 与 JSON-LD 所需的必要标签。
默认情况下,插件会读取站点配置、主题配置与页面的 frontmatter 来尽可能自动生成。诸如站点名称,页面标题,页面类型,写作日期,最后更新日期,文章标签均会自动生成。
属性名称 | 值 |
---|---|
og:url | options.hostname + path |
og:site_name | siteConfig.title |
og:title | page.title |
og:description | page.frontmatter.description || 自动生成 (当插件选项中的 autoDescription 为 true 时) |
og:type | "article" |
og:image | options.hostname + page.frontmatter.image || 页面的第一张图片|| 插件选项的 fallbackImage |
og:updated_time | page.git.updatedTime |
og:locale | page.lang |
og:locale:alternate | siteData.locales 包含的其他语言 |
twitter:card | "summary_large_image" (仅在找到图片时) |
twitter:image:alt | page.title (仅在找到图片时) |
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 |
属性名 | 值 |
---|---|
@context | "https://schema.org" |
@type | "NewsArticle" |
headline | page.title |
image | 页面中的图片|| options.hostname + page.frontmatter.image |
datePublished | page.frontmatter.date || page.git.createdTime |
dateModified | page.git.updatedTime |
author | page.frontmatter.author || options.author |
你可以在页面的 frontmatter 中配置 head
选项,自主添加特定标签到页面 <head>
以增强 SEO。
如:
---
+head:
+ - - meta
+ - name: keywords
+ content: SEO plugin
+---
+
会自动注入 <meta name="keywords" content="SEO plugin" />
。
本插件也支持你完全控制生成逻辑。
对于大多数页面,基本只有文章和网页两种类型,所以插件提供了 isArticle
选项让你提供辨别文章的逻辑。
选项接受一个 (page: Page) => boolean
格式的函数,默认情况下从 Markdown 文件生成的非主页页面都会被视为文章。
提示
如果某个网页的确符合图书、音乐之类的“冷门”类型,你可以通过设置下方三个选项处理它们。
你可以使用插件选项的 ogp
传入一个函数来按照你的需要修改默认 OGP 对象并返回。
function ogp(
+ /** 插件推断的 OGP 信息 */
+ ogp: SeoContent,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
比如你在使用某个第三方主题,并按照主题要求为每篇文章在 Front Matter 中设置了 banner
,那你可以传入这样的 ogp
:
seoPlugin({
+ ogp: (ogp, page) => ({
+ ...ogp,
+ 'og:image': page.frontmatter.banner || ogp['og:image'],
+ }),
+})
+
同 OGP,你可以使用插件选项的 jsonLd
传入一个函数来按照你的需要修改默认 JSON-LD 对象并返回。
function jsonLd(
+ /** 由插件推断出的 JSON-LD 对象 */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
如果你将内容部署到不同的站点,或不同 URL 下的相同内容,你可能需要设置 canonical
选项为你的页面提供 “规范链接”。 你可以设置一个字符串,这样它会附加在页面路由链接之前,或者添加一个自定义函数 (page: Page) => string | null
返回规范链接。
例子
如果你的站点部署在 example.com
的 docs 文件夹下,但同时在下列网址中可用:
http://example.com/docs/xxx
https://example.com/docs/xxx
http://www.example.com/docs/xxx
https://www.example.com/docs/xxx
(首选)要让搜索引擎结果始终是首选,你可能需要将 canonical
设置为 https://www.example.com/docs/
,以便搜索引擎知道首选第四个 URL 作为索引结果。
有些时候你可能需要符合其他协议或按照其他搜索引擎提供的格式提供对应的 SEO 标签,此时你可以使用 customHead
选项,其类型为:
function customHead(
+ /** head 标签配置 */
+ head: HeadConfig[],
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
你应该直接修改传入的 head
参数。
搜索引擎优化 (Search Engine Optimization),是一种透过了解搜索引擎的运作规则来调整网站,以及提高目的网站在有关搜索引擎内排名的方式。由于不少研究发现,搜索引擎的用户往往只会留意搜索结果最前面的几个条目,所以不少网站都希望透过各种形式来影响搜索引擎的排序,让自己的网站可以有优秀的搜索排名。 所谓“针对搜索引擎作最优化的处理”,是指为了要让网站更容易被搜索引擎接受。搜索引擎会将网站彼此间的内容做一些相关性的资料比对,然后再由浏览器将这些内容以最快速且接近最完整的方式,呈现给搜索者。搜索引擎优化就是通过搜索引擎的规则进行优化,为用户打造更好的用户体验,最终的目的就是做好用户体验。
The plugin can generate feed files in the following three formats for you:
Please set atom
, json
or rss
to true
in the plugin options according to the formats you want to generate.
To correctly generate feed links, you need to set hostname
in the plugin options,
If you want to preview your feed in devServer, set devServer: true
in plugin options. You may also need to set devHostname
if you are not using the default http://localhost:{port}
.
You can customize the feed channel information by setting the channel
option.
We recommend the following settings:
channel.pubDate
channel.ttl
(unit: minutes)channel.copyright
channel.author
.The plugin works out of the box. Without any config, it will extract information from the page content as much as possible to complete the necessary tags required by OGP and JSON-LD.
By default, the plugin will read the site config and page frontmatter to automatically generate tags as much as possible. Such as site name, page title, page type, writing date, last update date, and article tags are all automatically generated.
The following are the <meta>
tags and their values that will be injected into <head>
by default:
The following are the <meta>
tags and their value injected into <head>
by default to satisfy OGP:
Meta 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 in plugin options |
og:updated_time | page.git.updatedTime |
og:locale | page.lang |
og:locale:alternate | Other languages in siteData.locales |
twitter:card | "summary_large_image" (only available when image found) |
twitter:image:alt | page.title (only available when image 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 |
Property Name | Value |
---|---|
@context | "https://schema.org" |
@type | "NewsArticle" |
headline | page.title |
image | image in page || options.hostname + page.frontmatter.image || siteFavIcon in plugin options |
datePublished | page.frontmatter.date || page.git.createdTime |
dateModified | page.git.updatedTime |
author | page.frontmatter.author || options.author |
You can configure the head
option in the page's frontmatter to add specific tags to the page <head>
to enhance SEO. For example:
---
+head:
+ - - meta
+ - name: keywords
+ content: SEO plugin
+---
+
Will automatically inject <meta name="keywords" content="SEO plugin" />
.
The plugin also gives you full control over the build logic.
For most pages, there are basically only two types: articles and website, so the plugin provides the isArticle
option to allow you to provide logic for identifying articles.
The option accepts a function in the format (page: Page) => boolean
, by default all non-home pages generated from Markdown files are treated as articles.
TIP
If a page does fit into the "unpopular" genre like books, music, etc., you can handle them by setting the three options below.
You can use the plugin options ogp
to pass in a function to modify the default OGP object to your needs and return it.
function ogp(
+ /** OGP Object inferred by plugin */
+ ogp: SeoContent,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
For example, if you are using a third-party theme and set a banner
in frontmatter for each article according to the theme requirements, then you can pass in the following ogp
:
seoPlugin({
+ ogp: (ogp, page) => ({
+ ...ogp,
+ 'og:image': page.frontmatter.banner || ogp['og:image'],
+ }),
+})
+
Like OGP, you can use the plugin options jsonLd
to pass in a function to modify the default JSON-LD object to your needs and return it.
function jsonLd(
+ /** JSON-LD Object inferred by plugin */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
If you are deploying your content to different sites, or same content under different URLs, you may need to set canonical
option to provide a "Canonical Link" for your page. You can either set a string which will be appended before page route link, or adding a custom function (page: Page) => string | null
to return a canonical link if necessary.
Example
If your sites are deployed under docs directory in example.com
, but available in:
http://example.com/docs/xxx
https://example.com/docs/xxx
http://www.example.com/docs/xxx
https://www.example.com/docs/xxx
(primary)To let search engine results always be the primary choice, you may need to set canonical
to https://www.example.com/docs/
, so that search engine will know that the fourth URL is preferred to be indexed.
Sometimes you may need to fit other protocols or provide the corresponding SEO tags in the format provided by other search engines. In this case, you can use the customHead
option, whose type is:
function customHead(
+ /** Head tag config */
+ head: HeadConfig[],
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
You should modify the head
array in this function directly.
Search engine optimization (SEO) is the process of improving the quality and quantity of site traffic to a site or a web page from search engines. SEO targets unpaid traffic (known as "natural" or "organic" results) rather than direct traffic or paid traffic. Unpaid traffic may originate from different kinds of searches, including image search, video search, academic search, news search, and industry-specific vertical search engines.
As an internet marketing strategy, SEO considers how search engines work, the computer-programmed algorithms that dictate search engine behavior, what people search for, the actual search terms or keywords typed into search engines, and which search engines are preferred by their targeted audience. SEO is performed because a site will receive more visitors from a search engine when sites rank higher on the search engine results page (SERP). These visitors can then potentially be converted into customers.
插件可为你生成以下三种格式的 feed 文件:
请按照需要生成的格式,在插件选项中设置 atom
, json
或 rss
为 true
。
为了正确生成 Feed 链接,你需要在插件选项中设置 hostname
。
如果你想在开发服务器中预览 Feed,你需要在插件选项中设置 devServer: true
。如果你没有使用默认的 http://localhost:{port}
,你还需要设置 devHostname
。
你可以通过设置 channel
选项来自自定义 Feed 频道的各项信息。
我们推荐进行如下设置:
channel.pubDate
中channel.ttl
中设置内容的更新周期(单位: 分钟)channel.copyright
设置版权信息channel.author
设置频道作者。安装默认主题:
npm i -D @vuepress/theme-default@next
+
在配置文件中指定主题:
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ // 在这里添加主题配置
+ }),
+}
+
npm i -D @vuepress/plugin-seo@next
+
import { seoPlugin } from '@vuepress/plugin-seo'
+
+export default {
+ plugins: [
+ seoPlugin({
+ // options
+ }),
+ ],
+}
+
npm i -D @vuepress/plugin-sitemap@next
+
import { sitemapPlugin } from '@vuepress/plugin-sitemap'
+
+export default {
+ plugins: [
+ sitemapPlugin({
+ // 选项
+ }),
+ ],
+}
+
npm i -D @vuepress/plugin-sitemap@next
+
import { sitemapPlugin } from '@vuepress/plugin-sitemap'
+
+export default {
+ plugins: [
+ sitemapPlugin({
+ // options
+ }),
+ ],
+}
+
npm i -D @vuepress/plugin-seo@next
+
import { seoPlugin } from '@vuepress/plugin-seo'
+
+export default {
+ plugins: [
+ seoPlugin({
+ // 选项
+ }),
+ ],
+}
+
Install @vuepress/theme-default
:
npm install @vuepress/theme-default@next
+
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ // set theme config here
+ }),
+}
+
npm i -D @vuepress/plugin-feed@next
+
import { feedPlugin } from '@vuepress/plugin-feed'
+
+export default {
+ plugins: [
+ feedPlugin({
+ // 选项
+ }),
+ ],
+}
+
npm i -D @vuepress/plugin-feed@next
+
import { feedPlugin } from '@vuepress/plugin-feed'
+
+export default {
+ plugins: [
+ feedPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string
Details:
Specify the aria-label
attribute of the select language menu.
This is mainly for a11y purpose.
export default {
+ locales: {
+ '/': {
+ lang: 'en-US',
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ },
+ },
+ theme: defaultTheme({
+ locales: {
+ '/': {
+ selectLanguageName: 'English',
+ },
+ '/zh/': {
+ selectLanguageName: '简体中文',
+ },
+ },
+ }),
+}
+
Type: null | string
Details:
aria-label
value for main navigation in navbar.
Type: null | string
Details:
aria-label
value for next/previous page navigation.
Type: string
Default: 'Edit this page'
Details:
Specify the text of the edit this page link.
Type: string
Default: 'Last Updated'
Details:
Specify the text of the last updated timestamp label.
Type: string
Default: 'Contributors'
Details:
Specify the text of the contributors list label.
Type: string[]
Default: ['Not Found']
Details:
Specify the messages of the 404 page.
The message will be randomly picked from the array when users enter the 404 page.
Type: string
Default: 'Back to home'
Details:
Specify the text of the back to home link in the 404 page.
Type: string
Default: 'toggle sidebar'
Details:
Title text for sidebar toggle button.
This is mainly for a11y purpose.
类型: string
详情:
选择语言菜单 的 aria-label
属性。
它主要是为了站点的可访问性 (a11y) 。
export default {
+ locales: {
+ '/': {
+ lang: 'en-US',
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ },
+ },
+ theme: defaultTheme({
+ locales: {
+ '/': {
+ selectLanguageName: 'English',
+ },
+ '/zh/': {
+ selectLanguageName: '简体中文',
+ },
+ },
+ }),
+}
+
类型:null | string
详情:
导航栏中主导航 aria-label
属性的值。
类型:null | string
详情:
下一页/上一页导航 aria-label
属性的值
类型: string
默认值: 'Edit this page'
详情:
编辑此页 链接的文字。
类型: string
默认值: 'Last Updated'
详情:
最近更新时间戳 标签的文字。
类型: string
默认值: 'Contributors'
详情:
贡献者列表 标签的文字。
类型: string[]
默认值: ['Not Found']
详情:
404 页面的提示信息。
当用户进入 404 页面时,会从数组中随机选取一条信息进行展示。
类型: string
默认值: 'Back to home'
详情:
404 页面中 返回首页 链接的文字。
类型: string
默认值: 'toggle sidebar'
详情:
切换侧边栏按钮的标题文字。
它主要是为了站点的可访问性 (a11y) 。
使用:
::: <type> [title]
+[content]
+:::
+
type
是必需的, title
和 content
是可选的。
支持的 type
有:
输入
::: tip
+这是一个提示
+:::
+
+::: warning
+这是一个警告
+:::
+
+::: danger
+这是一个危险警告
+:::
+
+::: details
+这是一个 details 标签
+:::
+
输出
提示
这是一个提示
注意
这是一个警告
警告
这是一个危险警告
这是一个 details 标签
输入
::: danger STOP
+危险区域,禁止通行
+:::
+
+::: details 点击查看代码
+
+\`\`\`ts
+console.log('你好,VuePress!')
+\`\`\`
+
+:::
+
输出
STOP
危险区域,禁止通行
console.log('你好,VuePress!')
+
输入
:::: code-group
+::: code-group-item FOO
+
+\`\`\`ts
+const foo = 'foo'
+\`\`\`
+
+:::
+
+::: code-group-item BAR
+
+\`\`\`ts
+const bar = 'bar'
+\`\`\`
+
+:::
+::::
+
输出
`,17),f=s("div",{class:"language-typescript line-numbers-mode","data-ext":"ts","data-title":"ts"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#569CD6"}},"const"),s("span",{style:{color:"#4FC1FF"}}," foo"),s("span",{style:{color:"#D4D4D4"}}," = "),s("span",{style:{color:"#CE9178"}},"'foo'")]),l(` +`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),x=s("div",{class:"language-typescript line-numbers-mode","data-ext":"ts","data-title":"ts"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#569CD6"}},"const"),s("span",{style:{color:"#4FC1FF"}}," bar"),s("span",{style:{color:"#D4D4D4"}}," = "),s("span",{style:{color:"#CE9178"}},"'bar'")]),l(` +`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1);function F(w,B){const p=e("NpmBadge"),i=e("RouterLink"),o=e("CodeGroupItem"),d=e("CodeGroup");return r(),u("div",null,[v,n(p,{package:"@vuepress/theme-default"}),m,s("ul",null,[s("li",null,[b,s("ul",null,[y,g,_,h,s("li",null,[n(i,{to:"/zh/themes/default/components.html#codegroup"},{default:a(()=>[l("CodeGroup")]),_:1}),l(" 和 "),n(i,{to:"/zh/themes/default/components.html#codegroupitem"},{default:a(()=>[l("CodeGroupItem")]),_:1}),l(" 的别名: "),k])])]),C]),E,n(d,null,{default:a(()=>[n(o,{title:"FOO"},{default:a(()=>[f]),_:1}),n(o,{title:"BAR"},{default:a(()=>[x]),_:1})]),_:1})])}const A=t(D,[["render",F],["__file","markdown.html.vue"]]);export{A as default}; diff --git a/assets/markdown.html-gZt7th1N.js b/assets/markdown.html-gZt7th1N.js new file mode 100644 index 0000000000..d68c180c60 --- /dev/null +++ b/assets/markdown.html-gZt7th1N.js @@ -0,0 +1,50 @@ +import{_ as d,r as e,o as r,c as u,a,b as s,d as n,w as l,e as c}from"./app-GUhkEPRO.js";const D={},m=s("h1",{id:"markdown",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#markdown"},[s("span",null,"Markdown")])],-1),v=s("h2",{id:"custom-containers",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#custom-containers"},[s("span",null,"Custom Containers")])],-1),b=c(`Usage:
::: <type> [title]
+[content]
+:::
+
The type
is required, and the title
and content
are optional.
Supported type
:
Input
::: tip
+This is a tip
+:::
+
+::: warning
+This is a warning
+:::
+
+::: danger
+This is a dangerous warning
+:::
+
+::: details
+This is a details block
+:::
+
Output
TIP
This is a tip
WARNING
This is a warning
DANGER
This is a dangerous warning
This is a details block
Input
::: danger STOP
+Danger zone, do not proceed
+:::
+
+::: details Click me to view the code
+
+\`\`\`ts
+console.log('Hello, VuePress!')
+\`\`\`
+
+:::
+
Output
STOP
Danger zone, do not proceed
console.log('Hello, VuePress!')
+
Input
:::: code-group
+::: code-group-item FOO
+
+\`\`\`ts
+const foo = 'foo'
+\`\`\`
+
+:::
+
+::: code-group-item BAR
+
+\`\`\`ts
+const bar = 'bar'
+\`\`\`
+
+:::
+::::
+
Output
`,17),x=s("div",{class:"language-typescript line-numbers-mode","data-ext":"ts","data-title":"ts"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#569CD6"}},"const"),s("span",{style:{color:"#4FC1FF"}}," foo"),s("span",{style:{color:"#D4D4D4"}}," = "),s("span",{style:{color:"#CE9178"}},"'foo'")]),n(` +`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1),f=s("div",{class:"language-typescript line-numbers-mode","data-ext":"ts","data-title":"ts"},[s("pre",{class:"shiki dark-plus",style:{"background-color":"#1E1E1E",color:"#D4D4D4"},tabindex:"0"},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#569CD6"}},"const"),s("span",{style:{color:"#4FC1FF"}}," bar"),s("span",{style:{color:"#D4D4D4"}}," = "),s("span",{style:{color:"#CE9178"}},"'bar'")]),n(` +`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"})])],-1);function w(F,T){const p=e("NpmBadge"),i=e("RouterLink"),o=e("CodeGroupItem"),t=e("CodeGroup");return r(),u("div",null,[m,a(p,{package:"@vuepress/theme-default"}),v,s("ul",null,[s("li",null,[b,s("ul",null,[y,g,h,_,s("li",null,[n("Alias of "),a(i,{to:"/themes/default/components.html#codegroup"},{default:l(()=>[n("CodeGroup")]),_:1}),n(" and "),a(i,{to:"/themes/default/components.html#codegroupitem"},{default:l(()=>[n("CodeGroupItem")]),_:1}),n(": "),k])])]),C]),E,a(t,null,{default:l(()=>[a(o,{title:"FOO"},{default:l(()=>[x]),_:1}),a(o,{title:"BAR"},{default:l(()=>[f]),_:1})]),_:1})])}const N=d(D,[["render",w],["__file","markdown.html.vue"]]);export{N as default}; diff --git a/assets/markdown.html-jmp42nVr.js b/assets/markdown.html-jmp42nVr.js new file mode 100644 index 0000000000..d28577128a --- /dev/null +++ b/assets/markdown.html-jmp42nVr.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-f8d6dac2","path":"/zh/themes/default/markdown.html","title":"Markdown","lang":"zh-CN","frontmatter":{},"headers":[{"level":2,"title":"自定义容器","slug":"自定义容器","link":"#自定义容器","children":[]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"filePathRelative":"zh/themes/default/markdown.md"}');export{e as data}; diff --git a/assets/markdown.html-xk2DPo1W.js b/assets/markdown.html-xk2DPo1W.js new file mode 100644 index 0000000000..7601c4b5f6 --- /dev/null +++ b/assets/markdown.html-xk2DPo1W.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-66d0bcf0","path":"/themes/default/markdown.html","title":"Markdown","lang":"en-US","frontmatter":{},"headers":[{"level":2,"title":"Custom Containers","slug":"custom-containers","link":"#custom-containers","children":[]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"filePathRelative":"themes/default/markdown.md"}');export{e as data}; diff --git a/assets/medium-zoom.html-7wkriUuL.js b/assets/medium-zoom.html-7wkriUuL.js new file mode 100644 index 0000000000..f7011eccac --- /dev/null +++ b/assets/medium-zoom.html-7wkriUuL.js @@ -0,0 +1,31 @@ +import{_ as i,r as o,o as c,c as r,a,b as s,d as n,e as l}from"./app-GUhkEPRO.js";const t={},d=s("h1",{id:"medium-zoom",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#medium-zoom"},[s("span",null,"medium-zoom")])],-1),m={href:"https://github.com/francoischalifour/medium-zoom#readme",target:"_blank",rel:"noopener noreferrer"},u=l(`该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-medium-zoom@next
+
import { mediumZoomPlugin } from '@vuepress/plugin-medium-zoom'
+
+export default {
+ plugins: [
+ mediumZoomPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: string
默认值: ':not(a) > img'
详情:
可缩放的图片的选择器。
默认情况下,该插件会使 <a>
标签以外的所有图片都支持缩放。
类型: number
默认值: 500
详情:
以毫秒为单位的延迟。
在切换路由进入一个新页面时,该插件会在一定延迟后才使页面内的图片支持缩放。
你可以通过 zoomOptions 对大部分的缩放样式进行自定义,不过作为补充,该插件同样提供了一些 CSS 变量:
:root {
+ --medium-zoom-z-index: 100;
+ --medium-zoom-bg-color: #ffffff;
+ --medium-zoom-opacity: 1;
+}
+
import { nextTick } from 'vue'
+import { useMediumZoom } from '@vuepress/plugin-medium-zoom/client'
+
+export default {
+ setup() {
+ const zoom = useMediumZoom()
+
+ // ... 进行了一些操作,在当前页面添加了新的图片
+
+ // 此时你可能需要手动调用 \`refresh\` 来让这些新图片支持缩放
+ nextTick(() => {
+ zoom.refresh()
+ })
+ },
+}
+
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-medium-zoom@next
+
import { mediumZoomPlugin } from '@vuepress/plugin-medium-zoom'
+
+export default {
+ plugins: [
+ mediumZoomPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string
Default: ':not(a) > img'
Details:
Selector of zoomable images.
By default this plugin will make all images zoomable except those inside <a>
tags.
Type: number
Default: 500
Details:
Delay in milliseconds.
After navigating to a new page, this plugin will make images zoomable with a delay.
You can customize most of the zoom styles via zoomOptions, while this plugin also provides some CSS variables for additional customization:
:root {
+ --medium-zoom-z-index: 100;
+ --medium-zoom-bg-color: #ffffff;
+ --medium-zoom-opacity: 1;
+}
+
import { nextTick } from 'vue'
+import { useMediumZoom } from '@vuepress/plugin-medium-zoom/client'
+
+export default {
+ setup() {
+ const zoom = useMediumZoom()
+
+ // ... do something to add new images in current page
+
+ // then you may need to call \`refresh\` manually to make those new images zoomable
+ nextTick(() => {
+ zoom.refresh()
+ })
+ },
+}
+
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-nprogress@next
+
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
+
+export default {
+ plugins: [nprogressPlugin()],
+}
+
你可以通过 CSS 变量来自定义进度条的样式:
:root {
+ --nprogress-color: #29d;
+ --nprogress-z-index: 1031;
+}
+
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-nprogress@next
+
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
+
+export default {
+ plugins: [nprogressPlugin()],
+}
+
You can customize the style of the progress bar via CSS variables:
:root {
+ --nprogress-color: #29d;
+ --nprogress-z-index: 1031;
+}
+
为你的主题提供调色板功能。
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
对于主题作者,该插件可以帮助你提供用户自定义样式的能力。
npm i -D @vuepress/plugin-palette@next
+
import { palettePlugin } from '@vuepress/plugin-palette'
+
+export default {
+ plugins: [
+ palettePlugin({
+ // 配置项
+ }),
+ ],
+}
+
该插件会提供一个 @vuepress/plugin-palette/palette
(调色板文件)和一个 @vuepress/plugin-palette/style
(样式文件),用于在你的主题样式中引入。
样式文件用于覆盖默认样式或添加额外样式,因此它一般会在你主题样式的末尾引入。
在你的主题中使用该插件,假设你使用 SASS 作为 CSS 预处理器:
export default {
+ // ...
+ plugins: [palettePlugin({ preset: 'sass' })],
+}
+
在你主题需要使用对应变量的地方引入该插件的调色板文件,比如在 Layout.vue
中:
<template>
+ <h1 class="palette-title">你好,调色板!</h1>
+</template>
+
+<style lang="scss">
+/* 从该插件的调色板中引入变量 */
+@import '@vuepress/plugin-palette/palette';
+
+/* 设置变量的默认值 */
+$color: red !default;
+
+/* 在你的样式中使用变量 */
+.palette-title {
+ color: $color;
+}
+</style>
+
然后,用户就可以在 .vuepress/styles/palette.scss
中自定义变量:
$color: green;
+
在你主题的样式之后引入该插件的样式文件,比如在 clientConfigFile
中:
// 引入你主题本身的样式文件
+import 'path/to/your/theme/style'
+// 引入该插件的样式文件
+import '@vuepress/plugin-palette/style'
+
然后,用户就可以在 .vuepress/styles/index.scss
中添加额外样式,并可以覆盖你主题本身的样式:
h1 {
+ font-size: 2.5rem;
+}
+
类型: 'css' | 'sass' | 'less' | 'stylus'
默认值: 'css'
详情:
设置其他选项的预设。
如果你没有对该插件进行进阶定制化的需要,建议只设置该配置项并忽略其他选项。
类型: string
默认值:
'.vuepress/styles/palette.css'
'.vuepress/styles/palette.scss'
'.vuepress/styles/palette.less'
'.vuepress/styles/palette.styl'
详情:
用户调色板文件的路径,是针对源文件目录的相对路径。
默认值依赖于 preset 配置项。
该文件用于用户定义样式变量,建议保持默认值作为约定的文件路径。
类型: string
默认值:
'styles/palette.css'
'styles/palette.scss'
'styles/palette.less'
'styles/palette.styl'
详情:
生成的调色板临时文件的路径,是针对临时文件文件目录的相对路径。
默认值依赖于 preset 配置项。
你应该使用 '@vuepress/plugin-palette/palette'
别名来引入调色板文件,因此在绝大多数情况下你不需要修改该配置项。
类型: string
默认值:
'.vuepress/styles/index.css'
'.vuepress/styles/index.scss'
'.vuepress/styles/index.less'
'.vuepress/styles/index.styl'
详情:
用户样式文件的路径,是针对源文件目录的相对路径。
默认值依赖于 preset 配置项。
该文件用于用户覆盖默认样式和添加额外样式,建议保持默认值作为约定的文件路径。
类型: string
默认值:
'styles/index.css'
'styles/index.scss'
'styles/index.less'
'styles/index.styl'
详情:
生成的样式临时文件的路径,是针对临时文件文件目录的相对路径。
默认值依赖于 preset 配置项。
你应该使用 '@vuepress/plugin-palette/style'
别名来引入样式文件,因此在绝大多数情况下你不需要修改该配置项。
类型: (filePath: string) => string
默认值:
(filePath) => \`@import '\${filePath}';\\n\`
(filePath) => \`@forward 'file:///\${filePath}';\\n\`
(filePath) => \`@import '\${filePath}';\\n\`
(filePath) => \`@require '\${filePath}';\\n\`
详情:
用于生成引入代码的函数。
默认值依赖于 preset 配置项。
该配置项用于生成 tempPaletteFile 和 tempStyleFile ,在绝大多数情况下你不需要修改该配置项。
Provide palette support for your theme.
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
For theme authors, this plugin will help you to provide styles customization for users.
npm i -D @vuepress/plugin-palette@next
+
import { palettePlugin } from '@vuepress/plugin-palette'
+
+export default {
+ plugins: [
+ palettePlugin({
+ // options
+ }),
+ ],
+}
+
This plugin will provide a @vuepress/plugin-palette/palette
(palette file) and a @vuepress/plugin-palette/style
(style file) to be imported in your theme styles.
The style file is used for overriding the default styles or adding extra styles, so it's likely to be imported at the end of your theme styles.
Use this plugin in your theme, assuming you are using SASS:
export default {
+ // ...
+ plugins: [palettePlugin({ preset: 'sass' })],
+}
+
Import the plugin's palette file where your theme needs to use the corresponding variables, such as in the Layout.vue
file:
<template>
+ <h1 class="palette-title">Hello, Palette!</h1>
+</template>
+
+<style lang="scss">
+/* import variables from the plugin's palette file */
+@import '@vuepress/plugin-palette/palette';
+
+/* set default value for variables */
+$color: red !default;
+
+/* use variables in your styles */
+.palette-title {
+ color: $color;
+}
+</style>
+
Then users can customize variables in .vuepress/styles/palette.scss
:
$color: green;
+
Import the plugin's style file after your theme's styles, for example, in the clientConfigFile
:
// import your theme's style file
+import 'path/to/your/theme/style'
+// import the plugin's style file
+import '@vuepress/plugin-palette/style'
+
Then users can add extra styles in .vuepress/styles/index.scss
and override the default styles of your theme:
h1 {
+ font-size: 2.5rem;
+}
+
Type: 'css' | 'sass' | 'less' | 'stylus'
Default: 'css'
Details:
Set preset for other options.
If you don't need advanced customization of the plugin, it's recommended to only set this option and omit other options.
Type: string
Default:
'.vuepress/styles/palette.css'
'.vuepress/styles/palette.scss'
'.vuepress/styles/palette.less'
'.vuepress/styles/palette.styl'
Details:
File path of the user palette file, relative to source directory.
The default value depends on the preset option.
The file is where users define style variables, and it's recommended to keep the default file path as a convention.
Type: string
Default:
'styles/palette.css'
'styles/palette.scss'
'styles/palette.less'
'styles/palette.styl'
Details:
File path of the generated palette temp file, relative to temp directory.
The default value depends on the preset option.
You should import the palette file via '@vuepress/plugin-palette/palette'
alias, so you don't need to change this option in most cases.
Type: string
Default:
'.vuepress/styles/index.css'
'.vuepress/styles/index.scss'
'.vuepress/styles/index.less'
'.vuepress/styles/index.styl'
Details:
File path of the user style file, relative to source directory.
The default value depends on the preset option.
The file is where users override default styles or add extra styles, and it's recommended to keep the default file path as a convention.
Type: string
Default:
'styles/index.css'
'styles/index.scss'
'styles/index.less'
'styles/index.styl'
Details:
File path of the generated style temp file, relative to temp directory.
The default value depends on the preset option.
You should import the style file via '@vuepress/plugin-palette/style'
alias, so you don't need to change this option in most cases.
Type: (filePath: string) => string
Default:
(filePath) => \`@import '\${filePath}';\\n\`
(filePath) => \`@forward 'file:///\${filePath}';\\n\`
(filePath) => \`@import '\${filePath}';\\n\`
(filePath) => \`@require '\${filePath}';\\n\`
Details:
Function to generate import code.
The default value depends on the preset option.
This option is used for generating tempPaletteFile and tempStyleFile, and you don't need to change this option in most cases.
You can configure the plugins that used by default theme with themePlugins
.
Default theme is using some plugins by default. You can disable a plugin if you really do not want to use it. Make sure you understand what the plugin is for before disabling it.
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ themePlugins: {
+ // customize theme plugins here
+ },
+ }),
+}
+
ContainerType
type is:
tip
warning
danger
details
codeGroup
codeGroupItem
你可以通过 themePlugins
设置默认主题使用的插件。
默认主题使用了一些插件,如果你确实不需要该插件,你可以选择禁用它。在禁用插件之前,请确保你已了解它的用途。
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ themePlugins: {
+ // 在这里自定义主题插件
+ },
+ }),
+}
+
ContainerType
类型为:
tip
warning
danger
details
codeGroup
codeGroupItem
This plugin has been integrated into the default theme.
Notice that this plugin would only tokenize the code fence without adding styles. When using it with a custom theme, you may need to choose and import Prism.js style theme yourself.
npm i -D @vuepress/plugin-prismjs@next
+
import { prismjsPlugin } from '@vuepress/plugin-prismjs'
+
+export default {
+ plugins: [
+ prismjsPlugin({
+ // options
+ }),
+ ],
+}
+
该插件已经集成到默认主题中。
需要注意的是,该插件仅会给代码块添加 HTML 标记,而不会添加样式。当你在一个自定义主题中使用它时,可能需要自己选择并引入 Prism.js 样式主题。
npm i -D @vuepress/plugin-prismjs@next
+
import { prismjsPlugin } from '@vuepress/plugin-prismjs'
+
+export default {
+ plugins: [
+ prismjsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
When the new service worker is ready, a popup will appear in the right bottom of the page to ask users to activate the waiting service worker.
npm i -D @vuepress/plugin-pwa-popup@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup'
+
+export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, { message: string, buttonText: string }>
Details:
The messages of the popup in different locales.
If this option is not specified, it will fallback to default messages.
Example:
export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ locales: {
+ '/': {
+ message: 'New content is available.',
+ buttonText: 'Refresh',
+ },
+ '/zh/': {
+ message: '发现新内容可用',
+ buttonText: '刷新',
+ },
+ },
+ }),
+ ],
+}
+
You can customize the style of the popup via CSS variables:
:root {
+ --pwa-popup-z-index: 10;
+ --pwa-popup-text-color: #2c3e50;
+ --pwa-popup-bg-color: #ffffff;
+ --pwa-popup-border-color: #3eaf7c;
+ --pwa-popup-shadow: 0 4px 16px var(--pwa-popup-border-color);
+ --pwa-popup-btn-text-color: #ffffff;
+ --pwa-popup-btn-bg-color: #3eaf7c;
+ --pwa-popup-btn-hover-bg-color: #4abf8a;
+}
+
当新的 Service Worker 就绪时,会在页面右下角出现一个弹窗,询问用户是否需要激活处于 Waiting 状态的 Service Worker 。
npm i -D @vuepress/plugin-pwa-popup@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup'
+
+export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, { message: string, buttonText: string }>
详情:
弹窗在不同 locales 下的信息。
如果没有指定该配置项,它会降级使用默认信息。
示例:
export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ locales: {
+ '/': {
+ message: 'New content is available.',
+ buttonText: 'Refresh',
+ },
+ '/zh/': {
+ message: '发现新内容可用',
+ buttonText: '刷新',
+ },
+ },
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义弹窗的样式:
:root {
+ --pwa-popup-z-index: 10;
+ --pwa-popup-text-color: #2c3e50;
+ --pwa-popup-bg-color: #ffffff;
+ --pwa-popup-border-color: #3eaf7c;
+ --pwa-popup-shadow: 0 4px 16px var(--pwa-popup-border-color);
+ --pwa-popup-btn-text-color: #ffffff;
+ --pwa-popup-btn-bg-color: #3eaf7c;
+ --pwa-popup-btn-hover-bg-color: #4abf8a;
+}
+
npm i -D @vuepress/plugin-pwa@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+
+export default {
+ plugins: [
+ pwaPlugin({
+ // options
+ }),
+ ],
+}
+
Typically .vuepress/public/manifest.webmanifest
:
{
+ "name": "VuePress",
+ "short_name": "VuePress",
+ "description": "Vue-powered Static Site Generator",
+ "start_url": "/index.html",
+ "display": "standalone",
+ "background_color": "#fff",
+ "theme_color": "#3eaf7c",
+ "icons": [
+ {
+ "src": "/images/icons/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/images/icons/android-chrome-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ }
+ ]
+}
+
To make your PWA more accessible, you need to generate some icons, and put them inside the public directory.
Make sure the path of icons matches the icons
field in your manifest file:
.vuepress/public/images/icons/android-chrome-192x192.png
.vuepress/public/images/icons/android-chrome-384x384.png
export default {
+ head: [
+ ['link', { rel: 'manifest', href: '/manifest.webmanifest' }],
+ ['meta', { name: 'theme-color', content: '#3eaf7c' }],
+ // ...other tags
+ ],
+}
+
For example, you can set skipWaiting: true
to auto activate the new service worker once it is ready:
export default {
+ plugins: [
+ pwaPlugin({
+ skipWaiting: true,
+ }),
+ ],
+}
+
But if you omit skipWaiting
or set it to false
, you have to activate the new service worker manually:
import { usePwaEvent } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('ready', (registration) => {
+ console.log('Service worker is active.')
+ })
+ },
+}
+
Parameter | Type | Description |
---|---|---|
registration | ServiceWorkerRegistration | The registration of the service worker you want activate |
import { usePwaEvent, useSkipWaiting } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('updated', (registration) => {
+ console.log('The waiting service worker is available.')
+ // activate the waiting service worker
+ useSkipWaiting(registration)
+ })
+ },
+}
+
npm i -D @vuepress/plugin-pwa@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+
+export default {
+ plugins: [
+ pwaPlugin({
+ // 配置项
+ }),
+ ],
+}
+
通常是 .vuepress/public/manifest.webmanifest
:
{
+ "name": "VuePress",
+ "short_name": "VuePress",
+ "description": "Vue-powered Static Site Generator",
+ "start_url": "/index.html",
+ "display": "standalone",
+ "background_color": "#fff",
+ "theme_color": "#3eaf7c",
+ "icons": [
+ {
+ "src": "/images/icons/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/images/icons/android-chrome-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ }
+ ]
+}
+
为了提高你的 PWA 的可用性,你需要生成一些图标,并将它们放置在 Public 目录下。
确保图标的路径匹配 Manifest 文件中的 icons
字段:
.vuepress/public/images/icons/android-chrome-192x192.png
.vuepress/public/images/icons/android-chrome-384x384.png
export default {
+ head: [
+ ['link', { rel: 'manifest', href: '/manifest.webmanifest' }],
+ ['meta', { name: 'theme-color', content: '#3eaf7c' }],
+ // ...其他标签
+ ],
+}
+
比如,你可以设置 skipWaiting: true
,这将在新的 Service Worker 就绪之后立即激活它:
export default {
+ plugins: [
+ pwaPlugin({
+ skipWaiting: true,
+ }),
+ ],
+}
+
但是如果你不设置 skipWaiting
或设置为 false
,你就需要手动激活新的 Service Worker 。
import { usePwaEvent } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('ready', (registration) => {
+ console.log('Service worker 已经生效。')
+ })
+ },
+}
+
参数 | 类型 | 描述 |
---|---|---|
registration | ServiceWorkerRegistration | 你想要激活的 Service Worker 的 Registration |
import { usePwaEvent, useSkipWaiting } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('updated', (registration) => {
+ console.log('在 Waiting 状态的 Service Worker 已经就绪。')
+ // 激活 Waiting 状态的 Service Worker
+ useSkipWaiting(registration)
+ })
+ },
+}
+
此插件会为每个页面生成字数统计与预计阅读时间。
npm i -D @vuepress/plugin-reading-time@next
+
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default {
+ plugins: [
+ readingTimePlugin({
+ // 配置项
+ }),
+ ],
+}
+
插件会将相关信息注入到页面数据的 readingTime
,其中:
readingTime.minutes
:为预计阅读时间(分钟)number
readingTime.words
:字数统计,number
对于任何页面,你可以从 page.data.readingTime
获取预计阅读时间与字数统计:
page.data.readingTime // { minutes: 3.2, words: 934 }
+
你可以在 extendsPage
以及其他生命周期获取它做进一步处理:
export default {
+ // ...
+ extendsPage: (page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ },
+
+ onInitialized: (app) => {
+ app.pages.map((page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ })
+ },
+}
+
你可以从 @vuepress/plugin-reading-time/client
导入 useReadingTimeData
和 useReadingTimeLocale
来获取当前页面的阅读时间数据和语言环境数据:
<script setup lang="ts">
+import {
+ useReadingTimeData,
+ useReadingTimeLocale,
+} from '@vuepress/plugin-reading-time/client'
+
+const readingTimeData = useReadingTimeData() // { minutes: 1.1, words: 100 }
+const readingTimeLocale = useReadingTimeLocale() // { time: "1 分钟", words: "100 字" }
+</script>
+
number
300
类型:ReadingTimeLocaleConfig
interface ReadingTimeLocaleData {
+ /**
+ * 字数模板,模板中 \`$word\` 会被自动替换为字数
+ */
+ word: string
+
+ /**
+ * 小于一分钟文字
+ */
+ less1Minute: string
+
+ /**
+ * 时间模板
+ */
+ time: string
+}
+
+interface ReadingTimeLocaleConfig {
+ [localePath: string]: ReadingTimeLocaleData
+}
+
必填:否
详情:
阅读时间插件的国际化配置。
你可以从 @vuepress/plugin-reading-time/client
导入并使用这些 API:
即使插件被禁用,这些 API 也不会抛出错误。
interface ReadingTime {
+ /** 分钟为单位的预计阅读时长 */
+ minutes: number
+ /** 内容的字数 */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
当插件被禁用时会返回 null
。
interface ReadingTimeLocale {
+ /** 当前语言的预计阅读时间 */
+ time: string
+ /** 当前语言的字数文字 */
+ words: string
+}
+
+const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>
+
由于此插件主要面向插件和主题开发者,所以提供了 "使用 API":
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ useReadingTimePlugin(app, {
+ // 你的选项
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
为什么你应该使用 "使用 API"
当你多次注册一个插件时,vuepress 会给你一个警告,告诉你只有第一个插件会生效。useReadingTimePlugin
会自动检测插件是否已经注册,避免多次注册。
如果你在 extendsPage
生命周期访问阅读时间数据,那么 @vuepress/plugin-reading-time
必须在你的主题或插件之前被调用,否则你会得到未定义的 page.data.readingTime
。useReadingTimePlugin
确保了 @vuepress/plugin-reading-time
在你的主题或插件之前被调用。
我们也提供了一个 removeReadingTimePlugin
api 来移除插件。你可以使用它来确保你的调用生效或清除插件:
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ // 这会移除任何当前存在的阅读时间插件
+ removeReadingTimePlugin(app)
+
+ // 所以这会生效,即使之前已经注册了一个阅读时间插件
+ useReadingTimePlugin(app, {
+ // 你的选项
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
This plugin will generate word count and estimated reading time for each page.
npm i -D @vuepress/plugin-reading-time@next
+
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default {
+ plugins: [
+ readingTimePlugin({
+ // options
+ }),
+ ],
+}
+
The plugin will inject reading time information into the readingTime
of the page data, where:
readingTime.minutes
: estimated reading time (minutes) number
readingTime.words
: word count number
For any page, you can get estimated reading time and word count from page.data.readingTime
:
page.data.readingTime // { minutes: 3.2, words: 934 }
+
You can access it for further processing in the extendsPage
lifecycle and other lifecycle:
export default {
+ // ...
+ extendsPage: (page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ },
+
+ onInitialized: (app) => {
+ app.pages.map((page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ })
+ },
+}
+
You can import useReadingTimeData
and useReadingTimeLocale
from @vuepress/plugin-reading-time/client
to get the reading time data and locale data of the current page:
<script setup lang="ts">
+import {
+ useReadingTimeData,
+ useReadingTimeLocale,
+} from '@vuepress/plugin-reading-time/client'
+
+const readingTimeData = useReadingTimeData() // { minutes: 1.1, words: 100 }
+const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "100 words" }
+</script>
+
number
300
Type: ReadingTimeLocaleConfig
interface ReadingTimeLocaleData {
+ /**
+ * Word template, \`$word\` will be automatically replaced by actual words
+ */
+ word: string
+
+ /**
+ * Text for less than one minute
+ */
+ less1Minute: string
+
+ /**
+ * Time template
+ */
+ time: string
+}
+
+interface ReadingTimeLocaleConfig {
+ [localePath: string]: ReadingTimeLocaleData
+}
+
Required: No
Details:
Locales config for reading-time plugin.
You can import and use these APIs from @vuepress/plugin-reading-time/client
:
These APIs won't throw even you disable the plugin.
interface ReadingTime {
+ /** Expect reading time in minute unit */
+ minutes: number
+ /** Words count of content */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
null
is returned when the plugin is disabled.
interface ReadingTimeLocale {
+ /** Expect reading time text in locale */
+ time: string
+ /** Word count text in locale */
+ words: string
+}
+
+const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>
+
This plugin is targeting plugin and theme developers mostly, so we provide a "Use API":
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ useReadingTimePlugin(app, {
+ // your options
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
Why you should use "Use API"
useReadingTimePlugin
automatically detects if the plugin is registered and avoid registering multiple times.extendsPage
lifecycle, then @vuepress/plugin-reading-time
must be called before your theme or plugin, otherwise you will get undefined
for page.data.readingTime
. The useReadingTimePlugin
ensures that @vuepress/plugin-reading-time
is called before your theme or plugin.We also provides a removeReadingTimePlugin
api to remove the plugin.You can use this to ensure your call take effect or clear the plugin:
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ // this removes any existing reading time plugin at this time
+ removeReadingTimePlugin(app)
+
+ // so this will take effect even if there is a reading time plugin registered before
+ useReadingTimePlugin(app, {
+ // your options
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
This plugin can automatically handle redirects for your site.
npm i -D @vuepress/plugin-redirect@next
+
import { redirectPlugin } from '@vuepress/plugin-redirect'
+
+export default {
+ plugins: [
+ redirectPlugin({
+ // options
+ }),
+ ],
+}
+
If you change the address of an existing page, you can use the redirectFrom
option in Frontmatter to redirect to the address of this page, which ensures that users are redirected to the new address when they visit the old link.
If you need to redirect an existing page to a new page, you can use the redirectTo
option in Frontmatter to set the address to redirect to. This way the page will redirect to the new address when accessed.
You can also set config
with a redirect map in plugin options, see config for more details.
The plugin can automatically redirect non-multilingual links to the multilingual pages the user needs based on the user's language preference.
To achieve this, you need to leave the default language directory (/
) blank and set autoLocale: true
in plugin options. The plugin will automatically redirect to the correct page according to the user's language.
I.E.: you need to set the following directory structure:
.
+├── en
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+├── zh
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+└── other_languages
+ ├── ...
+ ├── page.md
+ └── README.md
+
And set locales
in theme options with:
export default {
+ locales: {
+ '/en/': {
+ lang: 'en-US',
+ // ...
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ // ...
+ },
+ // other languages
+ },
+ // ...
+}
+
So when a user accesses /
or /page.html
, they are automatically redirected to /en/
/en/page.html
and /en/
/en/page.html
based on current browser language.
Customizing fallback behavior
Sometimes, users may add more than one language to the system settings. By default, when a site supports a preferred language, but the page not exists for the preferred language, the plugin attempts to match the alternate language set by the user.
If you don't need to fall back to the user's alternate language, but directly match the user's preferred language, set localeFallback: false
in the plugin options.
Customizing missing behavior
Sometimes, when a user visits a page, the document does not yet contain the language version the user needs (a common case is that the current page has not been localized in the relevant language), so the plugin needs to perform a default action, which you can customize by defaultBehavior
in the plugin options:
"defaultLocale"
: Redirect to default language or first available language page (default behavior)"homepage"
: redirect to the home page in the current language (only available if the document contains the user's language)"404"
: Redirect to page 404 in current language (only available if the document contains the user's language)Customizing default locale path
You can customize the default locale path by setting defaultLocale
in the plugin options. By default, the plugin uses the first locale key in locales
as the default language.
The plugin supports automatically switching the link to the multilingual page that the user needs according to the user's language preference when opening a multilingual document. In order to achieve this, you need to set switchLocale
in the plugin options, which can be the following two values:
direct
: switch directly to the user language preference page without askingmodal
: When the user's language preference is different from the current page language, show a modal asking whether to switch languageBy default, the plugin generates a locale setting by reading locale path
and lang
from the site's locales
option. Sometimes, you may want multiple languages to hit the same path, in which case you should set localeConfig
in plugin options.
For example, you might want all English users to match to /en/
and Chinese Traditional users to /zh/
, then you can set:
redirect({
+ localeConfig: {
+ '/en/': ['en-US', 'en-UK', 'en'],
+ '/zh/': ['zh-CN', 'zh-TW', 'zh'],
+ },
+})
+
Sometimes you may change base
or use new domain for your site, so you may want the original site automatically redirects to the new one.
To solve this, the plugin provide vp-redirect
cli.
Usage:
+ $ vp-redirect generate [sourceDir]
+
+Options:
+ --hostname <hostname> Hostname to redirect to (E.g.: https://new.example.com/) (default: /)
+ -c, --config <config> Set path to config file
+ -o, --output <output> Set the output directory (default: .vuepress/redirect)
+ --cache <cache> Set the directory of the cache files
+ -t, --temp <temp> Set the directory of the temporary files
+ --clean-cache Clean the cache files before generation
+ --clean-temp Clean the temporary files before generation
+ -h, --help Display this message
+
You need to pass in VuePress project source dir and also set the hostname
option. The redirect helper cli will initialize your VuePress project to get pages, then generate and output the redirect html files to the output directory.
By default, the plugin will output to .vuepress/redirect
directory under source directory. And you should upload it to your original site to provide redirection.
Type: Record<string, string> | ((app: App) => Record<string, string>)
Details: Redirect map.
Example:
When base is set to /base/
:
/base/foo.html
to /base/bar.html
/base/baz.html
to https://example.com/qux.html
.redirect({
+ config: {
+ '/foo.html': '/bar.html',
+ '/baz.html': 'https://example.com/qux.html',
+ },
+})
+
Redirect post folder to posts folder:
redirect({
+ hostname: 'https://example.com',
+ config: (app) =>
+ Object.fromEntries(
+ app.pages
+ .filter(({ path }) => path.startsWith('/posts/'))
+ .map(({ path }) => [path.replace(/^\\/posts\\//, '/post/'), path]),
+ ),
+})
+
boolean
false
Type: "direct" | "modal" | false
Default: false
Details:
Whether switch to a new locale based on user preference.
"direct"
: redirect to the new locale directly without asking"modal"
: show a modal to let user choose whether to switch to the new localeType: Record<string, string | string[]>
Details: Locale language config
boolean
true
"defaultLocale" | "homepage" | "404"
"defaultLocale"
string
string | string[]
string
此插件提供页面与整站重定向功能。
npm i -D @vuepress/plugin-redirect@next
+
import { redirectPlugin } from '@vuepress/plugin-redirect'
+
+export default {
+ plugins: [
+ redirectPlugin({
+ // 配置项
+ }),
+ ],
+}
+
如果你改动了已有页面的地址,你可以在 Frontmatter 中使用 redirectFrom
选项设置重定向到此页面的地址,这样可以保证用户在访问旧链接时重定向到新的地址。
如果你需要将已有的页面重定向到新的页面,可以在 Frontmatter 中使用 redirectTo
选项设置需要重定向到的地址。这样该页面会在访问时重定向到新的地址。
你还可以通过插件选项中的 config
设置一个重定向映射,详见 config。
插件可以根据用户的语言首选项,自动将无多语言链接重定向到用户需要的多语言页面。为了实现这一点,你需要留空默认的语言目录 (/
),并在插件选项中设置 autoLocale: true
。插件会自动根据用户语言跳转到对应的语言页面。
也就是你需要设置以下目录结构:
.
+├── en
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+├── zh
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+└── other_languages
+ ├── ...
+ ├── page.md
+ └── README.md
+
并将主题选项的 locales 设置为:
export default {
+ locales: {
+ '/en/': {
+ lang: 'en-US',
+ // ...
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ // ...
+ },
+ // other languages
+ },
+ // ...
+}
+
这样当用户访问 /
或 /page.html
时,他们会自动根据当前浏览器语言重定向到 /en/
/en/page.html
与 /zh/
/zh/page.html
。
自定义回退行为
有些时候,用户可能会在系统设置中添加多个语言。默认情况下,在站点支持首选语言,但首选语言不存在相应页面时,插件会尝试匹配用户设置的备用语言。
如果不需要回退到用户备用语言,而直接匹配用户首选语言,请在插件选项中设置 localeFallback: false
。
自定义缺失行为
有些时候,当用户访问一个页面时,文档尚未包含用户需要的语言版本 (一个普遍的情况是当前页面尚未完成相关语言的本地化),这样插件需要做出默认行为,你可以通过插件选项中的 defaultBehavior
定制它:
"defaultLocale"
: 重定向到默认语言或首个可用语言页面 (默认行为)"homepage"
: 重定向到当前语言的主页 (仅在文档包含用户语言时可用)"404"
: 重定向到当前语言的 404 页 (仅在文档包含用户语言时可用)自定义默认路径
你可以通过设置插件选项中的 defaultLocale
来自定义默认路径。默认情况下,插件会使用 locales
中的第一个键名作为默认路径。
插件支持在多语言文档中,自动根据用户语言首选项,将链接切换到用户需要的多语言页面。为了实现这一点,你需要在插件选项中设置 switchLocale
,它可以是以下两个值:
direct
: 直接切换到用户语言首选项页面,而不询问modal
: 在用户语言首选项与当前页面语言不同时,弹出一个对话框询问用户是否切换语言默认情况下,插件会从站点的多语言配置 locales
选项中,读取 语言路径
和 lang
生成多语言配置。有些时候,你可能希望多个语言命中同一个路径,这种情况下,你应该设置插件的 localeConfig
选项。
比如,你可能希望所有英文用户都匹配到 /en/
,并将繁体中文用户匹配到 /zh/
中,那么你可以设置:
redirect({
+ localeConfig: {
+ '/en/': ['en-US', 'en-UK', 'en'],
+ '/zh/': ['zh-CN', 'zh-TW', 'zh'],
+ },
+})
+
有时你可能会更改 base
或为你的站点使用新域名,因此你可能希望原始站点自动重定向到新站点。
为了解决这个问题,插件提供了 vp-redirect
脚手架。
使用:
+ $ vp-redirect generate [源文件夹]
+
+Options:
+ --hostname <hostname> 重定向到的域名 (例如: https://new.example.com/) (默认: /)
+ -c, --config <config> 设置配置文件路径
+ -o, --output <output> 设置输出目录 (默认: .vuepress/redirect)
+ --cache <cache> 设置缓存文件的目录
+ -t, --temp <temp> 设置临时文件的目录
+ --clean-cache 生成前清理缓存文件
+ --clean-temp 生成前清理临时文件
+ -h, --help 显示此消息
+
你需要传入 VuePress 项目源目录并设置 hostname
选项。重定向助手脚手架将初始化你的 VuePress 项目以获取页面,然后在输出目录生成重定向 html 文件。
默认情况下,插件将输出到源文件夹下的 .vuepress/redirect
目录。你应该将其上传到你的原始站点以提供重定向。
类型:Record<string, string> | ((app: App) => Record<string, string>)
详情
页面重定向映射。
可直接传入对象或传入参数为 App
的函数返回值一个对象。
每个键名必须是一个绝对路径,代表重定向的源页面地址。
每个键值是重定向的目标地址,可以是绝对路径或完整路径。
示例:
当 base 为 /base/
时:
/base/foo.html
重定向到 /base/bar.html
/base/baz.html
重定向到 https://example.com/qux.html
。redirect({
+ config: {
+ '/foo.html': '/bar.html',
+ '/baz.html': 'https://example.com/qux.html',
+ },
+})
+
将 post 文件夹的路径重定向到 posts 文件夹
redirect({
+ hostname: 'https://example.com',
+ config: (app) =>
+ Object.fromEntries(
+ app.pages
+ .filter(({ path }) => path.startsWith('/posts/'))
+ .map(({ path }) => [path.replace(/^\\/posts\\//, '/post/'), path]),
+ ),
+})
+
类型:"direct" | "modal" | false
默认值: false
详情:
是否根据用户偏好切换到新的语言环境。
"direct"
: 直接重定向到新的语言环境而不询问"modal"
: 显示一个模式让用户选择是否切换到新的语言环境Record<string, string | string[]>
boolean
true
"defaultLocale" | "homepage" | "404"
"defaultLocale"
string
string | string[]
string
根据组件文件或目录自动注册 Vue 组件。
npm i -D @vuepress/plugin-register-components@next
+
import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, string>
默认值: {}
详情:
一个定义了组件名称和其对应文件路径的对象。
键会被用作组件名称,值是组件文件的绝对路径。
如果该配置项中的组件名称和 componentsDir 配置项发生冲突,那么该配置项会有更高的优先级。
示例:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ components: {
+ FooBar: path.resolve(__dirname, './components/FooBar.vue'),
+ },
+ }),
+ ],
+}
+
类型: string | null
默认值: null
详情:
组件目录的绝对路径。
该目录下匹配 componentsPatterns 的文件会被自动注册为 Vue 组件。
示例:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ componentsDir: path.resolve(__dirname, './components'),
+ }),
+ ],
+}
+
组件目录:
components
+├─ FooBar.vue
+└─ Baz.vue
+
组件会像这样被注册:
import { defineAsyncComponent } from 'vue'
+
+app.component(
+ 'FooBar',
+ defineAsyncComponent(() => import('/path/to/components/FooBar.vue')),
+)
+
+app.component(
+ 'Baz',
+ defineAsyncComponent(() => import('/path/to/components/Baz.vue')),
+)
+
类型: (filename: string) => string
默认值: (filename) => path.trimExt(filename.replace(/\\/|\\\\/g, '-'))
详情:
用于从文件名获取对应组件名称的函数。
它只会对 componentsDir 目录下匹配了 componentsPatterns 的文件生效。
注意,这里的 filename
是相对于 componentsPatterns 目录的文件路径。
Register Vue components from component files or directory automatically.
npm i -D @vuepress/plugin-register-components@next
+
import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, string>
Default: {}
Details:
An object that defines name of components and their corresponding file path.
The key will be used as the component name, and the value is an absolute path of the component file.
If the component name from this option conflicts with componentsDir option, this option will have a higher priority.
Example:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ components: {
+ FooBar: path.resolve(__dirname, './components/FooBar.vue'),
+ },
+ }),
+ ],
+}
+
Type: string | null
Default: null
Details:
Absolute path to the components directory.
Files in this directory which are matched with componentsPatterns will be registered as Vue components automatically.
Example:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ componentsDir: path.resolve(__dirname, './components'),
+ }),
+ ],
+}
+
Components directory:
components
+├─ FooBar.vue
+└─ Baz.vue
+
Components will be registered like this:
import { defineAsyncComponent } from 'vue'
+
+app.component(
+ 'FooBar',
+ defineAsyncComponent(() => import('/path/to/components/FooBar.vue')),
+)
+
+app.component(
+ 'Baz',
+ defineAsyncComponent(() => import('/path/to/components/Baz.vue')),
+)
+
Type: (filename: string) => string
Default: (filename) => path.trimExt(filename.replace(/\\/|\\\\/g, '-'))
Details:
A function to get component name from the filename.
It will only take effect on the files in the componentsDir which are matched with the componentsPatterns.
Notice that the filename
is a filepath relative to componentsDir.
npm i -D @vuepress/plugin-remove-pwa@next
+
import { removePwaPlugin } from '@vuepress/plugin-remove-pwa'
+
+export default {
+ plugins: [
+ removePwaPlugin({
+ // options
+ }),
+ ],
+}
+
string
'workbox'
string
'service-worker.js'
npm i -D @vuepress/plugin-remove-pwa@next
+
import { removePwaPlugin } from '@vuepress/plugin-remove-pwa'
+
+export default {
+ plugins: [
+ removePwaPlugin({
+ // options
+ }),
+ ],
+}
+
string
'workbox'
string
'service-worker.js'
This plugin will set direction to rtl on configured locales.
npm i -D @vuepress/plugin-rtl@next
+
import { rtlPlugin } from '@vuepress/plugin-rtl'
+
+export default {
+ plugins: [
+ rtlPlugin({
+ // options
+ locales: ['/ar/'],
+ }),
+ ],
+}
+
string[]
['/']
Type: SelectorOptions
interface SelectorOptions {
+ [element: string]: {
+ [attrs: string]: string
+ }
+}
+
Default: { 'html': { dir: 'rtl' } }
Details:
Selector to enable rtl.
The default settings mean that the dir
attribute of the html
element will be set to rtl
in rtl locales.
此插件会在配置的语言上设置 rtl 方向。
npm i -D @vuepress/plugin-rtl@next
+
import { rtlPlugin } from '@vuepress/plugin-rtl'
+
+export default {
+ plugins: [
+ rtlPlugin({
+ // 配置项
+ locales: ['/ar/'],
+ }),
+ ],
+}
+
string[]
['/']
类型:SelectorOptions
interface SelectorOptions {
+ [element: string]: {
+ [attrs: string]: string
+ }
+}
+
默认值:{ 'html': { dir: 'rtl' } }
详情:
开启 RTL 的选择器。
默认设置意味着在 RTL 多语言中,html
元素的 dir
属性将被设置为 rtl
。
为你的文档网站提供本地搜索能力。
提示
当你正确配置该插件后,默认主题会把搜索框添加到导航栏。
该插件不一定能在其他主题中直接使用,因此你应参考主题本身的文档来获取更多信息。
npm i -D @vuepress/plugin-search@next
+
import { searchPlugin } from '@vuepress/plugin-search'
+
+export default {
+ plugins: [
+ searchPlugin({
+ // 配置项
+ }),
+ ],
+}
+
该插件会根据你的页面,在本地生成搜索索引,然后在用户访问站点时加载搜索索引文件。换句话说,这是一个轻量级的内置搜索能力,不会进行任何外部请求。
`,7),v=l(`类型: Record<string, { placeholder: string }>
详情:
搜索框在不同 locales 下的文字。
如果没有指定该配置项,它会降级使用默认文字。
示例:
export default {
+ plugins: [
+ searchPlugin({
+ locales: {
+ '/': {
+ placeholder: 'Search',
+ },
+ '/zh/': {
+ placeholder: '搜索',
+ },
+ },
+ }),
+ ],
+}
+
(string | HotKeyOptions)[]
export interface HotKeyOptions {
+ /**
+ * Value of \`event.key\` to trigger the hot key
+ */
+ key: string;
+ /**
+ * Whether to press \`event.altKey\` at the same time
+ *
+ * @default false
+ */
+ alt?: boolean;
+ /**
+ * Whether to press \`event.ctrlKey\` at the same time
+ *
+ * @default false
+ */
+ ctrl?: boolean;
+ /**
+ * Whether to press \`event.shiftKey\` at the same time
+ *
+ * @default false
+ */
+ shift?: boolean;
+}
+
类型: number
默认值: 5
详情:
指定搜索结果的最大条数。
类型: (page: Page) => boolean
默认值: () => true
详情:
一个函数,用于判断一个页面是否应该被包含在搜索索引中。
true
来包含该页面。false
来排除该页面。示例:
export default {
+ plugins: [
+ searchPlugin({
+ // 排除首页
+ isSearchable: (page) => page.path !== '/',
+ }),
+ ],
+}
+
类型: (page: Page) => string[]
默认值: () => []
详情:
一个函数,用于在页面的搜索索引中添加额外字段。
默认情况下,该插件会将页面标题和小标题作为搜索索引。该配置项可以帮助你添加更多的可搜索字段。
示例:
export default {
+ plugins: [
+ searchPlugin({
+ // 允许搜索 Frontmatter 中的 \`tags\`
+ getExtraFields: (page) => page.frontmatter.tags ?? [],
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义搜索框的样式:
:root {
+ --search-bg-color: #ffffff;
+ --search-accent-color: #3eaf7c;
+ --search-text-color: #2c3e50;
+ --search-border-color: #eaecef;
+ --search-item-text-color: #5d81a5;
+ --search-item-focus-bg-color: #f3f4f5;
+ --search-input-width: 8rem;
+ --search-result-width: 20rem;
+}
+
详情:
该插件会全局注册一个 <SearchBox />
组件,你可以不传入任何 Props 来使用它。
将该组件放置在你想要显示搜索框的地方。例如,默认主题将这个组件放在了导航栏的末尾。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
Provide local search to your documentation site.
TIP
Default theme will add search box to the navbar once you configure this plugin correctly.
This plugin may not be used directly in other themes, so you'd better refer to the documentation of your theme for more details.
npm i -D @vuepress/plugin-search@next
+
import { searchPlugin } from '@vuepress/plugin-search'
+
+export default {
+ plugins: [
+ searchPlugin({
+ // options
+ }),
+ ],
+}
+
This plugin will generate search index from your pages locally, and load the search index file when users enter your site. In other words, this is a lightweight built-in search which does not require any external requests.
`,7),h=e(`Type: Record<string, { placeholder: string }>
Details:
The text of the search box in different locales.
If this option is not specified, it will fallback to default text.
Example:
export default {
+ plugins: [
+ searchPlugin({
+ locales: {
+ '/': {
+ placeholder: 'Search',
+ },
+ '/zh/': {
+ placeholder: '搜索',
+ },
+ },
+ }),
+ ],
+}
+
(string | HotKeyOptions)[]
export interface HotKeyOptions {
+ /**
+ * Value of \`event.key\` to trigger the hot key
+ */
+ key: string;
+ /**
+ * Whether to press \`event.altKey\` at the same time
+ *
+ * @default false
+ */
+ alt?: boolean;
+ /**
+ * Whether to press \`event.ctrlKey\` at the same time
+ *
+ * @default false
+ */
+ ctrl?: boolean;
+ /**
+ * Whether to press \`event.shiftKey\` at the same time
+ *
+ * @default false
+ */
+ shift?: boolean;
+}
+
Type: number
Default: 5
Details:
Specify the maximum number of search results.
Type: (page: Page) => boolean
Default: () => true
Details:
A function to determine whether a page should be included in the search index.
true
to include the page.false
to exclude the page.Example:
export default {
+ plugins: [
+ searchPlugin({
+ // exclude the homepage
+ isSearchable: (page) => page.path !== '/',
+ }),
+ ],
+}
+
Type: (page: Page) => string[]
Default: () => []
Details:
A function to add extra fields to the search index of a page.
By default, this plugin will use page title and headers as the search index. This option could help you to add more searchable fields.
Example:
export default {
+ plugins: [
+ searchPlugin({
+ // allow searching the \`tags\` frontmatter
+ getExtraFields: (page) => page.frontmatter.tags ?? [],
+ }),
+ ],
+}
+
You can customize the style of the search box via CSS variables:
:root {
+ --search-bg-color: #ffffff;
+ --search-accent-color: #3eaf7c;
+ --search-text-color: #2c3e50;
+ --search-border-color: #eaecef;
+ --search-item-text-color: #5d81a5;
+ --search-item-focus-bg-color: #f3f4f5;
+ --search-input-width: 8rem;
+ --search-result-width: 20rem;
+}
+
Details:
This plugin will register a <SearchBox />
component globally, and you can use it without any props.
Put this component to where you want to place the search box. For example, default theme puts this component to the end of the navbar.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
npm i -D @vuepress/plugin-shiki@next
+
import { shikiPlugin } from '@vuepress/plugin-shiki'
+
+export default {
+ plugins: [
+ shikiPlugin({
+ // 配置项
+ langs: ['ts', 'json', 'vue', 'md', 'bash', 'diff'],
+ }),
+ ],
+}
+
类型: ShikiTheme
默认值: 'nord'
详情:
Shikiji 的主题。
该配置项会被传递到 Shikiji 的 codeToHtml()
方法中。
npm i -D @vuepress/plugin-shiki@next
+
import { shikiPlugin } from '@vuepress/plugin-shiki'
+
+export default {
+ plugins: [
+ shikiPlugin({
+ // options
+ langs: ['ts', 'json', 'vue', 'md', 'bash', 'diff'],
+ }),
+ ],
+}
+
Type: ShikiTheme
Default: 'nord'
Details:
Theme of shikiji.
This option will be forwarded to codeToHtml()
method of shikiji.
用户可以通过 palette 文件 来自定义样式变量,还可以通过 style 文件 来添加额外的样式。
Palette 文件的路径是 .vuepress/styles/palette.scss
。
你可以利用它来覆盖默认主题的预定义 SASS 变量。
// responsive breakpoints
+$MQNarrow: 959px !default;
+$MQMobile: 719px !default;
+$MQMobileNarrow: 419px !default;
+
Style 文件的路径是 .vuepress/styles/index.scss
。
你可以在这里添加额外的样式,或者覆盖默认样式:
:root {
+ scroll-behavior: smooth;
+}
+
你也可以利用它来覆盖默认主题的预定义 CSS 变量。
:root {
+ // brand colors
+ --c-brand: #3eaf7c;
+ --c-brand-light: #4abf8a;
+
+ // background colors
+ --c-bg: #ffffff;
+ --c-bg-light: #f3f4f5;
+ --c-bg-lighter: #eeeeee;
+ --c-bg-dark: #ebebec;
+ --c-bg-darker: #e6e6e6;
+ --c-bg-navbar: var(--c-bg);
+ --c-bg-sidebar: var(--c-bg);
+ --c-bg-arrow: #cccccc;
+
+ // text colors
+ --c-text: #2c3e50;
+ --c-text-accent: var(--c-brand);
+ --c-text-light: #3a5169;
+ --c-text-lighter: #4e6e8e;
+ --c-text-lightest: #6a8bad;
+ --c-text-quote: #999999;
+
+ // border colors
+ --c-border: #eaecef;
+ --c-border-dark: #dfe2e5;
+
+ // custom container colors
+ --c-tip: #42b983;
+ --c-tip-bg: var(--c-bg-light);
+ --c-tip-title: var(--c-text);
+ --c-tip-text: var(--c-text);
+ --c-tip-text-accent: var(--c-text-accent);
+ --c-warning: #ffc310;
+ --c-warning-bg: #fffae3;
+ --c-warning-bg-light: #fff3ba;
+ --c-warning-bg-lighter: #fff0b0;
+ --c-warning-border-dark: #f7dc91;
+ --c-warning-details-bg: #fff5ca;
+ --c-warning-title: #f1b300;
+ --c-warning-text: #746000;
+ --c-warning-text-accent: #edb100;
+ --c-warning-text-light: #c1971c;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #f11e37;
+ --c-danger-bg: #ffe0e0;
+ --c-danger-bg-light: #ffcfde;
+ --c-danger-bg-lighter: #ffc9c9;
+ --c-danger-border-dark: #f1abab;
+ --c-danger-details-bg: #ffd4d4;
+ --c-danger-title: #ed1e2c;
+ --c-danger-text: #660000;
+ --c-danger-text-accent: #bd1a1a;
+ --c-danger-text-light: #b5474d;
+ --c-danger-text-quote: #c15b5b;
+ --c-details-bg: #eeeeee;
+
+ // badge component colors
+ --c-badge-tip: var(--c-tip);
+ --c-badge-warning: #ecc808;
+ --c-badge-warning-text: var(--c-bg);
+ --c-badge-danger: #dc2626;
+ --c-badge-danger-text: var(--c-bg);
+
+ // code group colors
+ --c-code-group-tab-title: rgba(255, 255, 255, 0.9);
+ --c-code-group-tab-bg: var(--code-bg-color);
+ --c-code-group-tab-outline: var(var(--c-code-group-tab-title));
+ --c-code-group-tab-active-border: var(--c-brand);
+
+ // transition vars
+ --t-color: 0.3s ease;
+ --t-transform: 0.3s ease;
+
+ // code blocks vars
+ --code-bg-color: #282c34;
+ --code-hl-bg-color: rgba(0, 0, 0, 0.66);
+ --code-ln-color: #9e9e9e;
+ --code-ln-wrapper-width: 3.5rem;
+
+ // font vars
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
+ Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+
+ // layout vars
+ --navbar-height: 3.6rem;
+ --navbar-padding-v: 0.7rem;
+ --navbar-padding-h: 1.5rem;
+ --sidebar-width: 20rem;
+ --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
+ --content-width: 740px;
+ --homepage-width: 960px;
+}
+
+// plugin-back-to-top
+.back-to-top {
+ --back-to-top-color: var(--c-brand);
+ --back-to-top-color-hover: var(--c-brand-light);
+ --back-to-top-bg-color: var(--c-bg);
+}
+
+// plugin-docsearch
+.DocSearch {
+ --docsearch-primary-color: var(--c-brand);
+ --docsearch-text-color: var(--c-text);
+ --docsearch-highlight-color: var(--c-brand);
+ --docsearch-muted-color: var(--c-text-quote);
+ --docsearch-container-background: rgba(9, 10, 17, 0.8);
+ --docsearch-modal-background: var(--c-bg-light);
+ --docsearch-searchbox-background: var(--c-bg-lighter);
+ --docsearch-searchbox-focus-background: var(--c-bg);
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
+ --docsearch-hit-color: var(--c-text-light);
+ --docsearch-hit-active-color: var(--c-bg);
+ --docsearch-hit-background: var(--c-bg);
+ --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
+ --docsearch-footer-background: var(--c-bg);
+}
+
+// plugin-external-link-icon
+.external-link-icon {
+ --external-link-icon-color: var(--c-text-quote);
+}
+
+// plugin-medium-zoom
+.medium-zoom-overlay {
+ --medium-zoom-bg-color: var(--c-bg);
+}
+
+// plugin-nprogress
+#nprogress {
+ --nprogress-color: var(--c-brand);
+}
+
+// plugin-pwa-popup
+.pwa-popup {
+ --pwa-popup-text-color: var(--c-text);
+ --pwa-popup-bg-color: var(--c-bg);
+ --pwa-popup-border-color: var(--c-brand);
+ --pwa-popup-shadow: 0 4px 16px var(--c-brand);
+ --pwa-popup-btn-text-color: var(--c-bg);
+ --pwa-popup-btn-bg-color: var(--c-brand);
+ --pwa-popup-btn-hover-bg-color: var(--c-brand-light);
+}
+
+// plugin-search
+.search-box {
+ --search-bg-color: var(--c-bg);
+ --search-accent-color: var(--c-brand);
+ --search-text-color: var(--c-text);
+ --search-border-color: var(--c-border);
+
+ --search-item-text-color: var(--c-text-lighter);
+ --search-item-focus-bg-color: var(--c-bg-light);
+}
+
html.dark {
+ // brand colors
+ --c-brand: #3aa675;
+ --c-brand-light: #349469;
+
+ // background colors
+ --c-bg: #22272e;
+ --c-bg-light: #2b313a;
+ --c-bg-lighter: #262c34;
+ --c-bg-dark: #343b44;
+ --c-bg-darker: #37404c;
+
+ // text colors
+ --c-text: #adbac7;
+ --c-text-light: #96a7b7;
+ --c-text-lighter: #8b9eb0;
+ --c-text-lightest: #8094a8;
+
+ // border colors
+ --c-border: #3e4c5a;
+ --c-border-dark: #34404c;
+
+ // custom container colors
+ --c-tip: #318a62;
+ --c-warning: #e0ad15;
+ --c-warning-bg: #2d2f2d;
+ --c-warning-bg-light: #423e2a;
+ --c-warning-bg-lighter: #44442f;
+ --c-warning-border-dark: #957c35;
+ --c-warning-details-bg: #39392d;
+ --c-warning-title: #fdca31;
+ --c-warning-text: #d8d96d;
+ --c-warning-text-accent: #ffbf00;
+ --c-warning-text-light: #ddb84b;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #fc1e38;
+ --c-danger-bg: #39232c;
+ --c-danger-bg-light: #4b2b35;
+ --c-danger-bg-lighter: #553040;
+ --c-danger-border-dark: #a25151;
+ --c-danger-details-bg: #482936;
+ --c-danger-title: #fc2d3b;
+ --c-danger-text: #ea9ca0;
+ --c-danger-text-accent: #fd3636;
+ --c-danger-text-light: #d9777c;
+ --c-danger-text-quote: #d56b6b;
+ --c-details-bg: #323843;
+
+ // badge component colors
+ --c-badge-warning: var(--c-warning);
+ --c-badge-warning-text: #3c2e05;
+ --c-badge-danger: var(--c-danger);
+ --c-badge-danger-text: #401416;
+
+ // code blocks vars
+ --code-hl-bg-color: #363b46;
+}
+
+// plugin-docsearch
+html.dark .DocSearch {
+ --docsearch-logo-color: var(--c-text);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
+ --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
+ 0 2px 2px 0 rgba(3, 4, 9, 0.3);
+ --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
+ --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
+ 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
+}
+
Users can customize style variables via a palette file, and add extra styles via a style file.
The path of the palette file is .vuepress/styles/palette.scss
.
You can make use of it to override predefined SASS variables of the default theme.
// responsive breakpoints
+$MQNarrow: 959px !default;
+$MQMobile: 719px !default;
+$MQMobileNarrow: 419px !default;
+
The path of the style file is .vuepress/styles/index.scss
.
You can add extra styles here, or override the default styles:
:root {
+ scroll-behavior: smooth;
+}
+
You can also make use of it to override predefined CSS variables of the default theme.
:root {
+ // brand colors
+ --c-brand: #3eaf7c;
+ --c-brand-light: #4abf8a;
+
+ // background colors
+ --c-bg: #ffffff;
+ --c-bg-light: #f3f4f5;
+ --c-bg-lighter: #eeeeee;
+ --c-bg-dark: #ebebec;
+ --c-bg-darker: #e6e6e6;
+ --c-bg-navbar: var(--c-bg);
+ --c-bg-sidebar: var(--c-bg);
+ --c-bg-arrow: #cccccc;
+
+ // text colors
+ --c-text: #2c3e50;
+ --c-text-accent: var(--c-brand);
+ --c-text-light: #3a5169;
+ --c-text-lighter: #4e6e8e;
+ --c-text-lightest: #6a8bad;
+ --c-text-quote: #999999;
+
+ // border colors
+ --c-border: #eaecef;
+ --c-border-dark: #dfe2e5;
+
+ // custom container colors
+ --c-tip: #42b983;
+ --c-tip-bg: var(--c-bg-light);
+ --c-tip-title: var(--c-text);
+ --c-tip-text: var(--c-text);
+ --c-tip-text-accent: var(--c-text-accent);
+ --c-warning: #ffc310;
+ --c-warning-bg: #fffae3;
+ --c-warning-bg-light: #fff3ba;
+ --c-warning-bg-lighter: #fff0b0;
+ --c-warning-border-dark: #f7dc91;
+ --c-warning-details-bg: #fff5ca;
+ --c-warning-title: #f1b300;
+ --c-warning-text: #746000;
+ --c-warning-text-accent: #edb100;
+ --c-warning-text-light: #c1971c;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #f11e37;
+ --c-danger-bg: #ffe0e0;
+ --c-danger-bg-light: #ffcfde;
+ --c-danger-bg-lighter: #ffc9c9;
+ --c-danger-border-dark: #f1abab;
+ --c-danger-details-bg: #ffd4d4;
+ --c-danger-title: #ed1e2c;
+ --c-danger-text: #660000;
+ --c-danger-text-accent: #bd1a1a;
+ --c-danger-text-light: #b5474d;
+ --c-danger-text-quote: #c15b5b;
+ --c-details-bg: #eeeeee;
+
+ // badge component colors
+ --c-badge-tip: var(--c-tip);
+ --c-badge-warning: #ecc808;
+ --c-badge-warning-text: var(--c-bg);
+ --c-badge-danger: #dc2626;
+ --c-badge-danger-text: var(--c-bg);
+
+ // code group colors
+ --c-code-group-tab-title: rgba(255, 255, 255, 0.9);
+ --c-code-group-tab-bg: var(--code-bg-color);
+ --c-code-group-tab-outline: var(var(--c-code-group-tab-title));
+ --c-code-group-tab-active-border: var(--c-brand);
+
+ // transition vars
+ --t-color: 0.3s ease;
+ --t-transform: 0.3s ease;
+
+ // code blocks vars
+ --code-bg-color: #282c34;
+ --code-hl-bg-color: rgba(0, 0, 0, 0.66);
+ --code-ln-color: #9e9e9e;
+ --code-ln-wrapper-width: 3.5rem;
+
+ // font vars
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
+ Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+
+ // layout vars
+ --navbar-height: 3.6rem;
+ --navbar-padding-v: 0.7rem;
+ --navbar-padding-h: 1.5rem;
+ --sidebar-width: 20rem;
+ --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
+ --content-width: 740px;
+ --homepage-width: 960px;
+}
+
+// plugin-back-to-top
+.back-to-top {
+ --back-to-top-color: var(--c-brand);
+ --back-to-top-color-hover: var(--c-brand-light);
+ --back-to-top-bg-color: var(--c-bg);
+}
+
+// plugin-docsearch
+.DocSearch {
+ --docsearch-primary-color: var(--c-brand);
+ --docsearch-text-color: var(--c-text);
+ --docsearch-highlight-color: var(--c-brand);
+ --docsearch-muted-color: var(--c-text-quote);
+ --docsearch-container-background: rgba(9, 10, 17, 0.8);
+ --docsearch-modal-background: var(--c-bg-light);
+ --docsearch-searchbox-background: var(--c-bg-lighter);
+ --docsearch-searchbox-focus-background: var(--c-bg);
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
+ --docsearch-hit-color: var(--c-text-light);
+ --docsearch-hit-active-color: var(--c-bg);
+ --docsearch-hit-background: var(--c-bg);
+ --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
+ --docsearch-footer-background: var(--c-bg);
+}
+
+// plugin-external-link-icon
+.external-link-icon {
+ --external-link-icon-color: var(--c-text-quote);
+}
+
+// plugin-medium-zoom
+.medium-zoom-overlay {
+ --medium-zoom-bg-color: var(--c-bg);
+}
+
+// plugin-nprogress
+#nprogress {
+ --nprogress-color: var(--c-brand);
+}
+
+// plugin-pwa-popup
+.pwa-popup {
+ --pwa-popup-text-color: var(--c-text);
+ --pwa-popup-bg-color: var(--c-bg);
+ --pwa-popup-border-color: var(--c-brand);
+ --pwa-popup-shadow: 0 4px 16px var(--c-brand);
+ --pwa-popup-btn-text-color: var(--c-bg);
+ --pwa-popup-btn-bg-color: var(--c-brand);
+ --pwa-popup-btn-hover-bg-color: var(--c-brand-light);
+}
+
+// plugin-search
+.search-box {
+ --search-bg-color: var(--c-bg);
+ --search-accent-color: var(--c-brand);
+ --search-text-color: var(--c-text);
+ --search-border-color: var(--c-border);
+
+ --search-item-text-color: var(--c-text-lighter);
+ --search-item-focus-bg-color: var(--c-bg-light);
+}
+
html.dark {
+ // brand colors
+ --c-brand: #3aa675;
+ --c-brand-light: #349469;
+
+ // background colors
+ --c-bg: #22272e;
+ --c-bg-light: #2b313a;
+ --c-bg-lighter: #262c34;
+ --c-bg-dark: #343b44;
+ --c-bg-darker: #37404c;
+
+ // text colors
+ --c-text: #adbac7;
+ --c-text-light: #96a7b7;
+ --c-text-lighter: #8b9eb0;
+ --c-text-lightest: #8094a8;
+
+ // border colors
+ --c-border: #3e4c5a;
+ --c-border-dark: #34404c;
+
+ // custom container colors
+ --c-tip: #318a62;
+ --c-warning: #e0ad15;
+ --c-warning-bg: #2d2f2d;
+ --c-warning-bg-light: #423e2a;
+ --c-warning-bg-lighter: #44442f;
+ --c-warning-border-dark: #957c35;
+ --c-warning-details-bg: #39392d;
+ --c-warning-title: #fdca31;
+ --c-warning-text: #d8d96d;
+ --c-warning-text-accent: #ffbf00;
+ --c-warning-text-light: #ddb84b;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #fc1e38;
+ --c-danger-bg: #39232c;
+ --c-danger-bg-light: #4b2b35;
+ --c-danger-bg-lighter: #553040;
+ --c-danger-border-dark: #a25151;
+ --c-danger-details-bg: #482936;
+ --c-danger-title: #fc2d3b;
+ --c-danger-text: #ea9ca0;
+ --c-danger-text-accent: #fd3636;
+ --c-danger-text-light: #d9777c;
+ --c-danger-text-quote: #d56b6b;
+ --c-details-bg: #323843;
+
+ // badge component colors
+ --c-badge-warning: var(--c-warning);
+ --c-badge-warning-text: #3c2e05;
+ --c-badge-danger: var(--c-danger);
+ --c-badge-danger-text: #401416;
+
+ // code blocks vars
+ --code-hl-bg-color: #363b46;
+}
+
+// plugin-docsearch
+html.dark .DocSearch {
+ --docsearch-logo-color: var(--c-text);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
+ --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
+ 0 2px 2px 0 rgba(3, 4, 9, 0.3);
+ --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
+ --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
+ 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
+}
+
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
For theme authors, this plugin will help you to use the same i18n mechanism as VuePress and the default theme. But if you don't want to provide i18n support, or you want to implement in your own way, you don't need this plugin.
npm i -D @vuepress/plugin-theme-data@next
+
import { themeDataPlugin } from '@vuepress/plugin-theme-data'
+
+export default {
+ plugins: [
+ themeDataPlugin({
+ // options
+ }),
+ ],
+}
+
Type: ThemeData
Default: {}
Details:
The theme data object that you want to use in client side.
You can provide theme data in Node side via this option, and use it in client side via useThemeData and useThemeLocaleData.
Example:
export default {
+ plugins: [
+ themeDataPlugin({
+ themeData: {
+ foo: 'foo',
+ locales: {
+ '/zh/': {
+ foo: 'zh-foo',
+ },
+ },
+ },
+ }),
+ ],
+}
+
WARNING
The theme data object will be processed by JSON.stringify()
before forwarding to client side, so you should ensure that you are providing a JSON-friendly object.
Details:
Returns the theme data ref object.
The value is provided by themeData option.
Example:
import { useThemeData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeData = useThemeData<MyThemeData>()
+ console.log(themeData.value)
+ },
+}
+
Details:
Returns the theme data ref object in current locale.
The properties of current locale has been merged into the root-level properties.
Example:
import { useThemeLocaleData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeLocaleData = useThemeLocaleData<MyThemeData>()
+ console.log(themeLocaleData.value)
+ },
+}
+
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
对于主题作者,该插件可以提供与 VuePress 及默认主题相同的多语言支持机制。但是如果你的主题不需要提供多语言支持,或者你想用你自己的方式来实现多语言支持,那么你不需要使用该插件。
npm i -D @vuepress/plugin-theme-data@next
+
import { themeDataPlugin } from '@vuepress/plugin-theme-data'
+
+export default {
+ plugins: [
+ themeDataPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: ThemeData
默认值: {}
详情:
你希望在 Client 端中使用的主题数据对象。
你可以通过该配置项,在 Node 端提供主题数据,然后在客户端通过 useThemeData 和 useThemeLocaleData 来使用主题数据。
示例:
export default {
+ plugins: [
+ themeDataPlugin({
+ themeData: {
+ foo: 'foo',
+ locales: {
+ '/zh/': {
+ foo: 'zh-foo',
+ },
+ },
+ },
+ }),
+ ],
+}
+
注意
主题数据对象在传递到客户端之前,会使用 JSON.stringify()
进行处理,因此你需要保证你提供的是一个可以被 JSON 序列化的对象。
详情:
返回主题数据的 Ref 对象。
数据是通过 themeData 配置项提供的。
示例:
import { useThemeData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeData = useThemeData<MyThemeData>()
+ console.log(themeData.value)
+ },
+}
+
详情:
返回当前 locale 下主题数据的 Ref 对象。
当前 locale 中的字段已被合并到顶层字段中。
示例:
import { useThemeLocaleData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeLocaleData = useThemeLocaleData<MyThemeData>()
+ console.log(themeLocaleData.value)
+ },
+}
+
This plugin will provide a table-of-contents (TOC) component.
npm i -D @vuepress/plugin-toc@next
+
import { tocPlugin } from '@vuepress/plugin-toc'
+
+export default {
+ plugins: [
+ tocPlugin({
+ // options
+ }),
+ ],
+}
+
<!-- markdown toc syntax -->
+
+[[toc]]
+
+<!-- vue toc component -->
+<Toc />
+
Both of them can be pre-rendered correctly in build mode. However, there are some differences between them.
The markdown syntax [[toc]]
could only be used in markdown files. It is parsed by markdown-it, and the generated TOC is static content.
The component <Toc/>
could be used in both markdown files and vue files. It is loaded by vue, and the generated TOC is a vue component.
Therefore, this plugin is more useful for theme developers.
Type: string
Default: 'Toc'
Details:
Specify the name of the TOC component.
Type: Partial<TocPropsOptions>
Default: {}
Details:
Override the default values of the component options prop.
The TOC component also accepts props for customization.
<template>
+ <Toc :headers="headers" :options="options" />
+</template>
+
PageHeader[]
interface PageHeader {
+ level: number
+ title: string
+ slug: string
+ children: PageHeader[]
+}
+
Details:
Specify the headers array to render.
If this prop is not specified, the headers of current page will be used.
Partial<TocPropsOptions>
interface TocPropsOptions {
+ containerTag: string
+ containerClass: string
+ listClass: string
+ itemClass: string
+ linkTag: 'a' | 'RouterLink'
+ linkClass: string
+ linkActiveClass: string
+ linkChildrenActiveClass: string
+}
+
Default:
Following default values can be overridden by defaultPropsOptions.
const defaultOptions = {
+ containerTag: 'nav',
+ containerClass: 'vuepress-toc',
+ listClass: 'vuepress-toc-list',
+ itemClass: 'vuepress-toc-item',
+ linkTag: 'RouterLink',
+ linkClass: 'vuepress-toc-link',
+ linkActiveClass: 'active',
+ linkChildrenActiveClass: 'active',
+}
+
Details:
Customize the TOC component.
If the containerTag
is set to an empty string ''
, the <nav>
container will be removed totally.
Example:
The rendered TOC component with default options looks like:
<template>
+ <!-- container -->
+ <nav class="vuepress-toc">
+ <!-- list -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link -->
+ <RouterLink class="vuepress-toc-link" to="#foo">Foo</RouterLink>
+ </li>
+ <!-- item with children -->
+ <li class="vuepress-toc-item">
+ <!-- link (children active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar">Bar</RouterLink>
+ <!-- list (children) -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link (active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar-child">
+ Bar Child
+ </RouterLink>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+</template>
+
该插件会提供一个目录 (table-of-contents, TOC) 组件。
npm i -D @vuepress/plugin-toc@next
+
import { tocPlugin } from '@vuepress/plugin-toc'
+
+export default {
+ plugins: [
+ tocPlugin({
+ // 配置项
+ }),
+ ],
+}
+
<!-- Markdown 目录语法 -->
+
+[[toc]]
+
+<!-- Vue 目录组件 -->
+<Toc />
+
在 Build 模式中,它们都可以被正确地预渲染。然而,它们之间存在一些区别。
Markdown 语法 [[toc]]
仅能在 Markdown 文件中使用。它是由 markdown-it 解析的,生成的目录是静态内容。
组件 <Toc/>
既可以用在 Markdown 文件中,也可以用在 Vue 文件中。它是由 Vue 加载的,生成的目录是一个 Vue 组件。
因此,该插件对于主题开发者来说更为有用。
类型: string
默认值: 'Toc'
详情:
指定目录组件的名称。
类型: Partial<TocPropsOptions>
默认值: {}
详情:
覆盖组件 options Prop 的默认值。
目录组件可以通过 Props 来进行自定义。
<template>
+ <Toc :headers="headers" :options="options" />
+</template>
+
PageHeader[]
interface PageHeader {
+ level: number
+ title: string
+ slug: string
+ children: PageHeader[]
+}
+
详情:
指定要渲染的标题数组。
如果该 Prop 没有被设置,默认会使用当前页面的标题。
Partial<TocPropsOptions>
interface TocPropsOptions {
+ containerTag: string
+ containerClass: string
+ listClass: string
+ itemClass: string
+ linkTag: 'a' | 'RouterLink'
+ linkClass: string
+ linkActiveClass: string
+ linkChildrenActiveClass: string
+}
+
默认值:
下列默认值可以用过 defaultPropsOptions 来覆盖:
const defaultOptions = {
+ containerTag: 'nav',
+ containerClass: 'vuepress-toc',
+ listClass: 'vuepress-toc-list',
+ itemClass: 'vuepress-toc-item',
+ linkTag: 'RouterLink',
+ linkClass: 'vuepress-toc-link',
+ linkActiveClass: 'active',
+ linkChildrenActiveClass: 'active',
+}
+
详情:
自定义目录组件。
如果 containerTag
设置为空字符串 ''
,那么最外层的 <nav>
Container 会被完全移除。
示例:
使用默认 options 的目录组件的渲染结果类似以下结构:
<template>
+ <!-- container -->
+ <nav class="vuepress-toc">
+ <!-- list -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link -->
+ <RouterLink class="vuepress-toc-link" to="#foo">Foo</RouterLink>
+ </li>
+ <!-- item with children -->
+ <li class="vuepress-toc-item">
+ <!-- link (children active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar">Bar</RouterLink>
+ <!-- list (children) -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link (active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar-child">
+ Bar Child
+ </RouterLink>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+</template>
+
This plugin will listen to page scroll event. When the page scrolls to a certain header anchor, this plugin will change the route hash to that header anchor if there is a corresponding header link.
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
npm i -D @vuepress/plugin-active-header-links@next
+
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
+
+export default {
+ plugins: [
+ activeHeaderLinksPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string
Default: 'a.sidebar-item'
Details:
Selector of header link.
If a header anchor does not have a corresponding header link, this plugin won't change the route hash to that anchor when scrolling to it.
Type: string
Default: '.header-anchor'
Details:
Selector of header anchor.
You don't need to specify this option unless you have changed the permalinkClass
option of markdown-it-anchor via markdown.anchor.
Also see:
Type: number
Default: 200
Details:
The delay of the debounced scroll event listener.
Type: number
Default: 5
Details:
Even if you click the link of the header anchor directly, the scrollTop
might not be exactly equal to offsetTop
of the header anchor, so we add an offset to avoid the error.
This plugin will add a back to top button to your site. The button will be displayed in the bottom right corner of the page when scrolling down. By clicking the button, the page will scroll to the top.
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-back-to-top@next
+
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'
+
+export default {
+ plugins: [backToTopPlugin()],
+}
+
number
100
boolean
true
You can customize the style of the back to top button via CSS variables:
:root {
+ --back-to-top-z-index: 5;
+ --back-to-top-icon: url("back-to-top.svg");
+ --back-to-top-bg-color: #fff;
+ --back-to-top-color: #3eaf7c;
+ --back-to-top-color-hover: #71cda3;
+ --back-to-top-shadow: rgb(0 0 0 / 20%);
+}
+
Register markdown custom containers in your VuePress site.
This plugin simplifies the use of markdown-it-container, but also retains its original capabilities.
The Custom Containers of default theme is powered by this plugin.
npm i -D @vuepress/plugin-container@next
+
import { containerPlugin } from '@vuepress/plugin-container'
+
+export default {
+ plugins: [
+ containerPlugin({
+ // options
+ }),
+ ],
+}
+
::: <type> [info]
+[content]
+:::
+
type
is required and should be specified via type option.info
is optional, and the default value can be specified via defaultInfo
in locales option.content
can be any valid markdown content.TIP
This plugin can be used multiple times to support different types of containers.
Type: string
Details:
The type of the container.
It will be used as the name
param of markdown-it-container.
Type: Record<string, { defaultInfo: string }>
Details:
The default info
of the container in different locales.
If this option is not specified, the default info
will fallback to the uppercase of the type option.
Example:
export default {
+ plugins: [
+ containerPlugin({
+ type: 'tip',
+ locales: {
+ '/': {
+ defaultInfo: 'TIP',
+ },
+ '/zh/': {
+ defaultInfo: '提示',
+ },
+ },
+ }),
+ ],
+}
+
Type: (info: string) => string
Default:
(info: string): string =>
+ `<div class="custom-container ${type}">${info ? `<p class="custom-container-title">${info}</p>` : ''}\n`
+
Details:
A function to render the starting tag of the container.
The first param is the info
part of container syntax.
This option will not take effect if you don't specify the after option.
Type: (info: string) => string
Default:
(): string => '</div>\n'
+
Details:
A function to render the ending tag of the container.
The first param is the info
part of container syntax.
This option will not take effect if you don't specify the before option.
type MarkdownItContainerRenderFunction = (
+ tokens: Token[],
+ index: number,
+ options: any,
+ env: MarkdownEnv,
+ self: Renderer,
+) => string
+
Details:
The render
option of markdown-it-container.
This plugin uses a default render
function. If you specify this option, the default render
function will be replaced, and the locales, before and after options will be ignored.
Type: (params: string) => boolean
Details:
The validate
option of markdown-it-container.
Type: string
Details:
The marker
option of markdown-it-container.
This plugin will automatically add a copy button to the top right corner of each code block on PC devices.
The default selector matches @vuepress/theme-default
, so you might need to change it when integrating your own theme.
npm i -D @vuepress/plugin-copy-code@next
+
import { copyCodePlugin } from '@vuepress/plugin-copy-code'
+
+export default {
+ plugins: [
+ copyCodePlugin({
+ // options
+ }),
+ ],
+}
+
Type: string | string[]
Default: '.theme-default-content div[class*="language-"] pre'
Details:
Code block selector
Type: boolean
Default: false
Details:
Whether to display copy button on the mobile device
Type: number
Default: 2000
Details:
Hint display time, setting it to 0
will disable the hint.
Type: number
Default: 800
Details:
The delay of registering copy code buttons, in ms.
If the theme you are using has a switching animation, it is recommended to configure this option to Switch animation duration + 200
.
Type: CopyCodeLocaleConfig
interface CopyCodeLocaleData {
+ /**
+ * Copy text
+ */
+ copy: string
+
+ /**
+ * Copied text
+ */
+ copied: string
+}
+
+interface CopyCodeLocaleConfig {
+ [localePath: string]: CopyCodeLocaleData
+}
+
Required: No
Details:
Locales config for copy code plugin.
Example:
import { copyCodePlugin } from 'vuepress-plugin-copy-code2'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyCodePlugin({
+ locales: {
+ '/': {
+ // Override copy button label text
+ copy: 'Copy Codes from code block',
+ },
+
+ '/xx/': {
+ // Complete locale config for `mm-NN` language here
+ },
+ },
+ }),
+ ],
+}
+
You can customize the icon of the copy button via CSS variables:
:root {
+ --code-copy-icon: url("copy-button.svg");
+ --code-copied-icon: url("copied-button.svg");
+ --copy-code-color: var(--code-ln-color, #9e9e9e);
+ --copy-code-hover: var(--code-hl-bg-color, rgb(0 0 0 / 66%));
+}
+
This plugin can automatically append copyright information when visitors copy content from your site, and can also prohibit site copying or selection.
npm i -D @vuepress/plugin-copyright@next
+
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ plugins: [
+ copyrightPlugin({
+ // options
+ }),
+ ],
+}
+
This plugin is disabled globally by default, you can:
copy: true
in page frontmatterglobal: true
in plugin options to enable it globally, and set copy: false
in page frontmatter to disable it.To avoid disturbing visitors, copyright information will be appended only when the copied content length is greater than 100. Set triggerLength
in plugin options if you want to change this threshold, or via copy.triggerLength
in page frontmatter.
You can set default author and license information via author
and license
in plugin options.
If your site have different authors and license in different pages, you can set authorGetter
and licenseGetter
with function (page: Page) => string
that takes the current page object as parameter and returns the corresponding information.
The plugin will generate copyright information from author, license, and page link via template by default, and append it when copying. If you think that this is not flexible enough, you can set copyrightGetter
option to return a completely customized information with Page object or return null to use the default template.
If you want to prevent users copying long content, you can set maxLength
in plugin options to customize this limit, or via copy.maxLength
in page frontmatter.
disableCopy
in plugin options or copy.disableCopy
in page frontmatter, the latter has higher priority.disableSelection
in plugin options or copy.disableSelection
in page frontmatter. This option has higher priority.string
string
(page: Page) => string | null
(page: Page) => string | null
(page: Page) => string | null
number
100
number
0
0
means no limit.boolean
false
boolean
false
boolean
false
string
Example
If you are deploying same content under https://myblog.com
and https://blog.com/username/
, you may want to prefer one site as reference link.
canonical
to https://myblog.com
canonical
to https://blog.com/username/
So copyright message triggered on another site also points to your preferred site.
Type: CopyrightLocaleConfig
interface CopyrightLocaleData {
+ /**
+ * Author text
+ *
+ * @description `:author` will be replaced by author
+ */
+ author: string
+
+ /**
+ * License text
+ *
+ * @description `:license` will be replaced by current license
+ */
+ license: string
+
+ /**
+ * Link text
+ *
+ * @description `:link` will be replaced by current page link
+ */
+ link: string
+}
+
+interface CopyrightLocaleConfig {
+ [localePath: string]: CopyrightLocaleData
+}
+
Details: Locale config for copyright plugin.
Example:
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyrightPlugin({
+ locales: {
+ '/': {
+ // Override link text
+ link: 'Original posted at :link',
+ },
+
+ '/xx/': {
+ // Complete locale config for `mm-NN` language here
+ },
+ },
+ }),
+ ],
+}
+
number
100
number
0
0
means no limit.boolean
false
boolean
false
Integrate Algolia DocSearch into VuePress, which can provide search to your documentation site.
TIP
Default theme will add DocSearch to the navbar once you configure this plugin correctly.
This plugin may not be used directly in other themes, so you'd better refer to the documentation of your theme for more details.
npm i -D @vuepress/plugin-docsearch@next
+
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
+
+export default {
+ plugins: [
+ docsearchPlugin({
+ // options
+ }),
+ ],
+}
+
You need to submit the URL of your site to join the DocSearch program. The DocSearch team will send apiKey and indexName to your email once the index is generated. Then you can configure this plugin to enable DocSearch in VuePress.
Alternatively, you can run your own crawler to generate the index, and then use your own appId, apiKey and indexName to configure this plugin.
new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ startUrls: [
+ // These are urls which algolia start to craw
+ // If your site is divided in to mutiple parts,
+ // you may want to set mutiple entry links
+ 'https://YOUR_WEBSITE_URL/',
+ ],
+ sitemaps: [
+ // if you are using sitemap plugins (e.g.: @vuepress-plugin/sitemap), you may provide one
+ 'https://YOUR_WEBSITE_URL/sitemap.xml',
+ ],
+ ignoreCanonicalTo: false,
+ exclusionPatterns: [
+ // You can use this to stop algolia crawing some paths
+ ],
+ discoveryPatterns: [
+ // These are urls which algolia looking for,
+ 'https://YOUR_WEBSITE_URL/**',
+ ],
+ // Crawler schedule, set it according to your docs update frequency
+ schedule: 'at 02:00 every 1 day',
+ actions: [
+ // you may have mutiple actions, especially when you are deploying mutiple docs under one domain
+ {
+ // name the index with name you like
+ indexName: 'YOUR_INDEX_NAME',
+ // paths where the index take effect
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ // controls how algolia extracts records from your site
+ recordExtractor: ({ $, helpers }) => {
+ // options for @vuepress/theme-default
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ lvl6: '.theme-default-content h6',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ })
+ },
+ },
+ ],
+ initialIndexSettings: {
+ // controls how index are initialized
+ // only has effects before index are initialize
+ // you may need to delete your index and recraw after modification
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ 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 above recordProps
is the configuration used for the default theme. You can modify them according to the theme you are using.
Notice that the initialIndexSettings.YOUR_INDEX_NAME.attributesForFaceting
fields must include 'lang'
to make this plugin work properly.
TIP
If you are not using default theme, or you meet any problems when using docsearch, you can also check the above example crawler config, and ahead to Algolia Crawler, and edit your config with 'Editor' panel in project sidebar.
Type: string
Required: true
Details:
The apiKey
that you received from the DocSearch team, or generated by yourself.
Also see:
Type: string
Required: true
Details:
The indexName
that you received from the DocSearch team, or generated by yourself.
Also see:
Type: string
Required: true
Details:
It defines your own application ID.
Also see:
Type: SearchParameters
Details:
Parameters of Algolia Search API.
Also see:
Type: string
Default: 'Search docs'
Details:
The placeholder attribute of the search input.
Also see:
Type: boolean
Default: false
Details:
Whether to disable all personalized features: recent searches, favorite searches, etc.
Also see:
Type: string
Details:
The initial query when the modal opens.
Also see:
Type: Partial<DocSearchTranslations>
Details:
Allow replacing the default text in the DocSearch button or modal.
Also see:
Type: Record<string, DocsearchPluginOptions>
Details:
Options of this plugin in different locales.
All other options of this plugin are acceptable in locale config.
Example:
export default {
+ plugins: [
+ docsearchPlugin({
+ appId: '<APP_ID>',
+ apiKey: '<API_KEY>',
+ indexName: '<INDEX_NAME>',
+ locales: {
+ '/': {
+ placeholder: 'Search Documentation',
+ translations: {
+ button: {
+ buttonText: 'Search Documentation',
+ },
+ },
+ },
+ '/zh/': {
+ placeholder: '搜索文档',
+ translations: {
+ button: {
+ buttonText: '搜索文档',
+ },
+ },
+ },
+ },
+ }),
+ ],
+}
+
Type: string
Default: base
Details:
The base path of the search index.
If you are deploying your site to multiple domains, you don't need to submit all of them to DocSearch and generate search index separately. You could choose one of the domains as the index domain, and only submit the index domain to Docsearch for crawling search index. Then, you could reuse the search index across all deployments.
However, if the base of your deployments are different for different domains, you need to set the option to the base of your index domain, so that other deployments could reuse the search index correctly.
Type: boolean
Default: true
Details:
Whether to inject the default styles of DocSearch or not.
If you think the default styles of DocSearch is not compatible with your site, you can try to override the default styles, or set this option to false
to totally exclude the default styles.
When this option is disabled, you need to import your own styles for DocSearch. Also notice that all styles customization in Styles section would be unavailable.
You can customize styles via CSS variables that provided by @docsearch/css:
:root {
+ --docsearch-primary-color: rgb(84, 104, 255);
+ --docsearch-text-color: rgb(28, 30, 33);
+ --docsearch-spacing: 12px;
+ --docsearch-icon-stroke-width: 1.4;
+ --docsearch-highlight-color: var(--docsearch-primary-color);
+ --docsearch-muted-color: rgb(150, 159, 175);
+ --docsearch-container-background: rgba(101, 108, 133, 0.8);
+ --docsearch-logo-color: rgba(84, 104, 255);
+
+ /* modal */
+ --docsearch-modal-width: 560px;
+ --docsearch-modal-height: 600px;
+ --docsearch-modal-background: rgb(245, 246, 247);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px
+ 8px 0 rgba(85, 90, 100, 1);
+
+ /* searchbox */
+ --docsearch-searchbox-height: 56px;
+ --docsearch-searchbox-background: rgb(235, 237, 240);
+ --docsearch-searchbox-focus-background: #fff;
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
+
+ /* hit */
+ --docsearch-hit-height: 56px;
+ --docsearch-hit-color: rgb(68, 73, 80);
+ --docsearch-hit-active-color: #fff;
+ --docsearch-hit-background: #fff;
+ --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225);
+
+ /* key */
+ --docsearch-key-gradient: linear-gradient(
+ -225deg,
+ rgb(213, 219, 228) 0%,
+ rgb(248, 248, 248) 100%
+ );
+ --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px
+ #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4);
+
+ /* footer */
+ --docsearch-footer-height: 44px;
+ --docsearch-footer-background: #fff;
+ --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
+}
+
Details:
This plugin will register a <Docsearch />
component globally, and you can use it without any props.
Put this component to where you want to place the docsearch button. For example, default theme puts this component to the end of the navbar.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
This plugin will add an icon to the external link in your markdown content, i.e.
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-external-link-icon@next
+
import { externalLinkIconPlugin } from '@vuepress/plugin-external-link-icon'
+
+export default {
+ plugins: [
+ externalLinkIconPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, { openInNewWindow: string }>
Details:
The a11y text of the external link icon in different locales.
If this option is not specified, it will fallback to default text.
Example:
export default {
+ plugins: [
+ externalLinkIconPlugin({
+ locales: {
+ '/': {
+ openInNewWindow: 'open in new window',
+ },
+ '/zh/': {
+ openInNewWindow: '在新窗口打开',
+ },
+ },
+ }),
+ ],
+}
+
Type: boolean
Details:
Whether to append an external link icon to external links in current page.
You can customize the style of the external link icon via CSS variables:
:root {
+ --external-link-icon-color: #aaa;
+}
+
Details:
This plugin will register a <ExternalLinkIcon />
component globally, and you can use it without any props.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
The channel plugin option is used to config the feed channel.
string
SiteConfig.title
Channel title
string
options.hostname
and context.base
)Channel address
string
SiteConfig.description
Channel description
Type: string
Default:
siteConfig.locales['/'].lang
"en-US"
The language of the channel
Type: string
Default:
author.name
in channel options, and fall back to Copyright by $author
Recommended to set manually: Yes
Channel copyright information
string
(must be a valid Date ISOString)Publish date of the Channel
string
(must be a valid Date ISOString)Last update time of channel content
number
The effective time of the content. It's the time to keep the cache after request without making new requests.
string
A picture presenting the channel. A square picture with a size not smaller than 512×512 is recommended.
string
An icon representing a channel, a square picture, with not less than 128×128 in size, and transparent background color is recommended.
FeedAuthor
The author of the channel.
interface FeedAuthor {
+ /** Author name */
+ name: string
+ /** Author's email */
+ email?: string
+ /** Author's site */
+ url?: string
+ /**
+ * Author's avatar address
+ *
+ * Square, preferably not less than 128×128 with transparent background
+ */
+ avatar?: string
+}
+
string
Link to Websub. Websub requires a server backend, which is inconsistent with VuePress, so ignore it if there is no special need.
WebSub
For details, see Websub.
string
The domain name of the deployment site.
boolean
false
Whether to output Atom syntax files.
boolean
false
Whether output JSON syntax files.
boolean
false
Whether to output RSS syntax files.
string
A large image/icon of the feed, probably used as banner.
string
A small icon of the feed, probably used as favicon.
number
100
Set the maximum number of items in the feed. After all pages are sorted, the first count
items will be intercepted.
If your site has a lot of articles, you may consider this option to reduce feed file size.
(RegExp | string)[] | (tagName: string) => boolean
Custom element or component which should be preserved in feed.
By default, all unknown tags will be removed.
Type: (page: Page)=> boolean
Default:
;({ frontmatter, filePathRelative }: Page): boolean =>
+ !(
+ frontmatter.home ||
+ !filePathRelative ||
+ frontmatter.article === false ||
+ frontmatter.feed === false
+ )
+
A custom filter function, used to filter feed items.
Type: (pageA: Page, pageB: Page)=> number
Default:
// dateSorter is from @vuepress/helper
+;(pageA: Page, pageB: Page): number =>
+ dateSorter(
+ pageA.data.git?.createdTime
+ ? new Date(pageA.data.git?.createdTime)
+ : pageA.frontmatter.date,
+ pageB.data.git?.createdTime
+ ? new Date(pageB.data.git?.createdTime)
+ : pageB.frontmatter.date,
+ )
+
Custom sorter function for feed items.
The default sorting behavior is by file adding time coming from git (needs @vuepress/plugin-git
).
TIP
You should enable @vuepress/plugin-git
to get the newest created pages as feed items. Otherwise, the feed items will be sorted by the default order of pages in VuePress.
channel
option is used to config Feed Channels.
For available options, please see Config → Channel
boolean
false
Whether enabled in devServer.
TIP
For performance reasons, we do not provide hot reload. Reboot your devServer to sync your changes.
string
"http://localhost:${port}"
Hostname to use in devServer
string
"atom.xml"
Atom syntax output filename, relative to dest folder.
string
@vuepress/plugin-feed/templates/atom.xsl
Atom xsl template file content.
string
"atom.xsl"
Atom xsl filename, relative to dest folder.
string
"feed.json"
JSON syntax output filename, relative to dest folder.
string
"rss.xml"
RSS syntax output filename, relative to dest folder.
string
@vuepress/plugin-feed/templates/rss.xsl
RSS xsl template file content.
string
"rss.xsl"
RSS syntax xsl filename, relative to dest folder.
Feed generation controller, see Feed Getter.
The plugin has a built-in getter, only set this if you want full control of feed generation.
Record<string, BaseFeedOptions>
You can use it to specific options for each locale.
Any options above are supported except hostname
.
You can control each feed item generation by setting page frontmatter.
By default, all articles are added to the feed stream. Set feed: false
in frontmatter to remove a page from feed.
string
Automatically generated by VuePress, defaults to the h1 content of the page
string
Description of the page
Date
Date when the page was published
boolean
Whether the page is an article
If this is set to
false
, the page will not be included in the final feed.
string
Page copyright information
string
Image used as page cover , should be full link or absolute link.
string
The title of the feed item
string
Description of the feed item
string
The content of the feed item
FeedAuthor[] | FeedAuthor
The author of the feed item
interface FeedAuthor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
FeedContributor[] | FeedContributor
Contributors to feed item
interface FeedContributor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
string
The identifier of feed item, used to identify the feed item.
You should ensure every feed has a unique guid.
You can take full control of feed items generation by setting getter
in the plugin options.
(page: Page) => string
Item title getter
(page: Page) => string
Item link getter
(page: Page) => string | undefined
Item description getter
TIP
Due to Atom support HTML in summary, so you can return HTML content here if possible, but the content must start with mark html:
.
(page: Page) => string
Item content getter
(page: Page) => FeedAuthor[]
Item author getter.
The getter should return an empty array when author information is missing.
interface FeedAuthor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => FeedCategory[] | undefined
Item category getter.
interface FeedCategory {
+ /**
+ * Category Name
+ */
+ name: string
+
+ /**
+ * A string that identifies a categorization taxonomy
+ *
+ * @description rss format only
+ */
+ domain?: string
+
+ /**
+ * the categorization scheme via a URI
+ *
+ * @description atom format only
+ */
+ scheme?: string
+}
+
(page: Page) => FeedEnclosure | undefined
Item enclosure getter.
interface FeedEnclosure {
+ /**
+ * Enclosure link
+ */
+ url: string
+
+ /**
+ * what its type is
+ *
+ * @description should be a standard MIME Type, rss format only
+ */
+ Type: string
+
+ /**
+ * Size in bytes
+ *
+ * @description rss format only
+ */
+ length?: number
+}
+
(page: Page) => Date | undefined
Item release date getter
(page: Page) => Date
Item last update date getter
(page: Page) => string
Item Image Getter
Ensure it's returning a full URL
(page: Page) => FeedContributor[]
Item Contributor Getter
The getter should return an empty array when contributor information is missing.
interface FeedContributor {
+ /**
+ * Author name
+ */
+ name?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+
+ /**
+ * Author site
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * Author avatar
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => string | undefined
Item copyright getter
The plugin can generate feed files in the following three formats for you:
Please set atom
, json
or rss
to true
in the plugin options according to the formats you want to generate.
To correctly generate feed links, you need to set hostname
in the plugin options,
When you open the feed file in browser, we magically convert atom and rss feed xml to human readable html via xsl template. Check atom and rss feed of this site as an example!
If you want to preview your feed in devServer, set devServer: true
in plugin options. You may also need to set devHostname
if you are not using the default http://localhost:{port}
.
You can customize the feed channel information by setting the channel
option.
We recommend the following settings:
channel.pubDate
channel.ttl
(unit: minutes)channel.copyright
channel.author
.For detailed options and their default values, see Channel Config
By default, all articles are added to the feed stream.
You can set feed
and other options in page frontmatter to control contents of feed item. See Frontmatter Config for how they are converted.
You can take full control of feed items generation by configuring the getter
in the plugin options. For detailed options and their default values, see Configuration → Feed Getter.
The plugin generates separate feeds for each language.
You can provide different settings for different languages via locales
in the plugin options.
This plugin will collect git information of your pages, including the created and updated time, the contributors, etc.
The lastUpdated and contributors of default theme is powered by this plugin.
This plugin is mainly used to develop themes. You won't need to use it directly in most cases.
npm i -D @vuepress/plugin-git@next
+
import { gitPlugin } from '@vuepress/plugin-git'
+
+export default {
+ plugins: [
+ gitPlugin({
+ // options
+ }),
+ ],
+}
+
This plugin requires your project to be inside a Git Repository, so that it can collect information from the commit history.
You should ensure all commits are available when building your site. For example, CI workflows usually clone your repository with --depth 1 to avoid fetching all commits, so you should disable the behavior to make this plugin work properly in CI.
WARNING
This plugin will significantly slow down the speed of data preparation, especially when you have a lot of pages. You can consider disabling this plugin in dev
mode to get better development experience.
Type: boolean
Default: true
Details:
Whether to collect page created time or not.
Type: boolean
Default: true
Details:
Whether to collect page updated time or not.
Type: boolean
Default: true
Details:
Whether to collect page contributors or not.
Type: string[]
Details:
An array of relative paths to be included when calculating page data.
Example:
---
+gitInclude:
+ - relative/path/to/file1
+ - relative/path/to/file2
+---
+
This plugin will add a git
field to page data.
After using this plugin, you can get the collected git information in page data:
import type { GitPluginPageData } from '@vuepress/plugin-git'
+import { usePageData } from 'vuepress/client'
+
+export default {
+ setup() {
+ const page = usePageData<GitPluginPageData>()
+ console.log(page.value.git)
+ },
+}
+
Type: number
Details:
Unix timestamp in milliseconds of the first commit of the page.
This attribute would take the minimum of the first commit timestamps of the current page and the files listed in gitInclude.
Type: number
Details:
Unix timestamp in milliseconds of the last commit of the page.
This attribute would take the maximum of the last commit timestamps of the current page and the files listed in gitInclude.
GitContributor[]
interface GitContributor {
+ name: string
+ email: string
+ commits: number
+}
+
Details:
The contributors information of the page.
This attribute would also include contributors to the files listed in gitInclude.
Integrate Google Analytics into VuePress.
This plugin will import gtag.js for Google Analytics 4.
npm i -D @vuepress/plugin-google-analytics@next
+
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'
+
+export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ // options
+ }),
+ ],
+}
+
Google Analytics will automatically collect some events, such as page_view
, first_visit
, etc.
So if you only want to collect some basic data of your site, you don't need to do anything else except setting the Measurement ID correctly.
After using this plugin, the global gtag()
function is available on the window
object, and you can use it for custom events reporting.
Type: string
Details:
The Measurement ID of Google Analytics 4, which should start with 'G-'
.
You can follow the instructions here to find your Measurement ID. Notice the difference between Google Analytics 4 Measurement ID (i.e. "G-" ID) and Universal Analytics Tracking ID (i.e. "UA-" ID).
Example:
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ }),
+ ],
+}
+
Type: boolean
Details:
Set to true
to enable sending events to DebugView. See more information on DebugView.
Example:
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ debug: true,
+ }),
+ ],
+}
+
Integrate medium-zoom into VuePress, which can provide the ability to zoom images.
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-medium-zoom@next
+
import { mediumZoomPlugin } from '@vuepress/plugin-medium-zoom'
+
+export default {
+ plugins: [
+ mediumZoomPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string
Default: ':not(a) > img'
Details:
Selector of zoomable images.
By default this plugin will make all images zoomable except those inside <a>
tags.
Type: number
Default: 500
Details:
Delay in milliseconds.
After navigating to a new page, this plugin will make images zoomable with a delay.
Type: Object
Details:
Options for medium-zoom.
Also see:
You can customize most of the zoom styles via zoomOptions, while this plugin also provides some CSS variables for additional customization:
:root {
+ --medium-zoom-z-index: 100;
+ --medium-zoom-bg-color: #ffffff;
+ --medium-zoom-opacity: 1;
+}
+
Details:
Returns the Zoom
instance that used by this plugin, so that you can use the instance methods directly.
This plugin will make images zoomable after navigating to current page. But if you are going to add new images dynamically, you may need this method to make those new images zoomable, too.
This plugin adds an extra refresh
method on the Zoom
instance, which will call zoom.detach()
then zoom.attach()
with the selector as the default parameter. It will help you to refresh the zoomable images for current page.
Example:
import { nextTick } from 'vue'
+import { useMediumZoom } from '@vuepress/plugin-medium-zoom/client'
+
+export default {
+ setup() {
+ const zoom = useMediumZoom()
+
+ // ... do something to add new images in current page
+
+ // then you may need to call `refresh` manually to make those new images zoomable
+ nextTick(() => {
+ zoom.refresh()
+ })
+ },
+}
+
Integrate nprogress into VuePress, which can provide a progress bar when navigating to another page.
This plugin has been integrated into the default theme.
npm i -D @vuepress/plugin-nprogress@next
+
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
+
+export default {
+ plugins: [nprogressPlugin()],
+}
+
You can customize the style of the progress bar via CSS variables:
:root {
+ --nprogress-color: #29d;
+ --nprogress-z-index: 1031;
+}
+
Provide palette support for your theme.
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
For theme authors, this plugin will help you to provide styles customization for users.
npm i -D @vuepress/plugin-palette@next
+
import { palettePlugin } from '@vuepress/plugin-palette'
+
+export default {
+ plugins: [
+ palettePlugin({
+ // options
+ }),
+ ],
+}
+
This plugin will provide a @vuepress/plugin-palette/palette
(palette file) and a @vuepress/plugin-palette/style
(style file) to be imported in your theme styles.
The palette file is used for defining style variables, so it's likely to be imported at the beginning of your theme styles. For example, users can define CSS variables, SASS variables, LESS variables or Stylus variables in the palette, and then you can use those variables in your theme styles.
The style file is used for overriding the default styles or adding extra styles, so it's likely to be imported at the end of your theme styles.
Use this plugin in your theme, assuming you are using SASS:
export default {
+ // ...
+ plugins: [palettePlugin({ preset: 'sass' })],
+}
+
Import the plugin's palette file where your theme needs to use the corresponding variables, such as in the Layout.vue
file:
<template>
+ <h1 class="palette-title">Hello, Palette!</h1>
+</template>
+
+<style lang="scss">
+/* import variables from the plugin's palette file */
+@import '@vuepress/plugin-palette/palette';
+
+/* set default value for variables */
+$color: red !default;
+
+/* use variables in your styles */
+.palette-title {
+ color: $color;
+}
+</style>
+
Then users can customize variables in .vuepress/styles/palette.scss
:
$color: green;
+
Import the plugin's style file after your theme's styles, for example, in the clientConfigFile
:
// import your theme's style file
+import 'path/to/your/theme/style'
+// import the plugin's style file
+import '@vuepress/plugin-palette/style'
+
Then users can add extra styles in .vuepress/styles/index.scss
and override the default styles of your theme:
h1 {
+ font-size: 2.5rem;
+}
+
Type: 'css' | 'sass' | 'less' | 'stylus'
Default: 'css'
Details:
Set preset for other options.
If you don't need advanced customization of the plugin, it's recommended to only set this option and omit other options.
Type: string
Default:
'.vuepress/styles/palette.css'
'.vuepress/styles/palette.scss'
'.vuepress/styles/palette.less'
'.vuepress/styles/palette.styl'
Details:
File path of the user palette file, relative to source directory.
The default value depends on the preset option.
The file is where users define style variables, and it's recommended to keep the default file path as a convention.
Type: string
Default:
'styles/palette.css'
'styles/palette.scss'
'styles/palette.less'
'styles/palette.styl'
Details:
File path of the generated palette temp file, relative to temp directory.
The default value depends on the preset option.
You should import the palette file via '@vuepress/plugin-palette/palette'
alias, so you don't need to change this option in most cases.
Type: string
Default:
'.vuepress/styles/index.css'
'.vuepress/styles/index.scss'
'.vuepress/styles/index.less'
'.vuepress/styles/index.styl'
Details:
File path of the user style file, relative to source directory.
The default value depends on the preset option.
The file is where users override default styles or add extra styles, and it's recommended to keep the default file path as a convention.
Type: string
Default:
'styles/index.css'
'styles/index.scss'
'styles/index.less'
'styles/index.styl'
Details:
File path of the generated style temp file, relative to temp directory.
The default value depends on the preset option.
You should import the style file via '@vuepress/plugin-palette/style'
alias, so you don't need to change this option in most cases.
Type: (filePath: string) => string
Default:
(filePath) => `@import '${filePath}';\n`
(filePath) => `@forward 'file:///${filePath}';\n`
(filePath) => `@import '${filePath}';\n`
(filePath) => `@require '${filePath}';\n`
Details:
Function to generate import code.
The default value depends on the preset option.
This option is used for generating tempPaletteFile and tempStyleFile, and you don't need to change this option in most cases.
This plugin will enable syntax highlighting for markdown code fence with Prism.js.
This plugin has been integrated into the default theme.
Notice that this plugin would only tokenize the code fence without adding styles. When using it with a custom theme, you may need to choose and import Prism.js style theme yourself.
npm i -D @vuepress/plugin-prismjs@next
+
import { prismjsPlugin } from '@vuepress/plugin-prismjs'
+
+export default {
+ plugins: [
+ prismjsPlugin({
+ // options
+ }),
+ ],
+}
+
Type: string[]
Default: ['markdown', 'jsdoc', 'yaml']
Details:
Languages to preload.
By default, languages will be loaded on demand when parsing markdown files.
However, Prism.js has some potential issues about loading languages dynamically. To avoid them, you can preload languages via this option.
Provide a popup component for users to activate the new PWA service worker manually.
This plugin must be used together with pwa plugin, and the skipWaiting
option must not be set to true
.
When the new service worker is ready, a popup will appear in the right bottom of the page to ask users to activate the waiting service worker.
npm i -D @vuepress/plugin-pwa-popup@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup'
+
+export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, { message: string, buttonText: string }>
Details:
The messages of the popup in different locales.
If this option is not specified, it will fallback to default messages.
Example:
export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ locales: {
+ '/': {
+ message: 'New content is available.',
+ buttonText: 'Refresh',
+ },
+ '/zh/': {
+ message: '发现新内容可用',
+ buttonText: '刷新',
+ },
+ },
+ }),
+ ],
+}
+
You can customize the style of the popup via CSS variables:
:root {
+ --pwa-popup-z-index: 10;
+ --pwa-popup-text-color: #2c3e50;
+ --pwa-popup-bg-color: #ffffff;
+ --pwa-popup-border-color: #3eaf7c;
+ --pwa-popup-shadow: 0 4px 16px var(--pwa-popup-border-color);
+ --pwa-popup-btn-text-color: #ffffff;
+ --pwa-popup-btn-bg-color: #3eaf7c;
+ --pwa-popup-btn-hover-bg-color: #4abf8a;
+}
+
Make your VuePress site a Progressive Web Application (PWA).
This plugin uses workbox-build to generate service worker file, and uses register-service-worker to register service worker.
WARNING
If you enabled this plugin once and you want to disable it, you might need `@vuepress/plugin-remove-pwa to remove the existing service worker.
npm i -D @vuepress/plugin-pwa@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+
+export default {
+ plugins: [
+ pwaPlugin({
+ // options
+ }),
+ ],
+}
+
To make your website fully compliant with PWA, you need to create a Web app manifests file and set the icons, colors, etc. for your PWA.
You need to put your manifest file and icons into the public files directory. In the following example, we assume that you are using the default public directory .vuepress/public
.
Typically .vuepress/public/manifest.webmanifest
:
{
+ "name": "VuePress",
+ "short_name": "VuePress",
+ "description": "Vue-powered Static Site Generator",
+ "start_url": "/index.html",
+ "display": "standalone",
+ "background_color": "#fff",
+ "theme_color": "#3eaf7c",
+ "icons": [
+ {
+ "src": "/images/icons/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/images/icons/android-chrome-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ }
+ ]
+}
+
To make your PWA more accessible, you need to generate some icons, and put them inside the public directory.
Make sure the path of icons matches the icons
field in your manifest file:
.vuepress/public/images/icons/android-chrome-192x192.png
.vuepress/public/images/icons/android-chrome-384x384.png
TIP
Some tools can help to do that. For example, Favicon Generator would help you to generate icons together with a sample manifest file.
You also need to set some tags via head option to deploy the manifest:
export default {
+ head: [
+ ['link', { rel: 'manifest', href: '/manifest.webmanifest' }],
+ ['meta', { name: 'theme-color', content: '#3eaf7c' }],
+ // ...other tags
+ ],
+}
+
This plugin accepts all parameters of workbox-build's generateSW method in its options, except globDirectory
and swDest
.
For example, you can set skipWaiting: true
to auto activate the new service worker once it is ready:
export default {
+ plugins: [
+ pwaPlugin({
+ skipWaiting: true,
+ }),
+ ],
+}
+
But if you omit skipWaiting
or set it to false
, you have to activate the new service worker manually:
Type: string
Default: 'service-worker.js'
Details:
File path of the generated service worker file, which is relative to the dest directory.
The service worker file will only be generated in build
mode.
Details:
Returns the event emitter of this plugin.
You can add listener function to events that provided by register-service-worker.
Example:
import { usePwaEvent } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('ready', (registration) => {
+ console.log('Service worker is active.')
+ })
+ },
+}
+
Parameter | Type | Description |
---|---|---|
registration | ServiceWorkerRegistration | The registration of the service worker you want activate |
Details:
Call skipWaiting() to activate the waiting service worker.
Example:
import { usePwaEvent, useSkipWaiting } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('updated', (registration) => {
+ console.log('The waiting service worker is available.')
+ // activate the waiting service worker
+ useSkipWaiting(registration)
+ })
+ },
+}
+
This plugin will generate word count and estimated reading time for each page.
npm i -D @vuepress/plugin-reading-time@next
+
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default {
+ plugins: [
+ readingTimePlugin({
+ // options
+ }),
+ ],
+}
+
The plugin will inject reading time information into the readingTime
of the page data, where:
readingTime.minutes
: estimated reading time (minutes) number
readingTime.words
: word count number
For any page, you can get estimated reading time and word count from page.data.readingTime
:
page.data.readingTime // { minutes: 3.2, words: 934 }
+
You can access it for further processing in the extendsPage
lifecycle and other lifecycle:
export default {
+ // ...
+ extendsPage: (page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ },
+
+ onInitialized: (app) => {
+ app.pages.map((page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ })
+ },
+}
+
You can import useReadingTimeData
and useReadingTimeLocale
from @vuepress/plugin-reading-time/client
to get the reading time data and locale data of the current page:
<script setup lang="ts">
+import {
+ useReadingTimeData,
+ useReadingTimeLocale,
+} from '@vuepress/plugin-reading-time/client'
+
+const readingTimeData = useReadingTimeData() // { minutes: 1.1, words: 100 }
+const readingTimeLocale = useReadingTimeLocale() // { time: "1 minute", words: "100 words" }
+</script>
+
number
300
Type: ReadingTimeLocaleConfig
interface ReadingTimeLocaleData {
+ /**
+ * Word template, `$word` will be automatically replaced by actual words
+ */
+ word: string
+
+ /**
+ * Text for less than one minute
+ */
+ less1Minute: string
+
+ /**
+ * Time template
+ */
+ time: string
+}
+
+interface ReadingTimeLocaleConfig {
+ [localePath: string]: ReadingTimeLocaleData
+}
+
Required: No
Details:
Locales config for reading-time plugin.
You can import and use these APIs from @vuepress/plugin-reading-time/client
:
These APIs won't throw even you disable the plugin.
interface ReadingTime {
+ /** Expect reading time in minute unit */
+ minutes: number
+ /** Words count of content */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
null
is returned when the plugin is disabled.
interface ReadingTimeLocale {
+ /** Expect reading time text in locale */
+ time: string
+ /** Word count text in locale */
+ words: string
+}
+
+const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>
+
This plugin is targeting plugin and theme developers mostly, so we provide a "Use API":
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ useReadingTimePlugin(app, {
+ // your options
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
Why you should use "Use API"
useReadingTimePlugin
automatically detects if the plugin is registered and avoid registering multiple times.extendsPage
lifecycle, then @vuepress/plugin-reading-time
must be called before your theme or plugin, otherwise you will get undefined
for page.data.readingTime
. The useReadingTimePlugin
ensures that @vuepress/plugin-reading-time
is called before your theme or plugin.We also provides a removeReadingTimePlugin
api to remove the plugin.You can use this to ensure your call take effect or clear the plugin:
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ // this removes any existing reading time plugin at this time
+ removeReadingTimePlugin(app)
+
+ // so this will take effect even if there is a reading time plugin registered before
+ useReadingTimePlugin(app, {
+ // your options
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
This plugin can automatically handle redirects for your site.
npm i -D @vuepress/plugin-redirect@next
+
import { redirectPlugin } from '@vuepress/plugin-redirect'
+
+export default {
+ plugins: [
+ redirectPlugin({
+ // options
+ }),
+ ],
+}
+
If you change the address of an existing page, you can use the redirectFrom
option in Frontmatter to redirect to the address of this page, which ensures that users are redirected to the new address when they visit the old link.
If you need to redirect an existing page to a new page, you can use the redirectTo
option in Frontmatter to set the address to redirect to. This way the page will redirect to the new address when accessed.
You can also set config
with a redirect map in plugin options, see config for more details.
The plugin can automatically redirect non-multilingual links to the multilingual pages the user needs based on the user's language preference.
To achieve this, you need to leave the default language directory (/
) blank and set autoLocale: true
in plugin options. The plugin will automatically redirect to the correct page according to the user's language.
I.E.: you need to set the following directory structure:
.
+├── en
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+├── zh
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+└── other_languages
+ ├── ...
+ ├── page.md
+ └── README.md
+
And set locales
in theme options with:
export default {
+ locales: {
+ '/en/': {
+ lang: 'en-US',
+ // ...
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ // ...
+ },
+ // other languages
+ },
+ // ...
+}
+
So when a user accesses /
or /page.html
, they are automatically redirected to /en/
/en/page.html
and /en/
/en/page.html
based on current browser language.
Customizing fallback behavior
Sometimes, users may add more than one language to the system settings. By default, when a site supports a preferred language, but the page not exists for the preferred language, the plugin attempts to match the alternate language set by the user.
If you don't need to fall back to the user's alternate language, but directly match the user's preferred language, set localeFallback: false
in the plugin options.
Customizing missing behavior
Sometimes, when a user visits a page, the document does not yet contain the language version the user needs (a common case is that the current page has not been localized in the relevant language), so the plugin needs to perform a default action, which you can customize by defaultBehavior
in the plugin options:
"defaultLocale"
: Redirect to default language or first available language page (default behavior)"homepage"
: redirect to the home page in the current language (only available if the document contains the user's language)"404"
: Redirect to page 404 in current language (only available if the document contains the user's language)Customizing default locale path
You can customize the default locale path by setting defaultLocale
in the plugin options. By default, the plugin uses the first locale key in locales
as the default language.
The plugin supports automatically switching the link to the multilingual page that the user needs according to the user's language preference when opening a multilingual document. In order to achieve this, you need to set switchLocale
in the plugin options, which can be the following two values:
direct
: switch directly to the user language preference page without askingmodal
: When the user's language preference is different from the current page language, show a modal asking whether to switch languageBy default, the plugin generates a locale setting by reading locale path
and lang
from the site's locales
option. Sometimes, you may want multiple languages to hit the same path, in which case you should set localeConfig
in plugin options.
For example, you might want all English users to match to /en/
and Chinese Traditional users to /zh/
, then you can set:
redirect({
+ localeConfig: {
+ '/en/': ['en-US', 'en-UK', 'en'],
+ '/zh/': ['zh-CN', 'zh-TW', 'zh'],
+ },
+})
+
Sometimes you may change base
or use new domain for your site, so you may want the original site automatically redirects to the new one.
To solve this, the plugin provide vp-redirect
cli.
Usage:
+ $ vp-redirect generate [sourceDir]
+
+Options:
+ --hostname <hostname> Hostname to redirect to (E.g.: https://new.example.com/) (default: /)
+ -c, --config <config> Set path to config file
+ -o, --output <output> Set the output directory (default: .vuepress/redirect)
+ --cache <cache> Set the directory of the cache files
+ -t, --temp <temp> Set the directory of the temporary files
+ --clean-cache Clean the cache files before generation
+ --clean-temp Clean the temporary files before generation
+ -h, --help Display this message
+
You need to pass in VuePress project source dir and also set the hostname
option. The redirect helper cli will initialize your VuePress project to get pages, then generate and output the redirect html files to the output directory.
By default, the plugin will output to .vuepress/redirect
directory under source directory. And you should upload it to your original site to provide redirection.
Type: Record<string, string> | ((app: App) => Record<string, string>)
Details: Redirect map.
Example:
When base is set to /base/
:
/base/foo.html
to /base/bar.html
/base/baz.html
to https://example.com/qux.html
.redirect({
+ config: {
+ '/foo.html': '/bar.html',
+ '/baz.html': 'https://example.com/qux.html',
+ },
+})
+
Redirect post folder to posts folder:
redirect({
+ hostname: 'https://example.com',
+ config: (app) =>
+ Object.fromEntries(
+ app.pages
+ .filter(({ path }) => path.startsWith('/posts/'))
+ .map(({ path }) => [path.replace(/^\/posts\//, '/post/'), path]),
+ ),
+})
+
boolean
false
Type: "direct" | "modal" | false
Default: false
Details:
Whether switch to a new locale based on user preference.
"direct"
: redirect to the new locale directly without asking"modal"
: show a modal to let user choose whether to switch to the new localeType: Record<string, string | string[]>
Details: Locale language config
boolean
true
"defaultLocale" | "homepage" | "404"
"defaultLocale"
string
string | string[]
string
Register Vue components from component files or directory automatically.
npm i -D @vuepress/plugin-register-components@next
+
import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ // options
+ }),
+ ],
+}
+
Type: Record<string, string>
Default: {}
Details:
An object that defines name of components and their corresponding file path.
The key will be used as the component name, and the value is an absolute path of the component file.
If the component name from this option conflicts with componentsDir option, this option will have a higher priority.
Example:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ components: {
+ FooBar: path.resolve(__dirname, './components/FooBar.vue'),
+ },
+ }),
+ ],
+}
+
Type: string | null
Default: null
Details:
Absolute path to the components directory.
Files in this directory which are matched with componentsPatterns will be registered as Vue components automatically.
Example:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ componentsDir: path.resolve(__dirname, './components'),
+ }),
+ ],
+}
+
Components directory:
components
+├─ FooBar.vue
+└─ Baz.vue
+
Components will be registered like this:
import { defineAsyncComponent } from 'vue'
+
+app.component(
+ 'FooBar',
+ defineAsyncComponent(() => import('/path/to/components/FooBar.vue')),
+)
+
+app.component(
+ 'Baz',
+ defineAsyncComponent(() => import('/path/to/components/Baz.vue')),
+)
+
Type: string[]
Default: ['**/*.vue']
Details:
Patterns to match component files using globby.
The patterns are relative to componentsDir.
Type: (filename: string) => string
Default: (filename) => path.trimExt(filename.replace(/\/|\\/g, '-'))
Details:
A function to get component name from the filename.
It will only take effect on the files in the componentsDir which are matched with the componentsPatterns.
Notice that the filename
is a filepath relative to componentsDir.
This plugin removes any related service worker from your VuePress site, so that users can still get updates if you removed any PWA plugin after enabling it.
Why this plugin is needed if you used PWA plugin once?
PWA plugins like @vuepress/plugin-pwa
register service worker to your site, which will cache your site and make it available offline.
However, if you remove pwa plugin, the old service worker will still be there, but they can never get an update because they can never found a new service worker to update to. So users will stay with the old version of your site.
To solve this problem:
npm i -D @vuepress/plugin-remove-pwa@next
+
import { removePwaPlugin } from '@vuepress/plugin-remove-pwa'
+
+export default {
+ plugins: [
+ removePwaPlugin({
+ // options
+ }),
+ ],
+}
+
string
'workbox'
string
'service-worker.js'
This plugin will set direction to rtl on configured locales.
npm i -D @vuepress/plugin-rtl@next
+
import { rtlPlugin } from '@vuepress/plugin-rtl'
+
+export default {
+ plugins: [
+ rtlPlugin({
+ // options
+ locales: ['/ar/'],
+ }),
+ ],
+}
+
string[]
['/']
Type: SelectorOptions
interface SelectorOptions {
+ [element: string]: {
+ [attrs: string]: string
+ }
+}
+
Default: { 'html': { dir: 'rtl' } }
Details:
Selector to enable rtl.
The default settings mean that the dir
attribute of the html
element will be set to rtl
in rtl locales.
Provide local search to your documentation site.
TIP
Default theme will add search box to the navbar once you configure this plugin correctly.
This plugin may not be used directly in other themes, so you'd better refer to the documentation of your theme for more details.
npm i -D @vuepress/plugin-search@next
+
import { searchPlugin } from '@vuepress/plugin-search'
+
+export default {
+ plugins: [
+ searchPlugin({
+ // options
+ }),
+ ],
+}
+
This plugin will generate search index from your pages locally, and load the search index file when users enter your site. In other words, this is a lightweight built-in search which does not require any external requests.
However, when your site has a large number of pages, the size of search index file would be very large, which could slow down the page loading speed. In this case, we recommend you to use a more professional solution - docsearch.
Type: Record<string, { placeholder: string }>
Details:
The text of the search box in different locales.
If this option is not specified, it will fallback to default text.
Example:
export default {
+ plugins: [
+ searchPlugin({
+ locales: {
+ '/': {
+ placeholder: 'Search',
+ },
+ '/zh/': {
+ placeholder: '搜索',
+ },
+ },
+ }),
+ ],
+}
+
(string | HotKeyOptions)[]
export interface HotKeyOptions {
+ /**
+ * Value of `event.key` to trigger the hot key
+ */
+ key: string;
+ /**
+ * Whether to press `event.altKey` at the same time
+ *
+ * @default false
+ */
+ alt?: boolean;
+ /**
+ * Whether to press `event.ctrlKey` at the same time
+ *
+ * @default false
+ */
+ ctrl?: boolean;
+ /**
+ * Whether to press `event.shiftKey` at the same time
+ *
+ * @default false
+ */
+ shift?: boolean;
+}
+
Default: ['s', '/']
Details:
Specify the event.key of the hotkeys.
When hotkeys are pressed, the search box input will be focused.
Set to an empty array to disable hotkeys.
Type: number
Default: 5
Details:
Specify the maximum number of search results.
Type: (page: Page) => boolean
Default: () => true
Details:
A function to determine whether a page should be included in the search index.
true
to include the page.false
to exclude the page.Example:
export default {
+ plugins: [
+ searchPlugin({
+ // exclude the homepage
+ isSearchable: (page) => page.path !== '/',
+ }),
+ ],
+}
+
Type: (page: Page) => string[]
Default: () => []
Details:
A function to add extra fields to the search index of a page.
By default, this plugin will use page title and headers as the search index. This option could help you to add more searchable fields.
Example:
export default {
+ plugins: [
+ searchPlugin({
+ // allow searching the `tags` frontmatter
+ getExtraFields: (page) => page.frontmatter.tags ?? [],
+ }),
+ ],
+}
+
You can customize the style of the search box via CSS variables:
:root {
+ --search-bg-color: #ffffff;
+ --search-accent-color: #3eaf7c;
+ --search-text-color: #2c3e50;
+ --search-border-color: #eaecef;
+ --search-item-text-color: #5d81a5;
+ --search-item-focus-bg-color: #f3f4f5;
+ --search-input-width: 8rem;
+ --search-result-width: 20rem;
+}
+
Details:
This plugin will register a <SearchBox />
component globally, and you can use it without any props.
Put this component to where you want to place the search box. For example, default theme puts this component to the end of the navbar.
TIP
This component is mainly used for theme development. You don't need to use it directly in most cases.
Type: string
Required: Yes
Details:
Deploy hostname.
Type: Author
type AuthorName = string
+
+interface AuthorInfo {
+ /**
+ * Author name
+ */
+ name: string
+
+ /**
+ * Author website
+ */
+ url?: string
+
+ /**
+ * Author email
+ */
+ email?: string
+}
+
+type Author = AuthorName | AuthorName[] | AuthorInfo | AuthorInfo[]
+
Required: No
Details:
Default author.
Type: boolean
Default: true
Details:
Whether generate description automatically
Type: string | ((page: Page) => string | null)
Details:
Canonical link
Type: string
Details:
Fallback Image link when no image are found
Type: string
Details:
The age rating of the content, the format is [int]+
, such as "13+"
.
Type: string
Details:
Fill in your twitter username.
Type: (page: Page) => boolean
Details:
Use this option to judge whether the page is an article.
Type:
function ogp(
+ /** OGP info inferred by plugin */
+ ogp: SeoContent,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
Required: No
Details:
Custom OPG Generator.
You can use this options to edit OGP tags.
Type:
function jsonLd(
+ /** JSON-LD Object inferred by plugin */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
Required: No
Details:
Custom JSON-LD Generator.
You can use this options to edit JSON-LD properties.
Type:
function customHead(
+ /** Head tag config */
+ head: HeadConfig[],
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
Required: No
Details:
You can use this options to edit tags injected to <head>
.
This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site.
The plugin works out of the box. Without any config, it will extract information from the page content as much as possible to complete the necessary tags required by OGP and JSON-LD.
By default, the plugin will read the site config and page frontmatter to automatically generate tags as much as possible. Such as site name, page title, page type, writing date, last update date, and article tags are all automatically generated.
The following are the <meta>
tags and their values that will be injected into <head>
by default:
The following are the <meta>
tags and their value injected into <head>
by default to satisfy OGP:
Meta 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 in plugin options |
og:updated_time | page.git.updatedTime |
og:locale | page.lang |
og:locale:alternate | Other languages in siteData.locales |
twitter:card | "summary_large_image" (only available when image found) |
twitter:image:alt | page.title (only available when image 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 |
Property Name | Value |
---|---|
@context | "https://schema.org" |
@type | "NewsArticle" |
headline | page.title |
image | image in page || options.hostname + page.frontmatter.image || siteFavIcon in plugin options |
datePublished | page.frontmatter.date || page.git.createdTime |
dateModified | page.git.updatedTime |
author | page.frontmatter.author || options.author |
You can configure the head
option in the page's frontmatter to add specific tags to the page <head>
to enhance SEO. For example:
---
+head:
+ - - meta
+ - name: keywords
+ content: SEO plugin
+---
+
Will automatically inject <meta name="keywords" content="SEO plugin" />
.
The plugin also gives you full control over the build logic.
For most pages, there are basically only two types: articles and website, so the plugin provides the isArticle
option to allow you to provide logic for identifying articles.
The option accepts a function in the format (page: Page) => boolean
, by default all non-home pages generated from Markdown files are treated as articles.
TIP
If a page does fit into the "unpopular" genre like books, music, etc., you can handle them by setting the three options below.
You can use the plugin options ogp
to pass in a function to modify the default OGP object to your needs and return it.
function ogp(
+ /** OGP Object inferred by plugin */
+ ogp: SeoContent,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
For detailed parameter structure, see Config.
For example, if you are using a third-party theme and set a banner
in frontmatter for each article according to the theme requirements, then you can pass in the following ogp
:
seoPlugin({
+ ogp: (ogp, page) => ({
+ ...ogp,
+ 'og:image': page.frontmatter.banner || ogp['og:image'],
+ }),
+})
+
Like OGP, you can use the plugin options jsonLd
to pass in a function to modify the default JSON-LD object to your needs and return it.
function jsonLd(
+ /** JSON-LD Object inferred by plugin */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
If you are deploying your content to different sites, or same content under different URLs, you may need to set canonical
option to provide a "Canonical Link" for your page. You can either set a string which will be appended before page route link, or adding a custom function (page: Page) => string | null
to return a canonical link if necessary.
Example
If your sites are deployed under docs directory in example.com
, but available in:
http://example.com/docs/xxx
https://example.com/docs/xxx
http://www.example.com/docs/xxx
https://www.example.com/docs/xxx
(primary)To let search engine results always be the primary choice, you may need to set canonical
to https://www.example.com/docs/
, so that search engine will know that the fourth URL is preferred to be indexed.
Sometimes you may need to fit other protocols or provide the corresponding SEO tags in the format provided by other search engines. In this case, you can use the customHead
option, whose type is:
function customHead(
+ /** Head tag config */
+ head: HeadConfig[],
+ /** Page Object */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
You should modify the head
array in this function directly.
Search engine optimization (SEO) is the process of improving the quality and quantity of site traffic to a site or a web page from search engines. SEO targets unpaid traffic (known as "natural" or "organic" results) rather than direct traffic or paid traffic. Unpaid traffic may originate from different kinds of searches, including image search, video search, academic search, news search, and industry-specific vertical search engines.
As an internet marketing strategy, SEO considers how search engines work, the computer-programmed algorithms that dictate search engine behavior, what people search for, the actual search terms or keywords typed into search engines, and which search engines are preferred by their targeted audience. SEO is performed because a site will receive more visitors from a search engine when sites rank higher on the search engine results page (SERP). These visitors can then potentially be converted into customers.
Open Content Protocol OGP (Open Graph Protocol)
This plugin perfectly supports this protocol and will automatically generate <meta>
tags that conform to the protocol.
This plugin will generate "NewsArticle" scheme for article pages.
RDFa mainly marks HTML structure. This is what the plugin cannot support. uses this feature to pass Google's rich media structure test. You can consider using it.
Schema definition site for structural markup
You can use Google Rich Media Structure Test Tool to test this site.
This plugin will enable syntax highlighting for markdown code fence with Shiki (Shikiji).
TIP
Shiki is the syntax highlighter being used by VSCode. It has higher fidelity, but it could be slower than Prism.js, especially when you have a lot of code blocks.
You could consider disabling this plugin in dev
mode to get better development experience.
npm i -D @vuepress/plugin-shiki@next
+
import { shikiPlugin } from '@vuepress/plugin-shiki'
+
+export default {
+ plugins: [
+ shikiPlugin({
+ // options
+ langs: ['ts', 'json', 'vue', 'md', 'bash', 'diff'],
+ }),
+ ],
+}
+
Type: ShikiLang[]
Details:
Languages of code blocks to be parsed by shikiji.
This option will be forwarded to getHighlighter()
method of shikiji.
You need to provide the languages list you are using explicitly, otherwise shikiji won't load any languages.
Also see:
Type: ShikiTheme
Default: 'nord'
Details:
Theme of shikiji.
This option will be forwarded to codeToHtml()
method of shikiji.
Also see:
Type: Record<'dark' | 'light', ShikiTheme>
Details:
Dark / Light Dual themes of shikiji.
This option will be forwarded to codeToHtml()
method of shikiji.
Also see:
Type: string
Required: Yes
Details:
The domain name where the current site is deployed, the plugin needs this option to work.
Type: string[]
Details:
Extra link to be included.
If you have some links not including in VuePress Router (normally in public directory or generated by other tools directly), you may need this option.
Example: ['/about.html', '/api/']
Type: string[]
Default: ['/404.html']
Details:
Urls excluding from sitemap, starting with absolute path.
By default, all the urls generated by VuePress (excluding 404 page) will be added into sitemap.
Type: boolean
Default: false
Details:
Whether enabled in devServer.
TIP
For performance reasons, we do not provide hot reload. Reboot your devServer to sync your changes.
Type: string
Default: "http://localhost:${port}"
Details:
Hostname to use in devServer
Type: string
Default value: "sitemap.xml"
Details:
The output filename, relative to output directory.
Type: string
Default value: "sitemap.xsl"
Details:
Output xsl filename, relative to dest folder.
Type: string
Default value: "@vuepress/plugin-sitemap/templates/sitemap.xsl"
Details:
XSL content used as template.
Type: "always" | "hourly" | "daily" | "weekly" |"monthly" | "yearly" | "never"
Default value: "daily"
Details:
Page default update frequency, will be overridden by sitemap.changefreq in Frontmatter.
Type: number
Default: 0.5
Details:
Page priority, from 0
to 1
.
Type: (page: Page, app: App) => string
Details:
Last modify time getter. By default, the plugin will use the timestamp generated by git plugin.
Type: SitemapFrontmatterOptions | false
Details:
false
means exclude the page from sitemap.
Type: "always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never"
Default: "daily"
Details:
Page default update frequency. This will override changefreq in Plugin Options.
Type: number
Default: 0.5
Details:
Page priority, range from 0
to 1
.
This plugin will automatically generate a Sitemap for your site. To let this plugin work, you need to pass the deployed domain name to the hostname
option of the plugin. If you want to preview in devServer, set devServer
options.
The plugin will automatically generate the last update time of the page based on the Git timestamp of the page, and will also declare the alternative links of the page in other languages according to the locales' config.
By default, all site links except 404 page will be added to the Sitemap.
To add other pages to the Sitemap outside the VuePress project page, please turn them into an array and pass to the extraUrls
plugin option.
If you don't want certain pages to appear in the sitemap, you can turn their paths into an array and pass to the excludePaths
plugin option, or set sitemap
to false
in the frontmatter of the corresponding page.
You can also control the output link through the sitemapFilename
option of the plugin, the link is relative to output directory. By default, the plugin will use sitemap.xml
.
The default update cycle of the page is daily
(every day). To modify the entire page cycle, please set changefreq
in the plugin options. You can also set sitemap.changefreq
in the frontmatter of the page. Note that page has a higher priority.
The legal frequencies are:
"always"
"hourly"
"daily"
"weekly"
"monthly"
"yearly"
"never"
You can set priority
in the plugin to provide a default value. At the same time you can set the priority for each page through sitemap.priority
in frontmatter. Acceptable values are floating point numbers from 0
to 1
.
You can use option modifyTimeGetter
to return a time in ISO string format, which is generated by the Git plugin by default.
The following is an example based on the last modification time of a file.
// Based on file last modified time
+({
+ modifyTimeGetter: (page, app) =>
+ fs.statSync(app.dir.source(page.filePathRelative)).mtime.toISOString();
+})
+
Sitemaps provide SEO (Search Engine Optimization):
A sitemap enhances SEO by making all pages findable.
Most search engines only follow a limited number of links within a page, so when the site is very large, a sitemap becomes essential to make everything on the site accessible to search engines and visitors.
Sitemaps is a protocol for site administrators to publish pages that can be crawled on a site to search engine spiders. The content of sitemap files must follow the definition in XML format. Each URL can contain the update period and last update time, the priority of the URL across the site. This allows search engines to crawl site content better and more efficiently.
Together with robots.txt
Sitemap is basically used by search engines, when using this plugin, you'd better ensure that you have a valid robots.txt
in the .vuepress/public
directory to allow search engines spiders to visit your site. The simplest robots.txt is as follows (allow all search engines to access all paths)
User-agent: *
+
+Allow: /
+
Provide client data for your theme, with VuePress i18n support.
This plugin is mainly used to develop themes, and has been integrated into the default theme. You won't need to use it directly in most cases.
For theme authors, this plugin will help you to use the same i18n mechanism as VuePress and the default theme. But if you don't want to provide i18n support, or you want to implement in your own way, you don't need this plugin.
npm i -D @vuepress/plugin-theme-data@next
+
import { themeDataPlugin } from '@vuepress/plugin-theme-data'
+
+export default {
+ plugins: [
+ themeDataPlugin({
+ // options
+ }),
+ ],
+}
+
Type: ThemeData
Default: {}
Details:
The theme data object that you want to use in client side.
You can provide theme data in Node side via this option, and use it in client side via useThemeData and useThemeLocaleData.
Example:
export default {
+ plugins: [
+ themeDataPlugin({
+ themeData: {
+ foo: 'foo',
+ locales: {
+ '/zh/': {
+ foo: 'zh-foo',
+ },
+ },
+ },
+ }),
+ ],
+}
+
WARNING
The theme data object will be processed by JSON.stringify()
before forwarding to client side, so you should ensure that you are providing a JSON-friendly object.
Details:
Returns the theme data ref object.
The value is provided by themeData option.
Example:
import { useThemeData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeData = useThemeData<MyThemeData>()
+ console.log(themeData.value)
+ },
+}
+
Details:
Returns the theme data ref object in current locale.
The properties of current locale has been merged into the root-level properties.
Example:
import { useThemeLocaleData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeLocaleData = useThemeLocaleData<MyThemeData>()
+ console.log(themeLocaleData.value)
+ },
+}
+
This plugin will provide a table-of-contents (TOC) component.
npm i -D @vuepress/plugin-toc@next
+
import { tocPlugin } from '@vuepress/plugin-toc'
+
+export default {
+ plugins: [
+ tocPlugin({
+ // options
+ }),
+ ],
+}
+
Similar to the Table of Contents Markdown Syntax, the TOC component that provided by this plugin could be used in your markdown content directly:
<!-- markdown toc syntax -->
+
+[[toc]]
+
+<!-- vue toc component -->
+<Toc />
+
Both of them can be pre-rendered correctly in build mode. However, there are some differences between them.
The markdown syntax [[toc]]
could only be used in markdown files. It is parsed by markdown-it, and the generated TOC is static content.
The component <Toc/>
could be used in both markdown files and vue files. It is loaded by vue, and the generated TOC is a vue component.
This plugin could work together with @vuepress/plugin-active-header-links by setting the headerLinkSelector to match the linkClass
option. When the page scroll to a certain header anchor, this corresponding link will be added linkActiveClass
class name.
Therefore, this plugin is more useful for theme developers.
Type: string
Default: 'Toc'
Details:
Specify the name of the TOC component.
Type: Partial<TocPropsOptions>
Default: {}
Details:
Override the default values of the component options prop.
The TOC component also accepts props for customization.
<template>
+ <Toc :headers="headers" :options="options" />
+</template>
+
PageHeader[]
interface PageHeader {
+ level: number
+ title: string
+ slug: string
+ children: PageHeader[]
+}
+
Details:
Specify the headers array to render.
If this prop is not specified, the headers of current page will be used.
Partial<TocPropsOptions>
interface TocPropsOptions {
+ containerTag: string
+ containerClass: string
+ listClass: string
+ itemClass: string
+ linkTag: 'a' | 'RouterLink'
+ linkClass: string
+ linkActiveClass: string
+ linkChildrenActiveClass: string
+}
+
Default:
Following default values can be overridden by defaultPropsOptions.
const defaultOptions = {
+ containerTag: 'nav',
+ containerClass: 'vuepress-toc',
+ listClass: 'vuepress-toc-list',
+ itemClass: 'vuepress-toc-item',
+ linkTag: 'RouterLink',
+ linkClass: 'vuepress-toc-link',
+ linkActiveClass: 'active',
+ linkChildrenActiveClass: 'active',
+}
+
Details:
Customize the TOC component.
If the containerTag
is set to an empty string ''
, the <nav>
container will be removed totally.
Example:
The rendered TOC component with default options looks like:
<template>
+ <!-- container -->
+ <nav class="vuepress-toc">
+ <!-- list -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link -->
+ <RouterLink class="vuepress-toc-link" to="#foo">Foo</RouterLink>
+ </li>
+ <!-- item with children -->
+ <li class="vuepress-toc-item">
+ <!-- link (children active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar">Bar</RouterLink>
+ <!-- list (children) -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link (active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar-child">
+ Bar Child
+ </RouterLink>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+</template>
+
Props:
'tip' | 'warning' | 'danger'
'tip'
string
''
'top' | 'middle' | 'bottom' | undefined
undefined
Example:
Input
- VuePress - <Badge type="tip" text="v2" vertical="top" />
+- VuePress - <Badge type="warning" text="v2" vertical="middle" />
+- VuePress - <Badge type="danger" text="v2" vertical="bottom" />
+
Output
Details:
Wrapper of the CodeGroupItem components.
Props:
string
true
boolean
false
Details:
This component must be placed inside a CodeGroup component.
Use the active
prop to set the initial active item, or the first item will be activated by default.
Example:
Input
<CodeGroup>
+ <CodeGroupItem title="pnpm">
+
+```bash:no-line-numbers
+pnpm install
+```
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="yarn">
+
+```bash:no-line-numbers
+yarn install
+```
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="npm" active>
+
+```bash:no-line-numbers
+npm install
+```
+
+ </CodeGroupItem>
+</CodeGroup>
+
Output
pnpm install
+
yarn install
+
npm install
+
WARNING
You must add an empty line between the starting tag of <CodeGroupItem>
and the code fence, otherwise the code fence will not be parsed correctly by Markdown.
All content must be valid Markdown first, and then a Vue SFC.
Learn more: Cookbook > Markdown and Vue SFC
Alternatively, you can use the custom containers.
Type: string
Details:
Hostname to be deployed, e.g.: https://example.com
Type: { [path: string]: Partial<DefaultThemeLocaleData> }
Default: {}
Details:
Specify locales for i18n support.
All the options inside the Locale Config section can be used in locales.
This option will only take effect in default theme, so don't confuse with locales
in Site Config.
Also see:
Config of this section can be used as normal config, and can also be used in the locales option.
Type: 'auto' | 'light' | 'dark'
Default: 'auto'
Details:
Default color mode.
If set to 'auto'
, the initial color mode will be automatically set according to prefers-color-scheme.
Also see:
Type: boolean
Default: true
Details:
Enable color mode switching or not.
If set to true
, a button to switch color mode will be displayed in the navbar.
Also see:
Type: string
Default: /
Details:
Specify the path of the homepage.
This will be used for:
Type: false | (NavbarItem | NavbarGroup | string)[]
Default: []
Details:
Configuration of navbar.
Set to false
to disable navbar.
To configure the navbar items, you can set it to a navbar array, each item of which could be a NavbarItem
object, a NavbarGroup
object, or a string:
NavbarItem
object should have a text
field and a link
field, could have an optional activeMatch
field.NavbarGroup
object should have a text
field and a children
field. The children
field should be a navbar array, too.NavbarItem
object, using the page title as text
, and the page route path as link
.Example 1:
export default {
+ theme: defaultTheme({
+ navbar: [
+ // NavbarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ },
+ // NavbarGroup
+ {
+ text: 'Group',
+ children: ['/group/foo.md', '/group/bar.md'],
+ },
+ // string - page file path
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ navbar: [
+ // nested group - max depth is 2
+ {
+ text: 'Group',
+ children: [
+ {
+ text: 'SubGroup',
+ children: ['/group/sub/foo.md', '/group/sub/bar.md'],
+ },
+ ],
+ },
+ // control when should the item be active
+ {
+ text: 'Group 2',
+ children: [
+ {
+ text: 'Always active',
+ link: '/',
+ // this item will always be active
+ activeMatch: '/',
+ },
+ {
+ text: 'Active on /foo/',
+ link: '/not-foo/',
+ // this item will be active when current route path starts with /foo/
+ // regular expression is supported
+ activeMatch: '^/foo/',
+ },
+ ],
+ },
+ ],
+ }),
+}
+
Type: null | string
Details:
Specify the url of logo image.
The logo image will be displayed at the left end of the navbar.
Set to null
to disable logo.
Example:
export default {
+ theme: defaultTheme({
+ // public file path
+ logo: '/hero.png',
+ // url
+ logo: 'https://vuejs.org/images/logo.png',
+ }),
+}
+
Type: null | string
Details:
Specify the url of logo image to be used in dark mode.
You can make use of this option if you want to use different logo config in dark mode.
Set to null
to disable logo in dark mode. Omit this option to use logo in dark mode.
Also see:
Type: null | string
Details:
Specify the alt text of the logo image.
If not specified, defaults to be the same as the site title.
Type: string
Details:
Specify the repository url of your project.
This will be used as the link of the repository link, which will be displayed as the last item of the navbar.
export default {
+ theme: defaultTheme({
+ // If you set it in the form of `organization/repository`
+ // we will take it as a GitHub repo
+ repo: 'vuejs/vuepress',
+ // You can also set it to a URL directly
+ repo: 'https://gitlab.com/foo/bar',
+ }),
+}
+
Type: false | 'auto' | SidebarConfigArray | SidebarConfigObject
Default: 'auto'
Details:
Configuration of sidebar.
You can override this global option via sidebar frontmatter in your pages.
Set to false
to disable sidebar.
If you set it to 'auto'
, the sidebar will be automatically generated from the page headers.
To configure the sidebar items manually, you can set this option to a sidebar array, each item of which could be a SidebarItem
object or a string:
SidebarItem
object should have a text
field, could have an optional link
field, an optional children
field and an optional collapsible
field. The children
field should be a sidebar array. The collapsible
field controls whether the item is collapsible.SidebarItem
object, whose text
is the page title, link
is the page route path, and children
is automatically generated from the page headers.If you want to set different sidebar for different sub paths, you can set this option to a sidebar object:
'heading'
to automatically generate the sidebar from the page headers for just the corresponding path.Example 1:
export default {
+ theme: defaultTheme({
+ // sidebar array
+ // all pages will use the same sidebar
+ sidebar: [
+ // SidebarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ children: [
+ // SidebarItem
+ {
+ text: 'github',
+ link: 'https://github.com',
+ children: [],
+ },
+ // string - page file path
+ '/foo/bar.md',
+ ],
+ },
+ // string - page file path
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // sidebar object
+ // pages under different sub paths will use different sidebar
+ sidebar: {
+ '/guide/': [
+ {
+ text: 'Guide',
+ children: ['/guide/introduction.md', '/guide/getting-started.md'],
+ },
+ ],
+ '/reference/': 'heading',
+ },
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // collapsible sidebar
+ sidebar: {
+ '/reference/': [
+ {
+ text: 'VuePress Reference',
+ collapsible: true,
+ children: ['/reference/cli.md', '/reference/config.md'],
+ },
+ {
+ text: 'Bundlers Reference',
+ collapsible: true,
+ children: [
+ '/reference/bundler/vite.md',
+ '/reference/bundler/webpack.md',
+ ],
+ },
+ ],
+ },
+ }),
+}
+
Type: number
Default: 2
Details:
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
0
to disable all levels of headers.1
to include <h2>
headers.2
to include <h2>
and <h3>
headers.The max value depends on which levels of headers you have extracted via markdown.headers.level.
The default value of markdown.headers.level
is [2, 3]
, so the default max value of sidebarDepth
is 2
.
You can override this global option via sidebarDepth frontmatter in your pages.
Type: boolean
Default: true
Details:
Enable the edit this page link or not.
You can override this global option via editLink frontmatter in your pages.
Type: string
Details:
Specify the pattern of the edit this page link.
This will be used for generating the edit this page link.
If you don't set this option, the pattern will be inferred from the docsRepo option. But if your documentation repository is not hosted on a common platform, for example, GitHub, GitLab, Bitbucket, Gitee, etc., you have to set this option explicitly to make the edit this page link work.
Usage:
Pattern | Description |
---|---|
:repo | The docs repo url, i.e. docsRepo |
:branch | The docs repo branch, i.e. docsBranch |
:path | The path of the page source file, i.e. docsDir joins the relative path of the page file |
Example:
export default {
+ theme: defaultTheme({
+ docsRepo: 'https://gitlab.com/owner/name',
+ docsBranch: 'master',
+ docsDir: 'docs',
+ editLinkPattern: ':repo/-/edit/:branch/:path',
+ }),
+}
+
The generated link will look like 'https://gitlab.com/owner/name/-/edit/master/docs/path/to/file.md'
.
Type: string
Details:
Specify the repository url of your documentation source files.
This will be used for generating the edit this page link.
If you don't set this option, it will use the repo option by default. But if your documentation source files are in a different repository, you will need to set this option.
Type: string
Default: 'main'
Details:
Specify the repository branch of your documentation source files.
This will be used for generating the edit this page link.
Type: string
Default: ''
Details:
Specify the directory of your documentation source files in the repository.
This will be used for generating the edit this page link.
Type: boolean
Default: true
Details:
Enable the last updated timestamp or not.
You can override this global option via lastUpdated frontmatter in your pages. Notice that if you have already set this option to false
, this feature will be disabled totally and could not be enabled in locales nor page frontmatter.
Type: boolean
Default: true
Details:
Enable the contributors list or not.
You can override this global option via contributors frontmatter in your pages. Notice that if you have already set this option to false
, this feature will be disabled totally and could not be enabled in locales nor page frontmatter.
VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
Default theme's Layout
provides some slots:
navbar
navbar-before
navbar-after
sidebar
sidebar-top
sidebar-bottom
page
page-top
page-bottom
page-content-top
page-content-bottom
With the help of them, you can add or replace content easily. Here comes an example to introduce how to extend default theme with layout slots.
Firstly, create a client config file .vuepress/client.ts
:
import { defineClientConfig } from 'vuepress/client'
+import Layout from './layouts/Layout.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout,
+ },
+})
+
Next, create the .vuepress/layouts/Layout.vue
, and make use of the slots that provided by the Layout
of default theme:
<script setup>
+import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'
+</script>
+
+<template>
+ <ParentLayout>
+ <template #page-bottom>
+ <div class="my-footer">This is my custom page footer</div>
+ </template>
+ </ParentLayout>
+</template>
+
+<style lang="css">
+.my-footer {
+ text-align: center;
+}
+</style>
+
Then the default Layout
layout has been overridden by your own local layout, which will add a custom footer to every normal pages in default theme (excluding homepage):
The layout slots are useful, but sometimes you might find it's not flexible enough. Default theme also provides the ability to replace a single component.
Default theme has registered alias for every non-global components with a @theme
prefix. For example, the alias of HomeFooter.vue
is @theme/HomeFooter.vue
.
Then, if you want to replace the HomeFooter.vue
component, just override the alias in your config file .vuepress/config.ts
:
import { defaultTheme } from '@vuepress/theme-default'
+import { getDirname, path } from 'vuepress/utils'
+import { defineUserConfig } from 'vuepress'
+
+const __dirname = getDirname(import.meta.url)
+
+export default defineUserConfig({
+ theme: defaultTheme(),
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+})
+
Instead of extending the default theme directly in .vuepress/config.ts
and .vuepress/client.ts
, you can also develop your own theme extending the default theme:
import { defaultTheme, type DefaultThemeOptions } from '@vuepress/theme-default'
+import type { Theme } from 'vuepress/core'
+import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export const childTheme = (options: DefaultThemeOptions): Theme => {
+ return {
+ name: 'vuepress-theme-child',
+ extends: defaultTheme(options),
+
+ // override layouts in child theme's client config file
+ // notice that you would build ts to js before publishing to npm,
+ // so this should be the path to the js file
+ clientConfigFile: path.resolve(__dirname, './client.js'),
+
+ // override component alias
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+ }
+}
+
Frontmatter in this section will take effect in all types of pages.
Type: boolean
Details:
Provided by @vuepress/plugin-external-link-icon.
Also see:
Type: boolean
Details:
Show navbar on this page or not.
If you disable navbar in theme config, this frontmatter will not take effect.
Also see:
Type: string
Details:
Add extra class name to this page.
Example:
---
+pageClass: custom-page-class
+---
+
Then you can customize styles of this page in .vuepress/styles/index.scss
file:
.theme-container.custom-page-class {
+ /* page styles */
+}
+
Frontmatter in this section will only take effect in home pages.
Type: boolean
Details:
Specify whether the page is homepage or a normal page.
If you don't set this frontmatter or set it to false
, the page would be a normal page.
Example:
---
+home: true
+---
+
Type: string
Details:
Specify the url of the hero image.
Example:
---
+# public file path
+heroImage: /images/hero.png
+# url
+heroImage: https://vuejs.org/images/logo.png
+---
+
Type: string
Details:
Specify the url of hero image to be used in dark mode.
You can make use of this option if you want to use different heroImage config in dark mode.
Also see:
Type: string
Details:
Specify the alt
attribute of the hero image.
This will fallback to the heroText.
Type: number
Default: 280
Details:
Specify the height
attribute of the hero <img>
tag.
You may need to reduce this value if the height of your hero image is less than the default value.
Notice that the height is also constrained by CSS. This attribute is to reduce Cumulative Layout Shift (CLS) that caused by the loading of the hero image.
Type: string | null
Details:
Specify the the hero text.
This will fallback to the site title.
Set to null
to disable hero text.
Type: string | null
Details:
Specify the the tagline.
This will fallback to the site description.
Set to null
to disable tagline.
Array<{
+ text: string
+ link: string
+ type?: 'primary' | 'secondary'
+}>
+
Details:
Configuration of the action buttons.
Example:
---
+actions:
+ - text: Get Started
+ link: /guide/getting-started.html
+ type: primary
+ - text: Introduction
+ link: /guide/introduction.html
+ type: secondary
+---
+
Array<{
+ title: string
+ details: string
+}>
+
Details:
Configuration of the features list.
Example:
---
+features:
+ - title: Simplicity First
+ details: Minimal setup with markdown-centered project structure helps you focus on writing.
+ - title: Vue-Powered
+ details: Enjoy the dev experience of Vue, use Vue components in markdown, and develop custom themes with Vue.
+ - title: Performant
+ details: VuePress generates pre-rendered static HTML for each page, and runs as an SPA once a page is loaded.
+---
+
Type: string
Details:
Specify the content of the footer.
Type: boolean
Details:
Allow HTML in footer or not.
If you set it to true
, the footer will be treated as HTML code.
Frontmatter in this section will only take effect in normal pages.
Type: boolean
Details:
Enable the edit this page link in this page or not.
Also see:
Type: string
Details:
Specify the pattern of the edit this page link of this page.
Also see:
Type: boolean
Details:
Enable the last updated timestamp in this page or not.
Also see:
Type: boolean
Details:
Enable the contributors list in this page or not.
Also see:
Type: false | 'auto' | SidebarConfigArray | SidebarConfigObject
Details:
Configure the sidebar of this page.
Also see:
Type: number
Details:
Configure the sidebar depth of this page.
Also see:
Type: NavLink | string
Details:
Specify the link of the previous page.
If you don't set this frontmatter, the link will be inferred from the sidebar config.
To configure the prev link manually, you can set this frontmatter to a NavLink
object or a string:
NavLink
object should have a text
field and a link
field.NavLink
object, whose text
is the page title, and link
is the page route path.Example:
---
+# NavLink
+prev:
+ text: Get Started
+ link: /guide/getting-started.html
+
+# NavLink - external url
+prev:
+ text: GitHub
+ link: https://github.com
+
+# string - page file path
+prev: /guide/getting-started.md
+
+# string - page file relative path
+prev: ../../guide/getting-started.md
+---
+
Type: NavLink | string
Details:
Specify the link of the next page.
If you don't set this frontmatter, the link will be inferred from the sidebar config.
The type is the same as prev frontmatter.
Install @vuepress/theme-default
:
npm install @vuepress/theme-default@next
+
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ // set theme config here
+ }),
+}
+
These options configure locale-related texts.
If your site is served in a different language besides English, you should set these options per locale to provide translations.
Type: string
Details:
Specify the repository label of your project.
This will be used as the text of the repository link, which will be displayed as the last item of the navbar.
If you don't set this option explicitly, it will be automatically inferred from the repo option.
Type: string
Details:
Specify the text of the select language menu.
The select language menu will appear next to the repository button in the navbar when you set multiple locales in your site config.
Type: string
Details:
Specify the aria-label
attribute of the select language menu.
This is mainly for a11y purpose.
Type: string
Details:
Specify the name of the language of a locale.
This option will only take effect inside the locales of your theme config. It will be used as the language name of the locale, which will be displayed in the select language menu.
Example:
export default {
+ locales: {
+ '/': {
+ lang: 'en-US',
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ },
+ },
+ theme: defaultTheme({
+ locales: {
+ '/': {
+ selectLanguageName: 'English',
+ },
+ '/zh/': {
+ selectLanguageName: '简体中文',
+ },
+ },
+ }),
+}
+
Type: null | string
Details:
aria-label
value for main navigation in navbar.
Type: null | string
Details:
aria-label
value for next/previous page navigation.
Type: string
Default: 'Edit this page'
Details:
Specify the text of the edit this page link.
Type: string
Default: 'Last Updated'
Details:
Specify the text of the last updated timestamp label.
Type: string
Default: 'Contributors'
Details:
Specify the text of the contributors list label.
Type: string
Default: 'TIP'
Details:
Specify the default title of the tip custom containers.
Type: string
Default: 'WARNING'
Details:
Specify the default title of the warning custom containers.
Type: string
Default: 'DANGER'
Details:
Specify the default title of the danger custom containers.
Type: string[]
Default: ['Not Found']
Details:
Specify the messages of the 404 page.
The message will be randomly picked from the array when users enter the 404 page.
Type: string
Default: 'Back to home'
Details:
Specify the text of the back to home link in the 404 page.
Type: string
Default: 'open in new window'
Details:
Specify the sr-only
text of the ExternalLinkIcon.
This is mainly for a11y purpose.
Also see:
Type: string
Default: 'toggle color mode'
Details:
Title text for the color mode toggle button.
This is mainly for a11y purpose.
Also see:
Type: string
Default: 'toggle sidebar'
Details:
Title text for sidebar toggle button.
This is mainly for a11y purpose.
Usage:
::: <type> [title]
+[content]
+:::
+
The type
is required, and the title
and content
are optional.
Supported type
:
tip
warning
danger
details
code-group
code-group-item
Example 1 (default title):
Input
::: tip
+This is a tip
+:::
+
+::: warning
+This is a warning
+:::
+
+::: danger
+This is a dangerous warning
+:::
+
+::: details
+This is a details block
+:::
+
Output
TIP
This is a tip
WARNING
This is a warning
DANGER
This is a dangerous warning
This is a details block
Input
::: danger STOP
+Danger zone, do not proceed
+:::
+
+::: details Click me to view the code
+
+```ts
+console.log('Hello, VuePress!')
+```
+
+:::
+
Output
STOP
Danger zone, do not proceed
console.log('Hello, VuePress!')
+
Input
:::: code-group
+::: code-group-item FOO
+
+```ts
+const foo = 'foo'
+```
+
+:::
+
+::: code-group-item BAR
+
+```ts
+const bar = 'bar'
+```
+
+:::
+::::
+
Output
const foo = 'foo'
+
const bar = 'bar'
+
You can configure the plugins that used by default theme with themePlugins
.
Default theme is using some plugins by default. You can disable a plugin if you really do not want to use it. Make sure you understand what the plugin is for before disabling it.
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ themePlugins: {
+ // customize theme plugins here
+ },
+ }),
+}
+
Type: boolean
Default: true
Details:
Enable @vuepress/plugin-active-header-links or not.
Type: BackToTopPluginOptions | boolean
Default: true
Details:
Enable @vuepress/plugin-back-to-top or not.
Object value is supported as plugin options.
Type: Record<ContainerType, boolean>
Details:
Enable custom containers that powered by @vuepress/plugin-container or not.
ContainerType
type is:
tip
warning
danger
details
codeGroup
codeGroupItem
Also see:
Type: boolean
Default: true
Details:
Enable @vuepress/plugin-external-link-icon or not.
Type: CopyCodePluginOptions | boolean
Default: true
Details:
Enable @vuepress/plugin-copy-code or not.
Object value is supported as plugin options.
Type: boolean
Default: true
Details:
Enable @vuepress/plugin-git or not.
Type: boolean
Default: true
Details:
Enable @vuepress/plugin-medium-zoom or not.
Type: boolean
Default: true
Details:
Enable @vuepress/plugin-nprogress or not.
Type: SeoPluginOptions | boolean
Default: true
Details:
Enable @vuepress/plugin-seo or not.
Object value is supported as plugin options.
Type: SitemapPluginOptions | boolean
Default: true
Details:
Enable @vuepress/plugin-sitemap or not.
Object value is supported as plugin options.
The default theme uses SASS as the CSS pre-processor.
Users can customize style variables via a palette file, and add extra styles via a style file.
The path of the palette file is .vuepress/styles/palette.scss
.
You can make use of it to override predefined SASS variables of the default theme.
// responsive breakpoints
+$MQNarrow: 959px !default;
+$MQMobile: 719px !default;
+$MQMobileNarrow: 419px !default;
+
The path of the style file is .vuepress/styles/index.scss
.
You can add extra styles here, or override the default styles:
:root {
+ scroll-behavior: smooth;
+}
+
You can also make use of it to override predefined CSS variables of the default theme.
:root {
+ // brand colors
+ --c-brand: #3eaf7c;
+ --c-brand-light: #4abf8a;
+
+ // background colors
+ --c-bg: #ffffff;
+ --c-bg-light: #f3f4f5;
+ --c-bg-lighter: #eeeeee;
+ --c-bg-dark: #ebebec;
+ --c-bg-darker: #e6e6e6;
+ --c-bg-navbar: var(--c-bg);
+ --c-bg-sidebar: var(--c-bg);
+ --c-bg-arrow: #cccccc;
+
+ // text colors
+ --c-text: #2c3e50;
+ --c-text-accent: var(--c-brand);
+ --c-text-light: #3a5169;
+ --c-text-lighter: #4e6e8e;
+ --c-text-lightest: #6a8bad;
+ --c-text-quote: #999999;
+
+ // border colors
+ --c-border: #eaecef;
+ --c-border-dark: #dfe2e5;
+
+ // custom container colors
+ --c-tip: #42b983;
+ --c-tip-bg: var(--c-bg-light);
+ --c-tip-title: var(--c-text);
+ --c-tip-text: var(--c-text);
+ --c-tip-text-accent: var(--c-text-accent);
+ --c-warning: #ffc310;
+ --c-warning-bg: #fffae3;
+ --c-warning-bg-light: #fff3ba;
+ --c-warning-bg-lighter: #fff0b0;
+ --c-warning-border-dark: #f7dc91;
+ --c-warning-details-bg: #fff5ca;
+ --c-warning-title: #f1b300;
+ --c-warning-text: #746000;
+ --c-warning-text-accent: #edb100;
+ --c-warning-text-light: #c1971c;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #f11e37;
+ --c-danger-bg: #ffe0e0;
+ --c-danger-bg-light: #ffcfde;
+ --c-danger-bg-lighter: #ffc9c9;
+ --c-danger-border-dark: #f1abab;
+ --c-danger-details-bg: #ffd4d4;
+ --c-danger-title: #ed1e2c;
+ --c-danger-text: #660000;
+ --c-danger-text-accent: #bd1a1a;
+ --c-danger-text-light: #b5474d;
+ --c-danger-text-quote: #c15b5b;
+ --c-details-bg: #eeeeee;
+
+ // badge component colors
+ --c-badge-tip: var(--c-tip);
+ --c-badge-warning: #ecc808;
+ --c-badge-warning-text: var(--c-bg);
+ --c-badge-danger: #dc2626;
+ --c-badge-danger-text: var(--c-bg);
+
+ // code group colors
+ --c-code-group-tab-title: rgba(255, 255, 255, 0.9);
+ --c-code-group-tab-bg: var(--code-bg-color);
+ --c-code-group-tab-outline: var(var(--c-code-group-tab-title));
+ --c-code-group-tab-active-border: var(--c-brand);
+
+ // transition vars
+ --t-color: 0.3s ease;
+ --t-transform: 0.3s ease;
+
+ // code blocks vars
+ --code-bg-color: #282c34;
+ --code-hl-bg-color: rgba(0, 0, 0, 0.66);
+ --code-ln-color: #9e9e9e;
+ --code-ln-wrapper-width: 3.5rem;
+
+ // font vars
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
+ Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+
+ // layout vars
+ --navbar-height: 3.6rem;
+ --navbar-padding-v: 0.7rem;
+ --navbar-padding-h: 1.5rem;
+ --sidebar-width: 20rem;
+ --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
+ --content-width: 740px;
+ --homepage-width: 960px;
+}
+
+// plugin-back-to-top
+.back-to-top {
+ --back-to-top-color: var(--c-brand);
+ --back-to-top-color-hover: var(--c-brand-light);
+ --back-to-top-bg-color: var(--c-bg);
+}
+
+// plugin-docsearch
+.DocSearch {
+ --docsearch-primary-color: var(--c-brand);
+ --docsearch-text-color: var(--c-text);
+ --docsearch-highlight-color: var(--c-brand);
+ --docsearch-muted-color: var(--c-text-quote);
+ --docsearch-container-background: rgba(9, 10, 17, 0.8);
+ --docsearch-modal-background: var(--c-bg-light);
+ --docsearch-searchbox-background: var(--c-bg-lighter);
+ --docsearch-searchbox-focus-background: var(--c-bg);
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
+ --docsearch-hit-color: var(--c-text-light);
+ --docsearch-hit-active-color: var(--c-bg);
+ --docsearch-hit-background: var(--c-bg);
+ --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
+ --docsearch-footer-background: var(--c-bg);
+}
+
+// plugin-external-link-icon
+.external-link-icon {
+ --external-link-icon-color: var(--c-text-quote);
+}
+
+// plugin-medium-zoom
+.medium-zoom-overlay {
+ --medium-zoom-bg-color: var(--c-bg);
+}
+
+// plugin-nprogress
+#nprogress {
+ --nprogress-color: var(--c-brand);
+}
+
+// plugin-pwa-popup
+.pwa-popup {
+ --pwa-popup-text-color: var(--c-text);
+ --pwa-popup-bg-color: var(--c-bg);
+ --pwa-popup-border-color: var(--c-brand);
+ --pwa-popup-shadow: 0 4px 16px var(--c-brand);
+ --pwa-popup-btn-text-color: var(--c-bg);
+ --pwa-popup-btn-bg-color: var(--c-brand);
+ --pwa-popup-btn-hover-bg-color: var(--c-brand-light);
+}
+
+// plugin-search
+.search-box {
+ --search-bg-color: var(--c-bg);
+ --search-accent-color: var(--c-brand);
+ --search-text-color: var(--c-text);
+ --search-border-color: var(--c-border);
+
+ --search-item-text-color: var(--c-text-lighter);
+ --search-item-focus-bg-color: var(--c-bg-light);
+}
+
html.dark {
+ // brand colors
+ --c-brand: #3aa675;
+ --c-brand-light: #349469;
+
+ // background colors
+ --c-bg: #22272e;
+ --c-bg-light: #2b313a;
+ --c-bg-lighter: #262c34;
+ --c-bg-dark: #343b44;
+ --c-bg-darker: #37404c;
+
+ // text colors
+ --c-text: #adbac7;
+ --c-text-light: #96a7b7;
+ --c-text-lighter: #8b9eb0;
+ --c-text-lightest: #8094a8;
+
+ // border colors
+ --c-border: #3e4c5a;
+ --c-border-dark: #34404c;
+
+ // custom container colors
+ --c-tip: #318a62;
+ --c-warning: #e0ad15;
+ --c-warning-bg: #2d2f2d;
+ --c-warning-bg-light: #423e2a;
+ --c-warning-bg-lighter: #44442f;
+ --c-warning-border-dark: #957c35;
+ --c-warning-details-bg: #39392d;
+ --c-warning-title: #fdca31;
+ --c-warning-text: #d8d96d;
+ --c-warning-text-accent: #ffbf00;
+ --c-warning-text-light: #ddb84b;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #fc1e38;
+ --c-danger-bg: #39232c;
+ --c-danger-bg-light: #4b2b35;
+ --c-danger-bg-lighter: #553040;
+ --c-danger-border-dark: #a25151;
+ --c-danger-details-bg: #482936;
+ --c-danger-title: #fc2d3b;
+ --c-danger-text: #ea9ca0;
+ --c-danger-text-accent: #fd3636;
+ --c-danger-text-light: #d9777c;
+ --c-danger-text-quote: #d56b6b;
+ --c-details-bg: #323843;
+
+ // badge component colors
+ --c-badge-warning: var(--c-warning);
+ --c-badge-warning-text: #3c2e05;
+ --c-badge-danger: var(--c-danger);
+ --c-badge-danger-text: #401416;
+
+ // code blocks vars
+ --code-hl-bg-color: #363b46;
+}
+
+// plugin-docsearch
+html.dark .DocSearch {
+ --docsearch-logo-color: var(--c-text);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
+ --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
+ 0 2px 2px 0 rgba(3, 4, 9, 0.3);
+ --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
+ --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
+ 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
+}
+
该插件会监听页面滚动事件。当页面滚动至某个 标题锚点 后,如果存在对应的 标题链接 ,那么该插件会将路由 Hash 更改为该 标题锚点 。
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
npm i -D @vuepress/plugin-active-header-links@next
+
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
+
+export default {
+ plugins: [
+ activeHeaderLinksPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: string
默认值: 'a.sidebar-item'
详情:
标题链接 的选择器。
如果一个 标题锚点 没有对应的 标题链接 ,那么即使滚动到这个 标题锚点 ,该插件也不会更改路由 Hash 。
类型: string
默认值: '.header-anchor'
详情:
标题锚点 的选择器。
你通常不需要设置该选项,除非你通过 markdown.anchor 修改了 markdown-it-anchor 的 permalinkClass
选项。
参考:
类型: number
默认值: 200
详情:
滚动事件监听器的 Debounce 延迟。
类型: number
默认值: 5
详情:
即便直接点击 标题锚点 的链接, scrollTop
也可能不会完全等于 标题锚点 的 offsetTop
,所以我们添加一个 Offset 偏移量来避免这个误差。
该插件会给你的站点添加一个 返回顶部 按钮。当页面向下滚动时,该按钮会显示在页面的右下角,点击它就会滚动到页面顶部。
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-back-to-top@next
+
import { backToTopPlugin } from '@vuepress/plugin-back-to-top'
+
+export default {
+ plugins: [backToTopPlugin()],
+}
+
数字
100
布尔值
true
你可以通过 CSS 变量来自定义 返回顶部 按钮的样式:
:root {
+ --back-to-top-z-index: 5;
+ --back-to-top-icon: url("back-to-top.svg");
+ --back-to-top-bg-color: #fff;
+ --back-to-top-color: #3eaf7c;
+ --back-to-top-color-hover: #71cda3;
+ --back-to-top-shadow: rgb(0 0 0 / 20%);
+}
+
为你的 VuePress 站点注册自定义容器。
该插件简化了 markdown-it-container 的使用方法,但同时也保留了其原本的能力。
默认主题的 自定义容器 就是由该插件支持的。
npm i -D @vuepress/plugin-container@next
+
import { containerPlugin } from '@vuepress/plugin-container'
+
+export default {
+ plugins: [
+ containerPlugin({
+ // 配置项
+ }),
+ ],
+}
+
::: <type> [info]
+[content]
+:::
+
type
是必需的,应通过 type 配置项来指定。info
是可选的,其默认值可以通过 locales 的 defaultInfo
配置项来指定。content
可是任何合法的 Markdown 内容。提示
该插件可以被多次使用,以便支持不同类型的容器。
类型: string
详情:
容器的类型。
它将会被用作 markdown-it-container 的 name
参数。
类型: Record<string, { defaultInfo: string }>
详情:
容器在不同 locales 下的默认 info
。
如果没有指定该配置项,默认 info
会使用大写的 type 。
示例:
export default {
+ plugins: [
+ containerPlugin({
+ type: 'tip',
+ locales: {
+ '/': {
+ defaultInfo: 'TIP',
+ },
+ '/zh/': {
+ defaultInfo: '提示',
+ },
+ },
+ }),
+ ],
+}
+
类型: (info: string) => string
默认值:
(info: string): string =>
+ `<div class="custom-container ${type}">${info ? `<p class="custom-container-title">${info}</p>` : ''}\n`
+
类型: (info: string) => string
默认值:
(): string => '</div>\n'
+
type MarkdownItContainerRenderFunction = (
+ tokens: Token[],
+ index: number,
+ options: any,
+ env: MarkdownEnv,
+ self: Renderer,
+) => string
+
详情:
markdown-it-container 的 render
配置项。
该插件使用了一个默认的 render
函数。但如果你指定了该配置项,那么默认的 render
函数就会被替换掉,此时 locales 、 before 和 after 配置项都会被忽略。
类型: (params: string) => boolean
详情:
markdown-it-container 的 validate
配置项。
类型: string
详情:
markdown-it-container 的 marker
配置项。
此插件会自动在 PC 设备上为每个代码块右上角添加复制按钮。
默认选择器匹配 @vuepress/theme-default
,所以在你自己的主题中集成时可能需要调整它。
npm i -D @vuepress/plugin-copy-code@next
+
import { copyCodePlugin } from '@vuepress/plugin-copy-code'
+
+export default {
+ plugins: [
+ copyCodePlugin({
+ // options
+ }),
+ ],
+}
+
类型:string | string[]
默认值:'.theme-default-content div[class*="language-"] pre'
详情:
代码块选择器
类型:boolean
默认值:false
详情:
是否展示在移动端
类型:number
默认值:2000
详情:
提示消息显示时间,设置为 0
会禁用提示。
类型:number
默认值:800
详情:
注册复制按钮的延时,单位 ms。
如果你使用的主题有切换动画,建议配置此选项为 切换动画时长 + 200
类型:CopyCodeLocaleConfig
interface CopyCodeLocaleData {
+ /**
+ * 复制文字
+ */
+ copy: string
+
+ /**
+ * 已复制文字
+ */
+ copied: string
+}
+
+interface CopyCodeLocaleConfig {
+ [localePath: string]: CopyCodeLocaleData
+}
+
必填:否
详情:
复制按钮插件的国际化配置。
示例:
import { copyCodePlugin } from 'vuepress-plugin-copy-code2'
+
+export default {
+ locales: {
+ '/': {
+ // 这是一个支持的语言
+ lang: 'zh-CN',
+ },
+ '/xx/': {
+ // 这是一个没有收到插件支持的语言
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyCodePlugin({
+ locales: {
+ '/': {
+ // 覆盖复制按钮标签文字
+ copy: '复制此段代码',
+ },
+
+ '/xx/': {
+ // 在这里完整设置 `mm-NN` 的多语言配置
+ },
+ },
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义复制按钮的样式:
:root {
+ --code-copy-icon: url("copy-button.svg");
+ --code-copied-icon: url("copied-button.svg");
+ --copy-code-color: var(--code-ln-color, #9e9e9e);
+ --copy-code-hover: var(--code-hl-bg-color, rgb(0 0 0 / 66%));
+}
+
此插件可以在访问者从你的站点复制内容时,自动追加版权信息,也可以禁止站点的复制或者选择。
npm i -D @vuepress/plugin-copyright@next
+
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ plugins: [
+ copyrightPlugin({
+ // options
+ }),
+ ],
+}
+
此插件默认全局禁用。你可以:
copy: true
手动开启。global: true
让其全局生效,并在页面的 frontmatter 中设置 copy: false
禁用它。处于不打扰用户的考虑,默认配置下仅当复制长度超过 100 时才会追加版权信息。如果你希望改变这个触发值,你可以插件选项中设置 triggerLength
,或在页面 frontmatter 单独设置 copy.triggerLength
。
你可以通过插件的 author
和 license
选项设置全局作者和协议信息。
如果文档的不同部分拥有不同的作者和协议,你可以通过 authorGetter
和 licenseGetter
传入一个使用当前页面对象作为参数的函数 (page: Page) => string
并通过它返回相应信息。
插件会默认通过模板从作者、协议和页面链接生成版权信息,并在复制时追加。如果你认为这不够灵活,你可以设置 copyrightGetter
返回一个完全由你自定义的版权信息,或返回 null 以使用默认模板。
如果你希望禁止用户复制较长内容,你可以在插件选项中设置 maxLength
控制这个临界值,或在页面 frontmatter 单独设置 copy.maxLength
。
disableCopy
或在页面 frontmatter 中设置 copy.disableCopy
来禁用复制,后者具有更高优先级。disableSelection
或在页面 frontmatter 中设置 copy.disableSelection
来禁用文字选择。此选项具有更高优先级string
string
(page: Page) => string | null
(page: Page) => string | null
(page: Page) => string | null
number
100
number
0
0
意味着无限制。boolean
false
boolean
false
boolean
false
类型:string
详情:
首选部署位置。
例子
如果你在 https://myblog.com
和 https://blog.com/username/
下部署相同的内容,你可能希望选择一个站点作为首选链接。
canonical
设置为 https://myblog.com
canonical
设置为 https://blog.com/username/
这样,在另一个站点触发的版权信息也会指向你的首选站点。
类型:CopyrightLocaleConfig
interface CopyrightLocaleData {
+ /**
+ * 作者文字
+ *
+ * @description `:author` 将会被作者替换
+ */
+ author: string
+
+ /**
+ * 协议文字
+ *
+ * @description `:license` 会被当前协议替换
+ */
+ license: string
+
+ /**
+ * 链接文字
+ *
+ * @description `:link` 会替换为当前页面链接
+ */
+ link: string
+}
+
+interface CopyrightLocaleConfig {
+ [localePath: string]: CopyrightLocaleData
+}
+
详情:版权插件的国际化配置。
示例:
import { copyrightPlugin } from '@vuepress/plugin-copyright'
+
+export default {
+ locales: {
+ '/': {
+ // this is a supported language
+ lang: 'en-US',
+ },
+ '/xx/': {
+ // the plugin does not support this language
+ lang: 'mm-NN',
+ },
+ },
+
+ plugins: [
+ copyrightPlugin({
+ locales: {
+ '/': {
+ // Override link text
+ link: 'Original posted at :link',
+ },
+
+ '/xx/': {
+ // Complete locale config for `mm-NN` language here
+ },
+ },
+ }),
+ ],
+}
+
number
100
number
0
0
意味着无限制。boolean
false
boolean
false
将 Algolia DocSearch 集成到 VuePress 中,为你的文档网站提供搜索功能。
提示
当你正确配置该插件后,默认主题会把 DocSearch 按钮添加到导航栏。
该插件不一定能在其他主题中直接使用,因此你应参考主题本身的文档来获取更多信息。
npm i -D @vuepress/plugin-docsearch@next
+
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
+
+export default {
+ plugins: [
+ docsearchPlugin({
+ // 配置项
+ }),
+ ],
+}
+
你需要 提交你的网站 URL 来加入 DocSearch 项目。当你的索引成功创建后, DocSearch 团队会将 apiKey 和 indexName 发送到你的邮箱。接下来,你就可以配置该插件,在 VuePress 中启用 DocSearch 了。
或者,你也可以 运行你自己的爬虫 来创建索引,然后使用你自己的 appId, apiKey 和 indexName 来配置该插件。
new Crawler({
+ appId: 'YOUR_APP_ID',
+ apiKey: 'YOUR_API_KEY',
+ rateLimit: 8,
+ startUrls: [
+ // 这是 Algolia 开始抓取网站的初始地址
+ // 如果你的网站被分为数个独立部分,你可能需要在此设置多个入口链接
+ 'https://YOUR_WEBSITE_URL/',
+ ],
+ sitemaps: [
+ // 如果你在使用 Sitemap 插件 (如: @vuepress-plugin/sitemap),你可以提供 Sitemap 链接
+ 'https://YOUR_WEBSITE_URL/sitemap.xml',
+ ],
+ ignoreCanonicalTo: false,
+ exclusionPatterns: [
+ // 你可以通过它阻止 Algolia 抓取某些 URL
+ ],
+ discoveryPatterns: [
+ // 这是 Algolia 抓取 URL 的范围
+ 'https://YOUR_WEBSITE_URL/**',
+ ],
+ // 爬虫执行的计划时间,可根据文档更新频率设置
+ schedule: 'at 02:00 every 1 day',
+ actions: [
+ // 你可以拥有多个 action,特别是你在一个域名下部署多个文档时
+ {
+ // 使用适当的名称为索引命名
+ indexName: 'YOUR_INDEX_NAME',
+ // 索引生效的路径
+ pathsToMatch: ['https://YOUR_WEBSITE_URL/**'],
+ // 控制 Algolia 如何抓取你的站点
+ recordExtractor: ({ $, helpers }) => {
+ // @vuepress/theme-default 的选项
+ return helpers.docsearch({
+ recordProps: {
+ lvl0: {
+ selectors: '.sidebar-heading.active',
+ defaultValue: 'Documentation',
+ },
+ lvl1: '.theme-default-content h1',
+ lvl2: '.theme-default-content h2',
+ lvl3: '.theme-default-content h3',
+ lvl4: '.theme-default-content h4',
+ lvl5: '.theme-default-content h5',
+ lvl6: '.theme-default-content h6',
+ content: '.theme-default-content p, .theme-default-content li',
+ },
+ indexHeadings: true,
+ })
+ },
+ },
+ ],
+ initialIndexSettings: {
+ // 控制索引如何被初始化,这仅当索引尚未生成时有效
+ // 你可能需要在修改后手动删除并重新生成新的索引
+ YOUR_INDEX_NAME: {
+ attributesForFaceting: ['type', 'lang'],
+ attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
+ 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',
+ },
+ },
+})
+
上述 recordProps
是用于默认主题的配置,你可以根据你使用的主题来修改它们。
注意 initialIndexSettings.YOUR_INDEX_NAME.attributesForFaceting
字段必须包含 'lang'
,否则该插件将无法正常工作。
提示
如果你使用的不是默认主题,或者在使用 Docsearch 的时候遇到了任何问题,你也可以检查上述的爬虫配置示例,然后前往 Algolia Crawler 仓库,在你项目侧边栏中的 Editor 页面中修改你的配置。
类型: string
是否必需: true
详情:
从 DocSearch 团队收到的 apiKey
,或者由你自己生成。
参考:
类型: string
是否必需: true
详情:
从 DocSearch 团队收到的 indexName
,或者由你自己生成。
参考:
类型: string
是否必需: true
详情:
用于设置你的 Application ID。
参考:
类型: SearchParameters
详情:
Algolia 搜索 API 参数。
参考:
类型: string
默认值: 'Search docs'
详情:
搜索输入框的 placeholder 属性。
参考:
类型: boolean
默认值: false
详情:
是否禁用所有的个性化功能:最近的搜索、收藏的搜索结果等。
参考:
类型: string
详情:
打开弹窗时的初始请求。
参考:
类型: Partial<DocSearchTranslations>
详情:
允许替换 DocSearch 按钮和弹窗内的默认文字。
参考:
类型: Record<string, DocsearchPluginOptions>
详情:
在不同 locales 下对该插件进行不同的配置。
该插件的所有其他选项都可以在 locale 中进行配置。
示例:
export default {
+ plugins: [
+ docsearchPlugin({
+ appId: '<APP_ID>',
+ apiKey: '<API_KEY>',
+ indexName: '<INDEX_NAME>',
+ locales: {
+ '/': {
+ placeholder: 'Search Documentation',
+ translations: {
+ button: {
+ buttonText: 'Search Documentation',
+ },
+ },
+ },
+ '/zh/': {
+ placeholder: '搜索文档',
+ translations: {
+ button: {
+ buttonText: '搜索文档',
+ },
+ },
+ },
+ },
+ }),
+ ],
+}
+
类型: string
默认值: base
详情:
搜索索引基础路径。
如果你需要把你的站点部署到不同的域名上,你不需要把它们全都提交到 Docsearch 上来分别生成搜索索引。你可以选择其中一个域名作为 索引域名 ,并且仅将 索引域名 提交到 DocSearch 上来爬去搜索索引。然后,你就可以在不同的部署域名下复用索引。
如果你不同部署域名下的 base 是不一样的,你就需要将这个配置设置成 索引域名 的 base ,这样其他的部署域名就可以正确复用索引了。
类型: boolean
默认值: true
详情:
是否注入 DocSearch 的默认样式。
如果你认为 DocSearch 的默认样式和你的站点不兼容,你可以尝试覆盖默认样式,或者将该选项设置为 false
来完全移除默认样式。
当该选项被禁用时,你需要为 DocSearch 引入你自己的样式。同时要注意,你也无法再使用 样式 章节中提到的样式自定义能力。
你可以通过 @docsearch/css 提供的 CSS 变量来自定义样式:
:root {
+ --docsearch-primary-color: rgb(84, 104, 255);
+ --docsearch-text-color: rgb(28, 30, 33);
+ --docsearch-spacing: 12px;
+ --docsearch-icon-stroke-width: 1.4;
+ --docsearch-highlight-color: var(--docsearch-primary-color);
+ --docsearch-muted-color: rgb(150, 159, 175);
+ --docsearch-container-background: rgba(101, 108, 133, 0.8);
+ --docsearch-logo-color: rgba(84, 104, 255);
+
+ /* modal */
+ --docsearch-modal-width: 560px;
+ --docsearch-modal-height: 600px;
+ --docsearch-modal-background: rgb(245, 246, 247);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 rgba(255, 255, 255, 0.5), 0 3px
+ 8px 0 rgba(85, 90, 100, 1);
+
+ /* searchbox */
+ --docsearch-searchbox-height: 56px;
+ --docsearch-searchbox-background: rgb(235, 237, 240);
+ --docsearch-searchbox-focus-background: #fff;
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--docsearch-primary-color);
+
+ /* hit */
+ --docsearch-hit-height: 56px;
+ --docsearch-hit-color: rgb(68, 73, 80);
+ --docsearch-hit-active-color: #fff;
+ --docsearch-hit-background: #fff;
+ --docsearch-hit-shadow: 0 1px 3px 0 rgb(212, 217, 225);
+
+ /* key */
+ --docsearch-key-gradient: linear-gradient(
+ -225deg,
+ rgb(213, 219, 228) 0%,
+ rgb(248, 248, 248) 100%
+ );
+ --docsearch-key-shadow: inset 0 -2px 0 0 rgb(205, 205, 230), inset 0 0 1px 1px
+ #fff, 0 1px 2px 1px rgba(30, 35, 90, 0.4);
+
+ /* footer */
+ --docsearch-footer-height: 44px;
+ --docsearch-footer-background: #fff;
+ --docsearch-footer-shadow: 0 -1px 0 0 rgb(224, 227, 232), 0 -3px 6px 0 rgba(69, 98, 155, 0.12);
+}
+
详情:
该插件会全局注册一个 <Docsearch />
组件,你可以不传入任何 Props 来使用它。
将该组件放置在你想要显示 docsearch 按钮的地方。例如,默认主题将这个组件放在了导航栏的末尾。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
该插件会为你 Markdown 内容中的外部链接添加一个图标,即
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-external-link-icon@next
+
import { externalLinkIconPlugin } from '@vuepress/plugin-external-link-icon'
+
+export default {
+ plugins: [
+ externalLinkIconPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, { openInNewWindow: string }>
详情:
外部链接图标在不同 locales 下的 A11y 文字。
如果没有指定该配置项,它会降级使用默认文字。
示例:
export default {
+ plugins: [
+ externalLinkIconPlugin({
+ locales: {
+ '/': {
+ openInNewWindow: 'open in new window',
+ },
+ '/zh/': {
+ openInNewWindow: '在新窗口打开',
+ },
+ },
+ }),
+ ],
+}
+
类型: boolean
详情:
是否在当前页面的外部链接的后面添加外部链接图标。
你可以通过 CSS 变量来自定义外部链接图标的样式:
:root {
+ --external-link-icon-color: #aaa;
+}
+
详情:
该插件会全局注册一个 <ExternalLinkIcon />
组件,你可以不传入任何 Props 来使用它。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
channel
插件选项用于配置 feed 的频道。
string
SiteConfig.title
频道的标题
string
options.hostname
和 context.base
生成)频道地址
string
SiteConfig.description
频道描述信息
string
siteConfig.locales['/'].locales
"en-US"
频道使用的语言
string
author.name
生成 Copyright by $author
频道版权信息
string
(需是合法的 Date ISOString)频道内容的发布时间
string
(需是合法的 Date ISOString)频道内容的上次更新时间
number
内容有效时间,即获取后保持缓存而不进行新获取的时间
string
这是一个会在频道中使用的图片,建议设置正方形图片、尺寸最好不小于 512×512。
string
一个代表频道的图标,建议设置正方形图片、尺寸最好不小于 128×128,背景色透明。
FeedAuthor
频道的作者。
interface FeedAuthor {
+ /** 作者姓名 */
+ name: string
+ /** 作者电子邮箱 */
+ email?: string
+ /** 作者网站 */
+ url?: string
+ /**
+ * 作者头像地址
+ *
+ * 正方形,最好不小于 128×128,透明背景
+ */
+ avatar?: string
+}
+
string
Websub 的链接。Websub 需要服务器后端,与 VuePress 主旨不符,如无特殊需要忽略即可。
WebSub
有关信息,详见 Websub。
string
部署网站的域名。
boolean
false
是否启用 Atom 格式输出。
boolean
false
是否启用 JSON 格式输出。
boolean
false
是否启用 RSS 格式输出。
string
一个大的图片,用作 feed 展示。
string
一个小的图标,显示在订阅列表中。
number
100
设置 feed 的最大项目数量。在所有页面排序好后,插件会截取前 count 个项目。
如果你的站点文章很多,你应该考虑设置这个选项以减少 feed 文件大小。
(RegExp | string)[] | (tagName:string) => boolean
应在 Feed 中保留的自定义元素或组件。
默认情况下,所有未知标签均会被移除。
类型:(page: Page)=> boolean
默认值:
;({ frontmatter, filePathRelative }: Page): boolean =>
+ !(
+ frontmatter.home ||
+ !filePathRelative ||
+ frontmatter.article === false ||
+ frontmatter.feed === false
+ )
+
自定义的过滤函数,用于过滤哪些项目在 feed 中显示。
类型: (pageA: Page, pageB: Page)=> number
默认值:
// dateSorter 来源于 @vuepress/helper
+;(pageA, pageB): number =>
+ dateSorter(
+ pageA.data.git?.createdTime
+ ? new Date(pageA.data.git?.createdTime)
+ : pageA.frontmatter.date,
+ pageB.data.git?.createdTime
+ ? new Date(pageB.data.git?.createdTime)
+ : pageB.frontmatter.date,
+ )
+
Feed 项目的排序器。
默认的排序行为是通过 Git 的文件添加日期 (需要 @vuepress/plugin-git
)。
提示
你应该启用 @vuepress/plugin-git
来获取最新创建的页面作为 feed 项目。否则,feed 项目将按照 VuePress 中页面的默认顺序排序。
channel
选项用于配置 Feed 频道。
可用选项详见 配置 → 频道设置
boolean
false
是否在开发服务器中启用
提示
由于性能原因,我们不提供热更新。重启开发服务器以同步你的变更。
string
"http://localhost:${port}"
开发服务器使用的主机名
string
"atom.xml"
Atom 格式输出路径,相对于输出路径。
string
@vuepress/plugin-feed/templates/atom.xsl
的内容Atom xsl 模板文件没人陪美国
string
"atom.xsl"
Atom xsl 输出路径,相对于输出路径。
string
"feed.json"
JSON 格式输出路径,相对于输出路径。
string
"rss.xml"
RSS 格式输出路径,相对于输出路径。
string
@vuepress/plugin-feed/templates/rss.xsl
的内容RSS xsl 模板文件内容。
string
"rss.xsl"
RSS xsl 输出路径,相对于输出路径。
Feed 生成控制器,详见 Feed 生成器。
此插件内置了生成器,只有当你想完全控制 feed 生成时才需要设置此选项。
Record<string, BaseFeedOptions>
你可以将它用于每个语言环境的特定选项。
除 hostname
外,上述任何选项均受支持。
你可以通过配置每个页面的 Frontmatter,来对每个 Feed 项目生成进行单独的控制。
默认情况下,所有文章均会被添加至 feed 流。如果你想在 feed 中移除特定页面,你可以在 frontmatter 中设置 feed: false
。
string
由 VuePress 自动生成,默认为页面的 h1 内容
string
页面描述
Date
页面的发布日期
boolean
该页面是否是文章
如果此项设置为
false
,则该页不会包含在最终的 feed 中。
string
页面版权信息
string
页面的封面/分享图,需为完整链接或绝对链接。
string
Feed 项目的标题
string
Feed 项目的描述
string
Feed 项目的内容
FeedAuthor[] | FeedAuthor
Feed 项目的作者
interface FeedAuthor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
FeedContributor[] | FeedContributor
Feed 项目的贡献者
interface FeedContributor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
string
Feed 项目的标识符,用于标识 Feed 项目。
你应该确保每个 Feed 项目有全局唯一的 guid。
你可以通过控制插件选项中的 getter
来完全控制 Feed 项目的生成。
(page: Page) => string
项目标题获取器
(page: Page) => string
项目链接获取器
(page: Page) => string | undefined
项目描述获取器
提示
因为 Atom 在摘要中支持 HTML,所以如果可能的话,你可以在这里返回 HTML 内容,但内容必须以标记 html:
开头。
(page: Page) => string
项目内容获取器
(page: Page) => FeedAuthor[]
项目作者获取器。
获取器应在作者信息缺失时返回空数组。
interface FeedAuthor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => FeedCategory[] | undefined
项目分类获取器。
interface FeedCategory {
+ /**
+ * 分类名称
+ */
+ name: string
+
+ /**
+ * 标识分类法的字符串
+ *
+ * @description rss format only
+ */
+ domain?: string
+
+ /**
+ * URI 标识的分类 scheme
+ *
+ * @description atom format only
+ */
+ scheme?: string
+}
+
(page: Page) => FeedEnclosure | undefined
项目附件获取器。
interface FeedEnclosure {
+ /**
+ * Enclosure 地址
+ */
+ url: string
+
+ /**
+ * 类型
+ *
+ * @description 应为一个标准的 MIME 类型,rss format only
+ */
+ type: string
+
+ /**
+ * 按照字节数计算的大小
+ *
+ * @description rss format only
+ */
+ length?: number
+}
+
(page: Page) => Date | undefined
项目发布日期获取器
(page: Page) => Date
项目最后更新日期获取器
(page: Page) => string
项目图片获取器
确保返回一个完整的 URL。
(page: Page) => FeedContributor[]
项目贡献者获取器
获取器应在贡献者信息缺失时返回空数组。
interface FeedContributor {
+ /**
+ * 作者名字
+ */
+ name?: string
+
+ /**
+ * 作者邮件
+ */
+ email?: string
+
+ /**
+ * 作者网站
+ *
+ * @description json format only
+ */
+ url?: string
+
+ /**
+ * 作者头像
+ *
+ * @description json format only
+ */
+ avatar?: string
+}
+
(page: Page) => string | undefined
项目版权获取器
插件可为你生成以下三种格式的 feed 文件:
请按照需要生成的格式,在插件选项中设置 atom
, json
或 rss
为 true
。
为了正确生成 Feed 链接,你需要在插件选项中设置 hostname
。
当你在浏览器中打开 Feed 文件时,我们会通过 xsl 模板将 atom 和 rss feed xml 魔法般地转换为可读的 html。你可以查看本站的 atom 和 rss feed 作为案例!
如果你想在开发服务器中预览 Feed,你需要在插件选项中设置 devServer: true
。如果你没有使用默认的 http://localhost:{port}
,你还需要设置 devHostname
。
你可以通过设置 channel
选项来自自定义 Feed 频道的各项信息。
我们推荐进行如下设置:
channel.pubDate
中channel.ttl
中设置内容的更新周期(单位: 分钟)channel.copyright
设置版权信息channel.author
设置频道作者。详细的选项及其默认值详见 配置 → 频道设置
默认情况下,所有文章均会被添加至 feed 流。
你可以在 frontmatter 中配置 feed
和其他选项控制每个页面的 Feed 项目内容,详见 Frontmatter 选项 了解它们如何被转换。
你可以通过配置插件选项中的 getter
完全控制 Feed 项目的生成逻辑。 详细的选项及其默认值详见 配置 → Feed 获取器
插件会针对每个语言生成单独的 Feed。
你可以通过插件选项中的 locales
分别对不同语言提供不同的默认设置。
该插件会收集你的页面的 Git 信息,包括创建和更新时间、贡献者等。
默认主题的 lastUpdated 和 contributors 就是由该插件支持的。
该插件主要用于开发主题,大部分情况下你不需要直接使用它。
npm i -D @vuepress/plugin-git@next
+
import { gitPlugin } from '@vuepress/plugin-git'
+
+export default {
+ plugins: [
+ gitPlugin({
+ // 配置项
+ }),
+ ],
+}
+
该插件要求你的项目在 Git 仓库 下,这样它才能从提交历史记录中收集信息。
在构建站点时,你应该确保所有的提交记录是可以获取到的。举例来说, CI 工作流通常会在克隆你的仓库时添加 --depth 1 参数来避免拉取全部的提交记录,因此你需要禁用这个功能,以便该插件在 CI 可以中正常使用。
注意
该插件会显著降低准备数据的速度,特别是在你的页面数量很多的时候。你可以考虑在 dev
模式下禁用该插件来获取更好的开发体验。
类型: boolean
默认值: true
详情:
是否收集页面的创建时间。
类型: boolean
默认值: true
详情:
是否收集页面的更新时间。
类型: boolean
默认值: true
详情:
是否收集页面的贡献者。
类型: string[]
详情:
文件相对路径组成的数组,该数组中的文件会在计算页面数据时被包含在内。
示例:
---
+gitInclude:
+ - relative/path/to/file1
+ - relative/path/to/file2
+---
+
该插件会向页面数据中添加一个 git
字段。
在使用该插件后,可以在页面数据中获取该插件收集到的 Git 信息:
import type { GitPluginPageData } from '@vuepress/plugin-git'
+import { usePageData } from 'vuepress/client'
+
+export default {
+ setup() {
+ const page = usePageData<GitPluginPageData>()
+ console.log(page.value.git)
+ },
+}
+
类型: number
详情:
页面第一次提交的 Unix 毫秒时间戳。
该属性将取当前页面及 gitInclude 中所列文件的第一次提交的时间戳的最小值。
类型: number
详情:
页面最后一次提交的 Unix 毫秒时间戳。
该属性将取当前页面及 gitInclude 中所列文件的最后一次提交的时间戳的最大值。
GitContributor[]
interface GitContributor {
+ name: string
+ email: string
+ commits: number
+}
+
详情:
页面的贡献者信息。
该属性将会包含 gitInclude 所列文件的贡献者。
将 Google Analytics 集成到 VuePress 中。
该插件会通过引入 gtag.js 来启用 Google Analytics 4 。
npm i -D @vuepress/plugin-google-analytics@next
+
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics'
+
+export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
Google Analytics 会 自动收集部分事件 ,比如 page_view
, first_visit
等。
因此,如果你只是想收集站点的一些基础数据,你只需要正确设置 Measurement ID ,不需要再额外做其他事情。
在引入该插件之后,一个全局的 gtag()
函数会被挂载到 window
对象上,你可以使用它进行 自定义事件的上报 。
类型: string
详情:
Google Analytics 4 的 Measurement ID ,应以 'G-'
开头。
你可以通过 这里 的指引来找到你的 Measurement ID 。注意区分 Google Analytics 4 的 Measurement ID (即 "G-" 开头的 ID) 和 Universal Analytics 的 Tracking ID (即 "UA-" 开头的 ID)。
示例:
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ }),
+ ],
+}
+
类型: boolean
详情:
设置为 true
可以向 DebugView 发送事件。了解更多关于 DebugView 的信息 。
示例:
export default {
+ plugins: [
+ googleAnalyticsPlugin({
+ id: 'G-XXXXXXXXXX',
+ debug: true,
+ }),
+ ],
+}
+
将 medium-zoom 集成到 VuePress 中,为图片提供可缩放的功能。
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-medium-zoom@next
+
import { mediumZoomPlugin } from '@vuepress/plugin-medium-zoom'
+
+export default {
+ plugins: [
+ mediumZoomPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: string
默认值: ':not(a) > img'
详情:
可缩放的图片的选择器。
默认情况下,该插件会使 <a>
标签以外的所有图片都支持缩放。
类型: number
默认值: 500
详情:
以毫秒为单位的延迟。
在切换路由进入一个新页面时,该插件会在一定延迟后才使页面内的图片支持缩放。
类型: Object
详情:
medium-zoom 的配置项。
参考:
你可以通过 zoomOptions 对大部分的缩放样式进行自定义,不过作为补充,该插件同样提供了一些 CSS 变量:
:root {
+ --medium-zoom-z-index: 100;
+ --medium-zoom-bg-color: #ffffff;
+ --medium-zoom-opacity: 1;
+}
+
详情:
返回该插件使用的 Zoom
实例,便于你直接使用实例上的 methods 。
该插件会在切换路由进入当前页面时使图片支持缩放。但如果你要动态添加新图片,那么你可能就需要这个方法来让这些新图片也支持缩放。
该插件在 Zoom
实例上额外添加了一个 refresh
方法,它将使用 selector 作为默认参数,先调用 zoom.detach()
再调用 zoom.attach()
,便于你快速刷新当前页面图片的缩放状态。
示例:
import { nextTick } from 'vue'
+import { useMediumZoom } from '@vuepress/plugin-medium-zoom/client'
+
+export default {
+ setup() {
+ const zoom = useMediumZoom()
+
+ // ... 进行了一些操作,在当前页面添加了新的图片
+
+ // 此时你可能需要手动调用 `refresh` 来让这些新图片支持缩放
+ nextTick(() => {
+ zoom.refresh()
+ })
+ },
+}
+
将 nprogress 集成到 VuePress 中,在切换到另一个页面时会展示进度条。
该插件已经集成到默认主题中。
npm i -D @vuepress/plugin-nprogress@next
+
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
+
+export default {
+ plugins: [nprogressPlugin()],
+}
+
你可以通过 CSS 变量来自定义进度条的样式:
:root {
+ --nprogress-color: #29d;
+ --nprogress-z-index: 1031;
+}
+
为你的主题提供调色板功能。
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
对于主题作者,该插件可以帮助你提供用户自定义样式的能力。
npm i -D @vuepress/plugin-palette@next
+
import { palettePlugin } from '@vuepress/plugin-palette'
+
+export default {
+ plugins: [
+ palettePlugin({
+ // 配置项
+ }),
+ ],
+}
+
该插件会提供一个 @vuepress/plugin-palette/palette
(调色板文件)和一个 @vuepress/plugin-palette/style
(样式文件),用于在你的主题样式中引入。
调色板文件用于定义样式变量,因此它一般会在你主题样式的开头引入。举例来说,用户可以在调色板中定义 CSS 变量 、 SASS 变量 、 LESS 变量 或 Stylus 变量 ,然后你可以在你的主题样式中使用这些变量。
样式文件用于覆盖默认样式或添加额外样式,因此它一般会在你主题样式的末尾引入。
在你的主题中使用该插件,假设你使用 SASS 作为 CSS 预处理器:
export default {
+ // ...
+ plugins: [palettePlugin({ preset: 'sass' })],
+}
+
在你主题需要使用对应变量的地方引入该插件的调色板文件,比如在 Layout.vue
中:
<template>
+ <h1 class="palette-title">你好,调色板!</h1>
+</template>
+
+<style lang="scss">
+/* 从该插件的调色板中引入变量 */
+@import '@vuepress/plugin-palette/palette';
+
+/* 设置变量的默认值 */
+$color: red !default;
+
+/* 在你的样式中使用变量 */
+.palette-title {
+ color: $color;
+}
+</style>
+
然后,用户就可以在 .vuepress/styles/palette.scss
中自定义变量:
$color: green;
+
在你主题的样式之后引入该插件的样式文件,比如在 clientConfigFile
中:
// 引入你主题本身的样式文件
+import 'path/to/your/theme/style'
+// 引入该插件的样式文件
+import '@vuepress/plugin-palette/style'
+
然后,用户就可以在 .vuepress/styles/index.scss
中添加额外样式,并可以覆盖你主题本身的样式:
h1 {
+ font-size: 2.5rem;
+}
+
类型: 'css' | 'sass' | 'less' | 'stylus'
默认值: 'css'
详情:
设置其他选项的预设。
如果你没有对该插件进行进阶定制化的需要,建议只设置该配置项并忽略其他选项。
类型: string
默认值:
'.vuepress/styles/palette.css'
'.vuepress/styles/palette.scss'
'.vuepress/styles/palette.less'
'.vuepress/styles/palette.styl'
详情:
用户调色板文件的路径,是针对源文件目录的相对路径。
默认值依赖于 preset 配置项。
该文件用于用户定义样式变量,建议保持默认值作为约定的文件路径。
类型: string
默认值:
'styles/palette.css'
'styles/palette.scss'
'styles/palette.less'
'styles/palette.styl'
详情:
生成的调色板临时文件的路径,是针对临时文件文件目录的相对路径。
默认值依赖于 preset 配置项。
你应该使用 '@vuepress/plugin-palette/palette'
别名来引入调色板文件,因此在绝大多数情况下你不需要修改该配置项。
类型: string
默认值:
'.vuepress/styles/index.css'
'.vuepress/styles/index.scss'
'.vuepress/styles/index.less'
'.vuepress/styles/index.styl'
详情:
用户样式文件的路径,是针对源文件目录的相对路径。
默认值依赖于 preset 配置项。
该文件用于用户覆盖默认样式和添加额外样式,建议保持默认值作为约定的文件路径。
类型: string
默认值:
'styles/index.css'
'styles/index.scss'
'styles/index.less'
'styles/index.styl'
详情:
生成的样式临时文件的路径,是针对临时文件文件目录的相对路径。
默认值依赖于 preset 配置项。
你应该使用 '@vuepress/plugin-palette/style'
别名来引入样式文件,因此在绝大多数情况下你不需要修改该配置项。
类型: (filePath: string) => string
默认值:
(filePath) => `@import '${filePath}';\n`
(filePath) => `@forward 'file:///${filePath}';\n`
(filePath) => `@import '${filePath}';\n`
(filePath) => `@require '${filePath}';\n`
详情:
用于生成引入代码的函数。
默认值依赖于 preset 配置项。
该配置项用于生成 tempPaletteFile 和 tempStyleFile ,在绝大多数情况下你不需要修改该配置项。
该插件使用 Prism.js 来为 Markdown 代码块启用代码高亮。
该插件已经集成到默认主题中。
需要注意的是,该插件仅会给代码块添加 HTML 标记,而不会添加样式。当你在一个自定义主题中使用它时,可能需要自己选择并引入 Prism.js 样式主题。
npm i -D @vuepress/plugin-prismjs@next
+
import { prismjsPlugin } from '@vuepress/plugin-prismjs'
+
+export default {
+ plugins: [
+ prismjsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: string[]
默认值: ['markdown', 'jsdoc', 'yaml']
详情:
需要预加载的语言。
默认情况下,语言会在解析 Markdown 文件时按需加载。
然而, Prism.js 在动态加载语言时可能会遇到 一些潜在的问题 。为了避免这些问题,你可以使用该配置项来预加载一些语言。
提供一个弹窗组件,允许用户手动刷新 PWA Service Worker 。
该插件必须和 pwa 插件 一起使用,并且 skipWaiting
配置项不能设置为 true
。
当新的 Service Worker 就绪时,会在页面右下角出现一个弹窗,询问用户是否需要激活处于 Waiting 状态的 Service Worker 。
npm i -D @vuepress/plugin-pwa-popup@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+import { pwaPopupPlugin } from '@vuepress/plugin-pwa-popup'
+
+export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, { message: string, buttonText: string }>
详情:
弹窗在不同 locales 下的信息。
如果没有指定该配置项,它会降级使用默认信息。
示例:
export default {
+ plugins: [
+ pwaPlugin(),
+ pwaPopupPlugin({
+ locales: {
+ '/': {
+ message: 'New content is available.',
+ buttonText: 'Refresh',
+ },
+ '/zh/': {
+ message: '发现新内容可用',
+ buttonText: '刷新',
+ },
+ },
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义弹窗的样式:
:root {
+ --pwa-popup-z-index: 10;
+ --pwa-popup-text-color: #2c3e50;
+ --pwa-popup-bg-color: #ffffff;
+ --pwa-popup-border-color: #3eaf7c;
+ --pwa-popup-shadow: 0 4px 16px var(--pwa-popup-border-color);
+ --pwa-popup-btn-text-color: #ffffff;
+ --pwa-popup-btn-bg-color: #3eaf7c;
+ --pwa-popup-btn-hover-bg-color: #4abf8a;
+}
+
使你的 VuePress 站点成为一个 渐进式 Web 应用 (PWA).
该插件使用 workbox-build 来生成 Service Worker 文件,并通过 register-service-worker 来注册 Service Worker 。
注意
如果你启用过该插件,并想要禁用它,你可能需要 `@vuepress/plugin-remove-pwa 来移除现有的 Service Worker 。
npm i -D @vuepress/plugin-pwa@next
+
import { pwaPlugin } from '@vuepress/plugin-pwa'
+
+export default {
+ plugins: [
+ pwaPlugin({
+ // 配置项
+ }),
+ ],
+}
+
为了使你的网站符合 PWA 的要求,你需要创建一个 Web app manifests 文件,并且为你的 PWA 设置图标、颜色等信息。
你需要将你的 Manifest 文件和图标放置在 Public 目录 下。在下述的示例中,我们假设你正在使用默认的 Public 目录 .vuepress/public
。
通常是 .vuepress/public/manifest.webmanifest
:
{
+ "name": "VuePress",
+ "short_name": "VuePress",
+ "description": "Vue-powered Static Site Generator",
+ "start_url": "/index.html",
+ "display": "standalone",
+ "background_color": "#fff",
+ "theme_color": "#3eaf7c",
+ "icons": [
+ {
+ "src": "/images/icons/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/images/icons/android-chrome-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ }
+ ]
+}
+
为了提高你的 PWA 的可用性,你需要生成一些图标,并将它们放置在 Public 目录下。
确保图标的路径匹配 Manifest 文件中的 icons
字段:
.vuepress/public/images/icons/android-chrome-192x192.png
.vuepress/public/images/icons/android-chrome-384x384.png
提示
一些工具可以帮助你做这些事。比如 Favicon Generator 可以帮助你生成图片以及一个 Manifest 文件样例。
你还需要通过 head 配置项来设置一些标签,用来 部署你的 Manifest 文件 。
export default {
+ head: [
+ ['link', { rel: 'manifest', href: '/manifest.webmanifest' }],
+ ['meta', { name: 'theme-color', content: '#3eaf7c' }],
+ // ...其他标签
+ ],
+}
+
该插件的配置项可以接收 workbox-build 中 generateSW 方法 除了 globDirectory
和 swDest
以外的所有参数。
比如,你可以设置 skipWaiting: true
,这将在新的 Service Worker 就绪之后立即激活它:
export default {
+ plugins: [
+ pwaPlugin({
+ skipWaiting: true,
+ }),
+ ],
+}
+
但是如果你不设置 skipWaiting
或设置为 false
,你就需要手动激活新的 Service Worker 。
类型: string
默认值: 'service-worker.js'
详情:
生成的 Service Worker 文件路径,该路径是 dest 目录的相对路径。
Service Worker 文件只会在 build
模式下生成。
详情:
返回该插件的 Event Emitter 。
你可以为 register-service-worker 提供的事件添加事件监听器。
示例:
import { usePwaEvent } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('ready', (registration) => {
+ console.log('Service worker 已经生效。')
+ })
+ },
+}
+
参数 | 类型 | 描述 |
---|---|---|
registration | ServiceWorkerRegistration | 你想要激活的 Service Worker 的 Registration |
详情:
调用 skipWaiting() 来激活处于 Waiting 状态的 Service Worker 。
示例:
import { usePwaEvent, useSkipWaiting } from '@vuepress/plugin-pwa/client'
+
+export default {
+ setup() {
+ const event = usePwaEvent()
+ event.on('updated', (registration) => {
+ console.log('在 Waiting 状态的 Service Worker 已经就绪。')
+ // 激活 Waiting 状态的 Service Worker
+ useSkipWaiting(registration)
+ })
+ },
+}
+
此插件会为每个页面生成字数统计与预计阅读时间。
npm i -D @vuepress/plugin-reading-time@next
+
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default {
+ plugins: [
+ readingTimePlugin({
+ // 配置项
+ }),
+ ],
+}
+
插件会将相关信息注入到页面数据的 readingTime
,其中:
readingTime.minutes
:为预计阅读时间(分钟)number
readingTime.words
:字数统计,number
对于任何页面,你可以从 page.data.readingTime
获取预计阅读时间与字数统计:
page.data.readingTime // { minutes: 3.2, words: 934 }
+
你可以在 extendsPage
以及其他生命周期获取它做进一步处理:
export default {
+ // ...
+ extendsPage: (page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ },
+
+ onInitialized: (app) => {
+ app.pages.map((page) => {
+ page.data.readingTime // { minutes: 3.2, words: 934 }
+ })
+ },
+}
+
你可以从 @vuepress/plugin-reading-time/client
导入 useReadingTimeData
和 useReadingTimeLocale
来获取当前页面的阅读时间数据和语言环境数据:
<script setup lang="ts">
+import {
+ useReadingTimeData,
+ useReadingTimeLocale,
+} from '@vuepress/plugin-reading-time/client'
+
+const readingTimeData = useReadingTimeData() // { minutes: 1.1, words: 100 }
+const readingTimeLocale = useReadingTimeLocale() // { time: "1 分钟", words: "100 字" }
+</script>
+
number
300
类型:ReadingTimeLocaleConfig
interface ReadingTimeLocaleData {
+ /**
+ * 字数模板,模板中 `$word` 会被自动替换为字数
+ */
+ word: string
+
+ /**
+ * 小于一分钟文字
+ */
+ less1Minute: string
+
+ /**
+ * 时间模板
+ */
+ time: string
+}
+
+interface ReadingTimeLocaleConfig {
+ [localePath: string]: ReadingTimeLocaleData
+}
+
必填:否
详情:
阅读时间插件的国际化配置。
你可以从 @vuepress/plugin-reading-time/client
导入并使用这些 API:
即使插件被禁用,这些 API 也不会抛出错误。
interface ReadingTime {
+ /** 分钟为单位的预计阅读时长 */
+ minutes: number
+ /** 内容的字数 */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
当插件被禁用时会返回 null
。
interface ReadingTimeLocale {
+ /** 当前语言的预计阅读时间 */
+ time: string
+ /** 当前语言的字数文字 */
+ words: string
+}
+
+const useReadingTimeLocale: () => ComputedRef<ReadingTimeLocale>
+
由于此插件主要面向插件和主题开发者,所以提供了 "使用 API":
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ useReadingTimePlugin(app, {
+ // 你的选项
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
为什么你应该使用 "使用 API"
当你多次注册一个插件时,vuepress 会给你一个警告,告诉你只有第一个插件会生效。useReadingTimePlugin
会自动检测插件是否已经注册,避免多次注册。
如果你在 extendsPage
生命周期访问阅读时间数据,那么 @vuepress/plugin-reading-time
必须在你的主题或插件之前被调用,否则你会得到未定义的 page.data.readingTime
。useReadingTimePlugin
确保了 @vuepress/plugin-reading-time
在你的主题或插件之前被调用。
我们也提供了一个 removeReadingTimePlugin
api 来移除插件。你可以使用它来确保你的调用生效或清除插件:
import { useReadingTimePlugin } from '@vuepress/plugin-reading-time'
+
+export default (options) => (app) => {
+ // 这会移除任何当前存在的阅读时间插件
+ removeReadingTimePlugin(app)
+
+ // 所以这会生效,即使之前已经注册了一个阅读时间插件
+ useReadingTimePlugin(app, {
+ // 你的选项
+ })
+
+ return {
+ name: 'vuepress-plugin-xxx', // or vuepress-theme-xxx
+ }
+}
+
此插件提供页面与整站重定向功能。
npm i -D @vuepress/plugin-redirect@next
+
import { redirectPlugin } from '@vuepress/plugin-redirect'
+
+export default {
+ plugins: [
+ redirectPlugin({
+ // 配置项
+ }),
+ ],
+}
+
如果你改动了已有页面的地址,你可以在 Frontmatter 中使用 redirectFrom
选项设置重定向到此页面的地址,这样可以保证用户在访问旧链接时重定向到新的地址。
如果你需要将已有的页面重定向到新的页面,可以在 Frontmatter 中使用 redirectTo
选项设置需要重定向到的地址。这样该页面会在访问时重定向到新的地址。
你还可以通过插件选项中的 config
设置一个重定向映射,详见 config。
插件可以根据用户的语言首选项,自动将无多语言链接重定向到用户需要的多语言页面。为了实现这一点,你需要留空默认的语言目录 (/
),并在插件选项中设置 autoLocale: true
。插件会自动根据用户语言跳转到对应的语言页面。
也就是你需要设置以下目录结构:
.
+├── en
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+├── zh
+│ ├── ...
+│ ├── page.md
+│ └── README.md
+└── other_languages
+ ├── ...
+ ├── page.md
+ └── README.md
+
并将主题选项的 locales 设置为:
export default {
+ locales: {
+ '/en/': {
+ lang: 'en-US',
+ // ...
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ // ...
+ },
+ // other languages
+ },
+ // ...
+}
+
这样当用户访问 /
或 /page.html
时,他们会自动根据当前浏览器语言重定向到 /en/
/en/page.html
与 /zh/
/zh/page.html
。
自定义回退行为
有些时候,用户可能会在系统设置中添加多个语言。默认情况下,在站点支持首选语言,但首选语言不存在相应页面时,插件会尝试匹配用户设置的备用语言。
如果不需要回退到用户备用语言,而直接匹配用户首选语言,请在插件选项中设置 localeFallback: false
。
自定义缺失行为
有些时候,当用户访问一个页面时,文档尚未包含用户需要的语言版本 (一个普遍的情况是当前页面尚未完成相关语言的本地化),这样插件需要做出默认行为,你可以通过插件选项中的 defaultBehavior
定制它:
"defaultLocale"
: 重定向到默认语言或首个可用语言页面 (默认行为)"homepage"
: 重定向到当前语言的主页 (仅在文档包含用户语言时可用)"404"
: 重定向到当前语言的 404 页 (仅在文档包含用户语言时可用)自定义默认路径
你可以通过设置插件选项中的 defaultLocale
来自定义默认路径。默认情况下,插件会使用 locales
中的第一个键名作为默认路径。
插件支持在多语言文档中,自动根据用户语言首选项,将链接切换到用户需要的多语言页面。为了实现这一点,你需要在插件选项中设置 switchLocale
,它可以是以下两个值:
direct
: 直接切换到用户语言首选项页面,而不询问modal
: 在用户语言首选项与当前页面语言不同时,弹出一个对话框询问用户是否切换语言默认情况下,插件会从站点的多语言配置 locales
选项中,读取 语言路径
和 lang
生成多语言配置。有些时候,你可能希望多个语言命中同一个路径,这种情况下,你应该设置插件的 localeConfig
选项。
比如,你可能希望所有英文用户都匹配到 /en/
,并将繁体中文用户匹配到 /zh/
中,那么你可以设置:
redirect({
+ localeConfig: {
+ '/en/': ['en-US', 'en-UK', 'en'],
+ '/zh/': ['zh-CN', 'zh-TW', 'zh'],
+ },
+})
+
有时你可能会更改 base
或为你的站点使用新域名,因此你可能希望原始站点自动重定向到新站点。
为了解决这个问题,插件提供了 vp-redirect
脚手架。
使用:
+ $ vp-redirect generate [源文件夹]
+
+Options:
+ --hostname <hostname> 重定向到的域名 (例如: https://new.example.com/) (默认: /)
+ -c, --config <config> 设置配置文件路径
+ -o, --output <output> 设置输出目录 (默认: .vuepress/redirect)
+ --cache <cache> 设置缓存文件的目录
+ -t, --temp <temp> 设置临时文件的目录
+ --clean-cache 生成前清理缓存文件
+ --clean-temp 生成前清理临时文件
+ -h, --help 显示此消息
+
你需要传入 VuePress 项目源目录并设置 hostname
选项。重定向助手脚手架将初始化你的 VuePress 项目以获取页面,然后在输出目录生成重定向 html 文件。
默认情况下,插件将输出到源文件夹下的 .vuepress/redirect
目录。你应该将其上传到你的原始站点以提供重定向。
类型:Record<string, string> | ((app: App) => Record<string, string>)
详情
页面重定向映射。
可直接传入对象或传入参数为 App
的函数返回值一个对象。
每个键名必须是一个绝对路径,代表重定向的源页面地址。
每个键值是重定向的目标地址,可以是绝对路径或完整路径。
示例:
当 base 为 /base/
时:
/base/foo.html
重定向到 /base/bar.html
/base/baz.html
重定向到 https://example.com/qux.html
。redirect({
+ config: {
+ '/foo.html': '/bar.html',
+ '/baz.html': 'https://example.com/qux.html',
+ },
+})
+
将 post 文件夹的路径重定向到 posts 文件夹
redirect({
+ hostname: 'https://example.com',
+ config: (app) =>
+ Object.fromEntries(
+ app.pages
+ .filter(({ path }) => path.startsWith('/posts/'))
+ .map(({ path }) => [path.replace(/^\/posts\//, '/post/'), path]),
+ ),
+})
+
boolean
false
类型:"direct" | "modal" | false
默认值: false
详情:
是否根据用户偏好切换到新的语言环境。
"direct"
: 直接重定向到新的语言环境而不询问"modal"
: 显示一个模式让用户选择是否切换到新的语言环境Record<string, string | string[]>
boolean
true
"defaultLocale" | "homepage" | "404"
"defaultLocale"
string
string | string[]
string
根据组件文件或目录自动注册 Vue 组件。
npm i -D @vuepress/plugin-register-components@next
+
import { registerComponentsPlugin } from '@vuepress/plugin-register-components'
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: Record<string, string>
默认值: {}
详情:
一个定义了组件名称和其对应文件路径的对象。
键会被用作组件名称,值是组件文件的绝对路径。
如果该配置项中的组件名称和 componentsDir 配置项发生冲突,那么该配置项会有更高的优先级。
示例:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ components: {
+ FooBar: path.resolve(__dirname, './components/FooBar.vue'),
+ },
+ }),
+ ],
+}
+
类型: string | null
默认值: null
详情:
组件目录的绝对路径。
该目录下匹配 componentsPatterns 的文件会被自动注册为 Vue 组件。
示例:
import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export default {
+ plugins: [
+ registerComponentsPlugin({
+ componentsDir: path.resolve(__dirname, './components'),
+ }),
+ ],
+}
+
组件目录:
components
+├─ FooBar.vue
+└─ Baz.vue
+
组件会像这样被注册:
import { defineAsyncComponent } from 'vue'
+
+app.component(
+ 'FooBar',
+ defineAsyncComponent(() => import('/path/to/components/FooBar.vue')),
+)
+
+app.component(
+ 'Baz',
+ defineAsyncComponent(() => import('/path/to/components/Baz.vue')),
+)
+
类型: string[]
默认值: ['**/*.vue']
详情:
使用 globby 来匹配组件文件的 Patterns 。
该 Patterns 是相对于 componentsDir 目录的。
类型: (filename: string) => string
默认值: (filename) => path.trimExt(filename.replace(/\/|\\/g, '-'))
详情:
用于从文件名获取对应组件名称的函数。
它只会对 componentsDir 目录下匹配了 componentsPatterns 的文件生效。
注意,这里的 filename
是相对于 componentsPatterns 目录的文件路径。
此插件从你的 VuePress 站点中删除任何相关的 Service Worker,因此如果你在启用后任何 PWA 插件后移除它们,用户仍然可以获得更新。
如果你启用过 PWA,为什么需要这个插件?
PWA 插件,如 @vuepress/plugin-pwa
将 Service Worker 注册到你的站点,这将缓存你的站点并使其离线可用。
但是,如果你删除 PWA 插件,先前的 Service Worker 仍将在那里,但它们永远无法获得更新,因为他们永远无法找到要更新的新 Service Worker。 因此,用户将继续使用你网站的旧版本。
要解决这个问题:
一个新的内容为空的 Service Worker 需要生成在原位置。
新的 Service Worker 应该尝试删除旧 Service Worker 缓存的内容,然后它应该注销自己。
npm i -D @vuepress/plugin-remove-pwa@next
+
import { removePwaPlugin } from '@vuepress/plugin-remove-pwa'
+
+export default {
+ plugins: [
+ removePwaPlugin({
+ // options
+ }),
+ ],
+}
+
string
'workbox'
string
'service-worker.js'
此插件会在配置的语言上设置 rtl 方向。
npm i -D @vuepress/plugin-rtl@next
+
import { rtlPlugin } from '@vuepress/plugin-rtl'
+
+export default {
+ plugins: [
+ rtlPlugin({
+ // 配置项
+ locales: ['/ar/'],
+ }),
+ ],
+}
+
string[]
['/']
类型:SelectorOptions
interface SelectorOptions {
+ [element: string]: {
+ [attrs: string]: string
+ }
+}
+
默认值:{ 'html': { dir: 'rtl' } }
详情:
开启 RTL 的选择器。
默认设置意味着在 RTL 多语言中,html
元素的 dir
属性将被设置为 rtl
。
为你的文档网站提供本地搜索能力。
提示
当你正确配置该插件后,默认主题会把搜索框添加到导航栏。
该插件不一定能在其他主题中直接使用,因此你应参考主题本身的文档来获取更多信息。
npm i -D @vuepress/plugin-search@next
+
import { searchPlugin } from '@vuepress/plugin-search'
+
+export default {
+ plugins: [
+ searchPlugin({
+ // 配置项
+ }),
+ ],
+}
+
该插件会根据你的页面,在本地生成搜索索引,然后在用户访问站点时加载搜索索引文件。换句话说,这是一个轻量级的内置搜索能力,不会进行任何外部请求。
然而,当你的站点包含大量页面时,搜索索引文件也会变得非常大,它可能会拖慢你的页面加载速度。在这种情况下,我们建议你使用更成熟的解决方案 - docsearch 。
类型: Record<string, { placeholder: string }>
详情:
搜索框在不同 locales 下的文字。
如果没有指定该配置项,它会降级使用默认文字。
示例:
export default {
+ plugins: [
+ searchPlugin({
+ locales: {
+ '/': {
+ placeholder: 'Search',
+ },
+ '/zh/': {
+ placeholder: '搜索',
+ },
+ },
+ }),
+ ],
+}
+
(string | HotKeyOptions)[]
export interface HotKeyOptions {
+ /**
+ * Value of `event.key` to trigger the hot key
+ */
+ key: string;
+ /**
+ * Whether to press `event.altKey` at the same time
+ *
+ * @default false
+ */
+ alt?: boolean;
+ /**
+ * Whether to press `event.ctrlKey` at the same time
+ *
+ * @default false
+ */
+ ctrl?: boolean;
+ /**
+ * Whether to press `event.shiftKey` at the same time
+ *
+ * @default false
+ */
+ shift?: boolean;
+}
+
默认值: ['s', '/']
详情:
指定热键的 event.key 。
当按下热键时,搜索框会被聚焦。
将该配置项设为空数组可以禁用热键功能。
类型: number
默认值: 5
详情:
指定搜索结果的最大条数。
类型: (page: Page) => boolean
默认值: () => true
详情:
一个函数,用于判断一个页面是否应该被包含在搜索索引中。
true
来包含该页面。false
来排除该页面。示例:
export default {
+ plugins: [
+ searchPlugin({
+ // 排除首页
+ isSearchable: (page) => page.path !== '/',
+ }),
+ ],
+}
+
类型: (page: Page) => string[]
默认值: () => []
详情:
一个函数,用于在页面的搜索索引中添加额外字段。
默认情况下,该插件会将页面标题和小标题作为搜索索引。该配置项可以帮助你添加更多的可搜索字段。
示例:
export default {
+ plugins: [
+ searchPlugin({
+ // 允许搜索 Frontmatter 中的 `tags`
+ getExtraFields: (page) => page.frontmatter.tags ?? [],
+ }),
+ ],
+}
+
你可以通过 CSS 变量来自定义搜索框的样式:
:root {
+ --search-bg-color: #ffffff;
+ --search-accent-color: #3eaf7c;
+ --search-text-color: #2c3e50;
+ --search-border-color: #eaecef;
+ --search-item-text-color: #5d81a5;
+ --search-item-focus-bg-color: #f3f4f5;
+ --search-input-width: 8rem;
+ --search-result-width: 20rem;
+}
+
详情:
该插件会全局注册一个 <SearchBox />
组件,你可以不传入任何 Props 来使用它。
将该组件放置在你想要显示搜索框的地方。例如,默认主题将这个组件放在了导航栏的末尾。
提示
该组件主要用于主题开发。在大多数情况下你不需要直接使用该组件。
类型:string
必填:是
详情:
部署域名
类型:Author
type AuthorName = string
+
+interface AuthorInfo {
+ /**
+ * 作者姓名
+ */
+ name: string
+
+ /**
+ * 作者网站
+ */
+ url?: string
+
+ /**
+ * 作者 Email
+ */
+ email?: string
+}
+
+type Author = AuthorName | AuthorName[] | AuthorInfo | AuthorInfo[]
+
详情:
默认作者
类型:boolean
默认值:true
详情:
是否自动生成描述
类型:string | ((page: Page) => string | null)
详情:
首选链接
类型:string
详情:
当找不到图片时的回退图片链接
类型:string
详情:
内容的年龄分级,格式为 [int]+
,如 "13+"
类型:string
详情:
你的 twitter 用户名
类型:(page: Page) => boolean
详情:
你可以使用此选项判断一个页面是否是文章。
类型:
function ogp(
+ /** 插件推断的 OGP 信息 */
+ ogp: SeoContent,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
详情:
自定义 OGP 生成器
你可以使用此选项来注入新的或覆盖掉默认生成的 OGP 标签。
类型:
function jsonLd(
+ /** 由插件推断出的 JSON-LD 对象 */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
详情:
自定义 JSON-LD 生成器
你可以使用此选项来注入新的或覆盖掉默认生成的 JSON-LD 标签。
类型:
function customHead(
+ /** head 标签配置 */
+ head: HeadConfig[],
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
详情:
你可以使用此选项来直接注入任意格式的标签到 <head>
。
本插件会通过向网站 <head>
注入标签,让你的网站完全支持 开放内容协议 OGP 和 JSON-LD 1.1,以全面增强站点的搜索引擎优化性。
插件开箱即用,在不做任何配置的情况下,会尽可能通过页面内容,提取对应的信息补全 OGP 与 JSON-LD 所需的必要标签。
默认情况下,插件会读取站点配置、主题配置与页面的 frontmatter 来尽可能自动生成。诸如站点名称,页面标题,页面类型,写作日期,最后更新日期,文章标签均会自动生成。
属性名称 | 值 |
---|---|
og:url | options.hostname + path |
og:site_name | siteConfig.title |
og:title | page.title |
og:description | page.frontmatter.description || 自动生成 (当插件选项中的 autoDescription 为 true 时) |
og:type | "article" |
og:image | options.hostname + page.frontmatter.image || 页面的第一张图片|| 插件选项的 fallbackImage |
og:updated_time | page.git.updatedTime |
og:locale | page.lang |
og:locale:alternate | siteData.locales 包含的其他语言 |
twitter:card | "summary_large_image" (仅在找到图片时) |
twitter:image:alt | page.title (仅在找到图片时) |
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 |
属性名 | 值 |
---|---|
@context | "https://schema.org" |
@type | "NewsArticle" |
headline | page.title |
image | 页面中的图片|| options.hostname + page.frontmatter.image |
datePublished | page.frontmatter.date || page.git.createdTime |
dateModified | page.git.updatedTime |
author | page.frontmatter.author || options.author |
你可以在页面的 frontmatter 中配置 head
选项,自主添加特定标签到页面 <head>
以增强 SEO。
如:
---
+head:
+ - - meta
+ - name: keywords
+ content: SEO plugin
+---
+
会自动注入 <meta name="keywords" content="SEO plugin" />
。
本插件也支持你完全控制生成逻辑。
对于大多数页面,基本只有文章和网页两种类型,所以插件提供了 isArticle
选项让你提供辨别文章的逻辑。
选项接受一个 (page: Page) => boolean
格式的函数,默认情况下从 Markdown 文件生成的非主页页面都会被视为文章。
提示
如果某个网页的确符合图书、音乐之类的“冷门”类型,你可以通过设置下方三个选项处理它们。
你可以使用插件选项的 ogp
传入一个函数来按照你的需要修改默认 OGP 对象并返回。
function ogp(
+ /** 插件推断的 OGP 信息 */
+ ogp: SeoContent,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): SeoContent
+
详细的参数结构详见 配置。
比如你在使用某个第三方主题,并按照主题要求为每篇文章在 Front Matter 中设置了 banner
,那你可以传入这样的 ogp
:
seoPlugin({
+ ogp: (ogp, page) => ({
+ ...ogp,
+ 'og:image': page.frontmatter.banner || ogp['og:image'],
+ }),
+})
+
同 OGP,你可以使用插件选项的 jsonLd
传入一个函数来按照你的需要修改默认 JSON-LD 对象并返回。
function jsonLd(
+ /** 由插件推断出的 JSON-LD 对象 */
+ jsonLD: ArticleSchema | BlogPostingSchema | WebPageSchema,
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): ArticleSchema | BlogPostingSchema | WebPageSchema
+
如果你将内容部署到不同的站点,或不同 URL 下的相同内容,你可能需要设置 canonical
选项为你的页面提供 “规范链接”。 你可以设置一个字符串,这样它会附加在页面路由链接之前,或者添加一个自定义函数 (page: Page) => string | null
返回规范链接。
例子
如果你的站点部署在 example.com
的 docs 文件夹下,但同时在下列网址中可用:
http://example.com/docs/xxx
https://example.com/docs/xxx
http://www.example.com/docs/xxx
https://www.example.com/docs/xxx
(首选)要让搜索引擎结果始终是首选,你可能需要将 canonical
设置为 https://www.example.com/docs/
,以便搜索引擎知道首选第四个 URL 作为索引结果。
有些时候你可能需要符合其他协议或按照其他搜索引擎提供的格式提供对应的 SEO 标签,此时你可以使用 customHead
选项,其类型为:
function customHead(
+ /** head 标签配置 */
+ head: HeadConfig[],
+ /** 页面对象 */
+ page: Page,
+ /** VuePress App */
+ app: App,
+): void
+
你应该直接修改传入的 head
参数。
搜索引擎优化 (Search Engine Optimization),是一种透过了解搜索引擎的运作规则来调整网站,以及提高目的网站在有关搜索引擎内排名的方式。由于不少研究发现,搜索引擎的用户往往只会留意搜索结果最前面的几个条目,所以不少网站都希望透过各种形式来影响搜索引擎的排序,让自己的网站可以有优秀的搜索排名。 所谓“针对搜索引擎作最优化的处理”,是指为了要让网站更容易被搜索引擎接受。搜索引擎会将网站彼此间的内容做一些相关性的资料比对,然后再由浏览器将这些内容以最快速且接近最完整的方式,呈现给搜索者。搜索引擎优化就是通过搜索引擎的规则进行优化,为用户打造更好的用户体验,最终的目的就是做好用户体验。
开放内容协议 OGP (Open Graph Protocal)
本插件完美支持该协议,会自动生成符合该协议的 <meta>
标签。
本插件会为文章类页面生成 NewsArticle 类标签。
RDFa 主要标记 HTML 结构。这是插件无法支持的内容, 使用了这一功能通过了谷歌的富媒体结构测试。你可以考虑搭配使用。
结构标记的 Schema 定义站点
你可以使用 Google 富媒体结构测试工具 测试本站点。
该插件使用 Shiki (Shikiji) 来为 Markdown 代码块启用代码高亮。
提示
Shiki 是 VSCode 正在使用的代码高亮器。它具有更高的保真度,但可能会比 Prism.js 要慢一些,特别是在有大量代码块需要处理的时候。
你可以考虑在 dev
模式下禁用该插件来获取更好的开发体验。
npm i -D @vuepress/plugin-shiki@next
+
import { shikiPlugin } from '@vuepress/plugin-shiki'
+
+export default {
+ plugins: [
+ shikiPlugin({
+ // 配置项
+ langs: ['ts', 'json', 'vue', 'md', 'bash', 'diff'],
+ }),
+ ],
+}
+
类型: ShikiLang[]
详情:
Shikiji 要解析的代码块的语言。
该配置项会被传递到 Shikiji 的 getHighlighter()
方法中。
你需要明确传入所有你使用的语言列表,否则 Shikiji 将不会加载任何语言。
参考:
类型: ShikiTheme
默认值: 'nord'
详情:
Shikiji 的主题。
该配置项会被传递到 Shikiji 的 codeToHtml()
方法中。
参考:
类型:Record<'dark' | 'light', ShikiTheme>
详情:
Shikiji 的暗黑和明亮模式双主题。
该配置项会被传递到 Shikiji 的 codeToHtml()
方法中。
参考:
类型:string
必填:是
详情:
当前网站部署到的域名,插件需要此选项才能工作。
类型:string[]
详情:
需要额外包含的网址。
如果你有一些不包含在 VuePress 路由中的链接 (如: 存放在 public 文件夹下的页面或其他插件或工具直接生成的页面),你可能需要设置此项。
示例:['/about.html', '/api/']
类型:string[]
默认值:['/404.html']
详情:
不需要收录的页面路径,请以绝对路径开头。
默认情况下 VuePress 自动生成的所有路径 (除 404 页) 都会被添加进 Sitemap。
类型:boolean
默认值:false
详情:
是否在开发服务器中启用
提示
由于性能原因,我们不提供热更新。重启开发服务器以同步你的变更。
类型:string
默认值:"http://localhost:${port}"
详情:
开发服务器使用的主机名
类型:string
默认值:"sitemap.xml"
详情:
输出的文件名,相对于输出目录。
类型:string
默认值:"sitemap.xsl"
详情:
输出的 xsl 文件名,相对于输出目录。
类型:string
默认值:"@vuepress-plugin/sitemap/templates/sitemap.xsl"
详情:
用作模板的 XSL 文件内容
类型:"always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never"
默认值:"daily"
详情:
页面默认更新频率,会被 Frontmatter 中的 changefreq 选项覆盖。
类型:number
默认值:0.5
详情:
页面优先级,范围 0
至 1
。
类型:(page: Page, app: App) => string
详情:
最后修改事件的获得器,需要返回一个 ISO 字符形式的时间,默认会自动通过 Git 插件生成。
类型:SitemapFrontmatterOptions | false
详情:
false
表示将页面排除在 sitemap 之外。
类型:"always" | "hourly" | "daily" | "weekly" | "monthly" | "yearly" | "never"
默认值:"daily"
详情:
页面默认更新频率。它会覆盖插件选项中的 changefreq 选项。
类型:number
默认值:0.5
详情:
页面优先级,范围 0
至 1
。
本插件会为你的网站自动生成 Sitemap。为了使插件正常工作,你需要将部署的域名传递给插件的 hostname
选项。如果你想在开发服务器中预览,请配置 devServer
选项。
插件会自动根据页面的 Git 的时间戳生成页面的最后更新时间,同时会根据站点的多语言配置声明页面的其他语言版本替代地址。
默认情况下,所有除 404 页面以外的网站链接均会被添加进 Sitemap。
如果你希望在 VuePress 项目页面之外,添加其他页面链接到 Sitemap,请将它们变成数组传入插件的 extraUrls
选项。
如果你需要排除一些页面路径,你可以将它们变成数组传入到插件的 excludePaths
选项。你也可以在对应页面的 frontmatter 中,设置 sitemap
为 false
。
你还可以通过插件的 sitemapFilename
选项控制输出的地址,此地址相对于输出目录,默认为 sitemap.xml
。
页面默认的更新周期是 daily
(每天),如果你希望修改全部的页面周期,请在插件选项中设置 changefreq
。你也可以在页面的 frontmatter 中设置 sitemap.changefreq
,页面具有更高的优先级。
合法的频率有:
"always"
"hourly"
"daily"
"weekly"
"monthly"
"yearly"
"never"
你可以在插件中设置 priority
以提供一个默认值。同时你可以通过 frontmatter 中的 sitemap.priority
来为每个页面设置优先级。可接受的值为 0
到 1
的浮点数。
你可以通过插件的 modifyTimeGetter
来返回一个 ISO 字符串格式的时间,默认会通过 Git 插件生成。
以下是一个基于文件最后修改时间的例子。
// 基于文件最后修改时间
+({
+ modifyTimeGetter: (page, app) =>
+ fs.statSync(app.dir.source(page.filePathRelative)).mtime.toISOString();
+})
+
网站地图 (Sitemap) 提供搜索引擎优化 (SEO):
网站地图通过使所有页面可被找到来增强搜索引擎优化的效果。
大部分搜索引擎只跟踪页面内有限数量的链接,因此当网站非常大的时候,网站地图对于使搜索引擎和访问者可以访问网站中的所有内容就变得必不可少了。
Sitemaps 是站点管理员向搜索引擎爬虫公布站点可被抓取页面的协议,sitemap 文件内容必须遵循 XML 格式的定义。每个 URL 可以包含更新的周期和时间、URL 在整个站点中的优先级。这样可以让搜索引擎更佳有效的抓取网站内容。
同步配置 robots.txt
由于 Sitemap 面向搜索引擎,配合此插件使用时,你最好保证你在 .vuepress/public
文件夹下放置了有效的 robots.txt
,以允许搜索引擎收录。一个最简单的 robots.txt 如下 (允许所有搜索引擎访问所有路径)
User-agent: *
+
+Allow: /
+
为你的主题提供客户端数据,包含 VuePress 的 多语言支持 。
该插件主要用于开发主题,并且已经集成到默认主题中。大部分情况下你不需要直接使用它。
对于主题作者,该插件可以提供与 VuePress 及默认主题相同的多语言支持机制。但是如果你的主题不需要提供多语言支持,或者你想用你自己的方式来实现多语言支持,那么你不需要使用该插件。
npm i -D @vuepress/plugin-theme-data@next
+
import { themeDataPlugin } from '@vuepress/plugin-theme-data'
+
+export default {
+ plugins: [
+ themeDataPlugin({
+ // 配置项
+ }),
+ ],
+}
+
类型: ThemeData
默认值: {}
详情:
你希望在 Client 端中使用的主题数据对象。
你可以通过该配置项,在 Node 端提供主题数据,然后在客户端通过 useThemeData 和 useThemeLocaleData 来使用主题数据。
示例:
export default {
+ plugins: [
+ themeDataPlugin({
+ themeData: {
+ foo: 'foo',
+ locales: {
+ '/zh/': {
+ foo: 'zh-foo',
+ },
+ },
+ },
+ }),
+ ],
+}
+
注意
主题数据对象在传递到客户端之前,会使用 JSON.stringify()
进行处理,因此你需要保证你提供的是一个可以被 JSON 序列化的对象。
详情:
返回主题数据的 Ref 对象。
数据是通过 themeData 配置项提供的。
示例:
import { useThemeData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeData = useThemeData<MyThemeData>()
+ console.log(themeData.value)
+ },
+}
+
详情:
返回当前 locale 下主题数据的 Ref 对象。
当前 locale 中的字段已被合并到顶层字段中。
示例:
import { useThemeLocaleData } from '@vuepress/plugin-theme-data/client'
+import type { ThemeData } from '@vuepress/plugin-theme-data/client'
+
+type MyThemeData = ThemeData<{
+ foo: string
+}>
+
+export default {
+ setup() {
+ const themeLocaleData = useThemeLocaleData<MyThemeData>()
+ console.log(themeLocaleData.value)
+ },
+}
+
该插件会提供一个目录 (table-of-contents, TOC) 组件。
npm i -D @vuepress/plugin-toc@next
+
import { tocPlugin } from '@vuepress/plugin-toc'
+
+export default {
+ plugins: [
+ tocPlugin({
+ // 配置项
+ }),
+ ],
+}
+
与 Markdown 目录语法 类似,该插件提供的目录组件可以直接在你的 Markdown 内容中使用:
<!-- Markdown 目录语法 -->
+
+[[toc]]
+
+<!-- Vue 目录组件 -->
+<Toc />
+
在 Build 模式中,它们都可以被正确地预渲染。然而,它们之间存在一些区别。
Markdown 语法 [[toc]]
仅能在 Markdown 文件中使用。它是由 markdown-it 解析的,生成的目录是静态内容。
组件 <Toc/>
既可以用在 Markdown 文件中,也可以用在 Vue 文件中。它是由 Vue 加载的,生成的目录是一个 Vue 组件。
该插件可以和 @vuepress/plugin-active-header-links 协同工作,你只需要将 headerLinkSelector 与该插件的 linkClass
匹配即可。当页面滚动至某个标题锚点后,对应的链接就会被加上 linkActiveClass
类名。
因此,该插件对于主题开发者来说更为有用。
类型: string
默认值: 'Toc'
详情:
指定目录组件的名称。
类型: Partial<TocPropsOptions>
默认值: {}
详情:
覆盖组件 options Prop 的默认值。
目录组件可以通过 Props 来进行自定义。
<template>
+ <Toc :headers="headers" :options="options" />
+</template>
+
PageHeader[]
interface PageHeader {
+ level: number
+ title: string
+ slug: string
+ children: PageHeader[]
+}
+
详情:
指定要渲染的标题数组。
如果该 Prop 没有被设置,默认会使用当前页面的标题。
Partial<TocPropsOptions>
interface TocPropsOptions {
+ containerTag: string
+ containerClass: string
+ listClass: string
+ itemClass: string
+ linkTag: 'a' | 'RouterLink'
+ linkClass: string
+ linkActiveClass: string
+ linkChildrenActiveClass: string
+}
+
默认值:
下列默认值可以用过 defaultPropsOptions 来覆盖:
const defaultOptions = {
+ containerTag: 'nav',
+ containerClass: 'vuepress-toc',
+ listClass: 'vuepress-toc-list',
+ itemClass: 'vuepress-toc-item',
+ linkTag: 'RouterLink',
+ linkClass: 'vuepress-toc-link',
+ linkActiveClass: 'active',
+ linkChildrenActiveClass: 'active',
+}
+
详情:
自定义目录组件。
如果 containerTag
设置为空字符串 ''
,那么最外层的 <nav>
Container 会被完全移除。
示例:
使用默认 options 的目录组件的渲染结果类似以下结构:
<template>
+ <!-- container -->
+ <nav class="vuepress-toc">
+ <!-- list -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link -->
+ <RouterLink class="vuepress-toc-link" to="#foo">Foo</RouterLink>
+ </li>
+ <!-- item with children -->
+ <li class="vuepress-toc-item">
+ <!-- link (children active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar">Bar</RouterLink>
+ <!-- list (children) -->
+ <ul class="vuepress-toc-list">
+ <!-- item -->
+ <li class="vuepress-toc-item">
+ <!-- link (active) -->
+ <RouterLink class="vuepress-toc-link active" to="#bar-child">
+ Bar Child
+ </RouterLink>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </nav>
+</template>
+
Props:
'tip' | 'warning' | 'danger'
'tip'
string
''
'top' | 'middle' | 'bottom' | undefined
undefined
示例:
输入
- VuePress - <Badge type="tip" text="v2" vertical="top" />
+- VuePress - <Badge type="warning" text="v2" vertical="middle" />
+- VuePress - <Badge type="danger" text="v2" vertical="bottom" />
+
输出
详情:
CodeGroupItem 组件的 Wrapper 。
Props:
string
true
boolean
false
详情:
该组件必须放置在 CodeGroup 组件的内部。
可以通过 active
Prop 来设置初始激活的元素。如果不设置,默认激活第一个元素。
示例:
输入
<CodeGroup>
+ <CodeGroupItem title="pnpm">
+
+```bash:no-line-numbers
+pnpm install
+```
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="yarn">
+
+```bash:no-line-numbers
+yarn install
+```
+
+ </CodeGroupItem>
+
+ <CodeGroupItem title="npm" active>
+
+```bash:no-line-numbers
+npm install
+```
+
+ </CodeGroupItem>
+</CodeGroup>
+
输出
pnpm install
+
yarn install
+
npm install
+
注意
你必须在 <CodeGroupItem>
的开始标签和代码块之间添加一个空行,否则代码块无法被 Markdown 正确解析。
所有内容首先都必须是合法的 Markdown ,然后才是一个 Vue SFC 。
了解更多: Cookbook > Markdown 与 Vue SFC
或者你可以选择使用 自定义容器 。
类型: string
详情:
部署的域名,例如 https://example.com
类型: { [path: string]: Partial<DefaultThemeLocaleData> }
默认值: {}
详情:
多语言支持的各个语言 locales 。
所有在 Locale 配置 章节内的配置项都可以在 locales 中使用。
该配置项仅能在默认主题内生效,注意不要和 站点配置 中的 locales
混淆。
参考:
该章节内的配置项可以作为一般配置使用,也可以使用在 locales 内。
类型: 'auto' | 'light' | 'dark'
默认值: 'auto'
详情:
默认颜色模式。
如果设置为 'auto'
,则会根据 prefers-color-scheme 自动设置初始颜色模式。
参考:
类型: boolean
默认值: true
详情:
是否启用切换颜色模式的功能。
如果设置为 true
,将会在导航栏展示一个切换颜色模式的按钮。
参考:
类型: string
默认值: /
详情:
首页的路径。
它将被用于:
类型: false | (NavbarItem | NavbarGroup | string)[]
默认值: []
详情:
导航栏配置。
设置为 false
可以禁用导航栏。
为了配置导航栏元素,你可以将其设置为 导航栏数组 ,其中的每个元素是 NavbarItem
对象、 NavbarGroup
对象、或者字符串:
NavbarItem
对象应该有一个 text
字段和一个 link
字段,还有一个可选的 activeMatch
字段。NavbarGroup
对象应该有一个 text
字段和一个 children
字段。 children
字段同样是一个 导航栏数组 。NavbarItem
对象,将页面标题作为 text
,将页面路由路径作为 link
。示例 1:
export default {
+ theme: defaultTheme({
+ navbar: [
+ // NavbarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ },
+ // NavbarGroup
+ {
+ text: 'Group',
+ children: ['/group/foo.md', '/group/bar.md'],
+ },
+ // 字符串 - 页面文件路径
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ navbar: [
+ // 嵌套 Group - 最大深度为 2
+ {
+ text: 'Group',
+ children: [
+ {
+ text: 'SubGroup',
+ children: ['/group/sub/foo.md', '/group/sub/bar.md'],
+ },
+ ],
+ },
+ // 控制元素何时被激活
+ {
+ text: 'Group 2',
+ children: [
+ {
+ text: 'Always active',
+ link: '/',
+ // 该元素将一直处于激活状态
+ activeMatch: '/',
+ },
+ {
+ text: 'Active on /foo/',
+ link: '/not-foo/',
+ // 该元素在当前路由路径是 /foo/ 开头时激活
+ // 支持正则表达式
+ activeMatch: '^/foo/',
+ },
+ ],
+ },
+ ],
+ }),
+}
+
类型: null | string
详情:
Logo 图片的 URL。
Logo 图片将会显示在导航栏的左端。
设置为 null
可以禁用 Logo 。
示例:
export default {
+ theme: defaultTheme({
+ // Public 文件路径
+ logo: '/images/hero.png',
+ // URL
+ logo: 'https://vuejs.org/images/logo.png',
+ }),
+}
+
类型: null | string
详情:
在夜间模式中使用的 Logo 图片的 URL。
如果你想在夜间模式中使用不同的 Logo 图片,就可以使用该配置项。
设置为 null
可以在夜间模式下禁用 Logo 。忽略该配置项将会在夜间模式中使用 logo 配置。
参考:
类型:null | string
详情:
指定 Logo 图片的替代文字。
当未指定时,将默认与站点标题相同。
类型: string
详情:
项目仓库的 URL。
它将被用作 仓库链接 的链接。仓库链接 将会显示为导航栏的最后一个元素。
export default {
+ theme: defaultTheme({
+ // 如果你按照 `organization/repository` 的格式设置它
+ // 我们会将它作为一个 GitHub 仓库
+ repo: 'vuejs/vuepress',
+ // 你也可以直接将它设置为一个 URL
+ repo: 'https://gitlab.com/foo/bar',
+ }),
+}
+
类型: false | 'auto' | SidebarConfigArray | SidebarConfigObject
默认值: 'auto'
详情:
侧边栏配置。
你可以通过页面的 sidebar frontmatter 来覆盖这个全局配置。
设置为 false
可以禁用侧边栏。
如果你设置为 'auto'
,侧边栏会根据页面标题自动生成。
为了手动配置侧边栏元素,你可以将其设置为 侧边栏数组 ,其中的每个元素是一个 SidebarItem
对象或者一个字符串:
SidebarItem
对象应该有一个 text
字段,有一个可选的 link
字段、一个可选的 children
字段和一个可选的 collapsible
字段。 children
字段同样是一个 侧边栏数组 。 collapsible
字段来控制它是否可折叠。SidebarItem
对象,将页面标题作为 text
,将页面路由路径作为 link
,并根据页面小标题自动生成 children
。如果你想在不同子路径中使用不同的侧边栏,你可以将该配置项设置为 侧边栏对象 :
"heading"
以自动为相应路径生成基于标题的侧边栏。示例 1:
export default {
+ theme: defaultTheme({
+ // 侧边栏数组
+ // 所有页面会使用相同的侧边栏
+ sidebar: [
+ // SidebarItem
+ {
+ text: 'Foo',
+ link: '/foo/',
+ children: [
+ // SidebarItem
+ {
+ text: 'github',
+ link: 'https://github.com',
+ children: [],
+ },
+ // 字符串 - 页面文件路径
+ '/foo/bar.md',
+ ],
+ },
+ // 字符串 - 页面文件路径
+ '/bar/README.md',
+ ],
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // 侧边栏对象
+ // 不同子路径下的页面会使用不同的侧边栏
+ sidebar: {
+ '/guide/': [
+ {
+ text: 'Guide',
+ children: ['/guide/introduction.md', '/guide/getting-started.md'],
+ },
+ ],
+ '/reference/': 'heading',
+ },
+ }),
+}
+
export default {
+ theme: defaultTheme({
+ // 可折叠的侧边栏
+ sidebar: {
+ '/reference/': [
+ {
+ text: 'VuePress Reference',
+ collapsible: true,
+ children: ['/reference/cli.md', '/reference/config.md'],
+ },
+ {
+ text: 'Bundlers Reference',
+ collapsible: true,
+ children: [
+ '/reference/bundler/vite.md',
+ '/reference/bundler/webpack.md',
+ ],
+ },
+ ],
+ },
+ }),
+}
+
类型: number
默认值: 2
详情:
设置根据页面标题自动生成的侧边栏的最大深度。
0
来禁用所有级别的页面标题。1
来包含 <h2>
标题。2
来包含 <h2>
和 <h3>
标题。最大值取决于你通过 markdown.headers.level 提取了哪些级别的标题。
由于 markdown.headers.level
的默认值是 [2, 3]
,因此 sidebarDepth
的默认最大值是 2
。
你可以通过页面的 sidebarDepth frontmatter 来覆盖这个全局配置。
类型: boolean
默认值: true
详情:
是否启用 编辑此页 链接。
你可以通过页面的 editLink frontmatter 来覆盖这个全局配置。
类型: string
详情:
编辑此页 链接的 Pattern 。
它将会用于生成 编辑此页 的链接。
如果你不设置该选项,则会根据 docsRepo 配置项来推断 Pattern 。但是如果你的文档仓库没有托管在常用的平台上,比如 GitHub 、 GitLab 、 Bitbucket 、 Gitee 等,那么你必须设置该选项才能使 编辑此页 链接正常工作。
用法:
Pattern | 描述 |
---|---|
:repo | 文档仓库 URL ,即 docsRepo |
:branch | 文档仓库分支 ,即 docsBranch |
:path | 页面源文件的路径,即 docsDir 拼接上页面文件的相对路径 |
示例:
export default {
+ theme: defaultTheme({
+ docsRepo: 'https://gitlab.com/owner/name',
+ docsBranch: 'master',
+ docsDir: 'docs',
+ editLinkPattern: ':repo/-/edit/:branch/:path',
+ }),
+}
+
则会生成类似于 'https://gitlab.com/owner/name/-/edit/master/docs/path/to/file.md'
的链接。
类型: string
详情:
文档源文件的仓库 URL 。
它将会用于生成 编辑此页 的链接。
如果你不设置该选项,则默认会使用 repo 配置项。但是如果你的文档源文件是在一个不同的仓库内,你就需要设置该配置项了。
类型: string
默认值: 'main'
详情:
文档源文件的仓库分支。
它将会用于生成 编辑此页 的链接。
类型: string
默认值: ''
详情:
文档源文件存放在仓库中的目录名。
它将会用于生成 编辑此页 的链接。
类型: boolean
默认值: true
详情:
是否启用 最近更新时间戳 。
你可以通过页面的 lastUpdated frontmatter 来覆盖这个全局配置。要注意的是,如果你已经将该选项设为了 false
,那么这个功能会被完全禁用,并且无法在 locales 或页面 frontmatter 中启用。
类型: boolean
默认值: true
详情:
是否启用 贡献者列表 。
你可以通过页面的 contributors frontmatter 来覆盖这个全局配置。要注意的是,如果你已经将该选项设为了 false
,那么这个功能会被完全禁用,并且无法在 locales 或页面 frontmatter 中启用。
VuePress 默认主题有着大量的用户,因此我们对它进行了一些便于继承的设计,以便用户轻松进行定制化。
默认主题的 Layout
布局提供了一些插槽:
navbar
navbar-before
navbar-after
sidebar
sidebar-top
sidebar-bottom
page
page-top
page-bottom
page-content-top
page-content-bottom
在它们的帮助下,你可以很容易地添加或替换内容。下面通过一个示例来介绍一下如何使用布局插槽来继承默认主题。
首先,创建一个客户端配置文件 .vuepress/client.ts
:
import { defineClientConfig } from 'vuepress/client'
+import Layout from './layouts/Layout.vue'
+
+export default defineClientConfig({
+ layouts: {
+ Layout,
+ },
+})
+
接下来,创建 .vuepress/layouts/Layout.vue
,并使用由默认主题的 Layout
布局提供的插槽:
<script setup>
+import ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'
+</script>
+
+<template>
+ <ParentLayout>
+ <template #page-bottom>
+ <div class="my-footer">This is my custom page footer</div>
+ </template>
+ </ParentLayout>
+</template>
+
+<style lang="css">
+.my-footer {
+ text-align: center;
+}
+</style>
+
此时默认的 Layout
布局已经被你的本地布局覆盖,将会在除了首页外的所有页面添加一个自定义的页脚:
布局插槽十分实用,但有时候你可能会觉得它不够灵活。默认主题同样提供了替换单个组件的能力。
默认主题将所有 非全局的组件 都注册了一个带 @theme
前缀的 alias 。例如,HomeFooter.vue
的别名是 @theme/HomeFooter.vue
。
接下来,如果你想要替换 HomeFooter.vue
组件,只需要在配置文件 .vuepress/config.ts
中覆盖这个别名即可:
import { defaultTheme } from '@vuepress/theme-default'
+import { getDirname, path } from 'vuepress/utils'
+import { defineUserConfig } from 'vuepress'
+
+const __dirname = getDirname(import.meta.url)
+
+export default defineUserConfig({
+ theme: defaultTheme(),
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+})
+
除了在 .vuepress/config.ts
和 .vuepress/client.ts
中直接扩展默认主题以外,你可以通过继承默认主题来开发一个你自己的主题:
import { defaultTheme, type DefaultThemeOptions } from '@vuepress/theme-default'
+import type { Theme } from 'vuepress/core'
+import { getDirname, path } from 'vuepress/utils'
+
+const __dirname = getDirname(import.meta.url)
+
+export const childTheme = (options: DefaultThemeOptions): Theme => {
+ return {
+ name: 'vuepress-theme-child',
+ extends: defaultTheme(options),
+
+ // 在子主题的客户端配置文件中覆盖布局
+ // 注意,你在发布到 NPM 之前会将 TS 构建为 JS ,因此这里需要设置为 JS 文件的路径
+ clientConfigFile: path.resolve(__dirname, './client.js'),
+
+ // 覆盖组件别名
+ alias: {
+ '@theme/HomeFooter.vue': path.resolve(
+ __dirname,
+ './components/MyHomeFooter.vue',
+ ),
+ },
+ }
+}
+
本章节中的 Frontmatter 会在所有类型的页面中生效。
类型: boolean
详情:
参考:
类型: boolean
详情:
是否在当前页面展示导航栏。
如果你在主题配置中禁用了导航栏,那么该 Frontmatter 将不会生效。
参考:
类型: string
详情:
为当前页面添加额外的类名。
示例:
---
+pageClass: custom-page-class
+---
+
然后你可以在 .vuepress/styles/index.scss
文件中为这个页面添加自定义样式:
.theme-container.custom-page-class {
+ /* 页面样式 */
+}
+
本章节中的 Frontmatter 只会在首页中生效。
类型: boolean
详情:
设定该页面是首页还是普通页面。
如果你不设置该 Frontmatter 或将其设为 false
,则该页面会是一个 普通页面
示例:
---
+home: true
+---
+
类型: string
详情:
首页图片的 URL 。
示例:
---
+# Public 文件路径
+heroImage: /images/hero.png
+# URL
+heroImage: https://vuejs.org/images/logo.png
+---
+
参考:
类型: string
详情:
在夜间模式中使用的首页图片的 URL 。
如果你想在夜间模式中使用不同的首页图片,就可以使用该配置项。
参考:
类型: string
详情:
首页图片的 alt
属性。
如果不设置,则默认使用 heroText 。
类型: number
默认值: 280
详情:
首页图片 <img>
标签的 height
属性。
当你的首页图片高度小于默认值时,你可能需要减小该属性。
需要注意的是,首页图片的高度同样受到了 CSS 的约束。设置这个属性主要是为了减少由加载首页图片引起的 累积布局偏移 (CLS) 。
类型: string | null
详情:
首页的大标题。
如果不设置,则默认使用站点 title 。
设置为 null
来禁用首页大标题。
类型: string | null
详情:
首页的标语。
如果不设置,则默认使用站点 description 。
设置为 null
来禁用首页标语。
Array<{
+ text: string
+ link: string
+ type?: 'primary' | 'secondary'
+}>
+
详情:
配置首页按钮。
示例:
---
+actions:
+ - text: 快速上手
+ link: /zh/guide/getting-started.html
+ type: primary
+ - text: 项目简介
+ link: /zh/guide/introduction.html
+ type: secondary
+---
+
Array<{
+ title: string
+ details: string
+}>
+
详情:
配置首页特性列表。
示例:
---
+features:
+ - title: 简洁至上
+ details: 以 Markdown 为中心的项目结构,以最少的配置帮助你专注于写作。
+ - title: Vue 驱动
+ details: 享受 Vue 的开发体验,可以在 Markdown 中使用 Vue 组件,又可以使用 Vue 来开发自定义主题。
+ - title: 高性能
+ details: VuePress 会为每个页面预渲染生成静态的 HTML,同时,每个页面被加载的时候,将作为 SPA 运行。
+---
+
类型: string
详情:
首页的页脚。
类型: boolean
详情:
是否允许页脚中使用 HTML 。
如果设置为 true
,那么 footer 会被作为 HTML 代码处理。
本章节中的 Frontmatter 只会在普通页面中生效。
类型: boolean
详情:
是否在本页面中启用 编辑此页 链接。
参考:
类型: string
详情:
本页面中 编辑此页 链接的 Pattern 。
参考:
类型: boolean
详情:
是否在本页面中启用 最近更新时间戳 。
参考:
类型: boolean
详情:
是否在本页面中启用 贡献者列表 。
参考:
类型: false | 'auto' | SidebarConfigArray | SidebarConfigObject
详情:
配置本页面的侧边栏。
参考:
类型: number
详情:
配置本页面的侧边栏深度。
参考:
类型: NavLink | string
详情:
上一个页面的链接。
如果你不设置该 Frontmatter ,该链接会自动根据侧边栏配置进行推断。
为了手动配置上一页面的链接,你可以将其设置为一个 NavLink
对象或者一个字符串:
NavLink
对象应该有一个 text
字段和一个 link
字段。NavLink
对象,将页面标题作为 text
,将页面路由路径作为 link
。示例:
---
+# NavLink
+prev:
+ text: Get Started
+ link: /guide/getting-started.html
+
+# NavLink - 外部 URL
+prev:
+ text: GitHub
+ link: https://github.com
+
+# 字符串 - 页面文件路径
+prev: /guide/getting-started.md
+
+# 字符串 - 页面文件相对路径
+prev: ../../guide/getting-started.md
+---
+
类型: NavLink | string
详情:
下一个页面的链接。
如果你不设置该 Frontmatter ,该链接会自动根据侧边栏配置进行推断。
类型和 prev Frontmatter 相同。
安装默认主题:
npm i -D @vuepress/theme-default@next
+
在配置文件中指定主题:
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ // 在这里添加主题配置
+ }),
+}
+
这些选项用于配置与语言相关的文本。
如果你的站点是以英语以外的其他语言提供服务的,你应该为每个语言设置这些选项来提供翻译。
类型: string
详情:
项目仓库的标签。
它将被用作 仓库链接 的文字。仓库链接 将会显示为导航栏的最后一个元素。
如果你不明确指定该配置项,它将会根据 repo 配置项自动推断。
类型: string
详情:
选择语言菜单 的文字。
如果你在站点配置中设置了多个 locales ,那么 选择语言菜单 就会显示在导航栏中仓库按钮的旁边。
类型: string
详情:
选择语言菜单 的 aria-label
属性。
它主要是为了站点的可访问性 (a11y) 。
类型: string
详情:
Locale 的语言名称。
该配置项 仅能在主题配置的 locales 的内部生效 。它将被用作 locale 的语言名称,展示在 选择语言菜单 内。
示例:
export default {
+ locales: {
+ '/': {
+ lang: 'en-US',
+ },
+ '/zh/': {
+ lang: 'zh-CN',
+ },
+ },
+ theme: defaultTheme({
+ locales: {
+ '/': {
+ selectLanguageName: 'English',
+ },
+ '/zh/': {
+ selectLanguageName: '简体中文',
+ },
+ },
+ }),
+}
+
类型:null | string
详情:
导航栏中主导航 aria-label
属性的值。
类型:null | string
详情:
下一页/上一页导航 aria-label
属性的值
类型: string
默认值: 'Edit this page'
详情:
编辑此页 链接的文字。
类型: string
默认值: 'Last Updated'
详情:
最近更新时间戳 标签的文字。
类型: string
默认值: 'Contributors'
详情:
贡献者列表 标签的文字。
类型: string
默认值: 'TIP'
详情:
Tip 自定义容器 的默认标题。
类型: string
默认值: 'WARNING'
详情:
Warning 自定义容器 的默认标题。
类型: string
默认值: 'DANGER'
详情:
Danger 自定义容器 的默认标题。
类型: string[]
默认值: ['Not Found']
详情:
404 页面的提示信息。
当用户进入 404 页面时,会从数组中随机选取一条信息进行展示。
类型: string
默认值: 'Back to home'
详情:
404 页面中 返回首页 链接的文字。
类型: string
默认值: 'open in new window'
详情:
ExternalLinkIcon. 链接内的 sr-only
文字。
它主要是为了站点的可访问性 (a11y) 。
参考:
类型: string
默认值: 'toggle color mode'
详情:
切换颜色模式按钮的标题文字。
它主要是为了站点的可访问性 (a11y) 。
参考:
类型: string
默认值: 'toggle sidebar'
详情:
切换侧边栏按钮的标题文字。
它主要是为了站点的可访问性 (a11y) 。
使用:
::: <type> [title]
+[content]
+:::
+
type
是必需的, title
和 content
是可选的。
支持的 type
有:
tip
warning
danger
details
code-group
code-group-item
示例 1 (默认标题):
输入
::: tip
+这是一个提示
+:::
+
+::: warning
+这是一个警告
+:::
+
+::: danger
+这是一个危险警告
+:::
+
+::: details
+这是一个 details 标签
+:::
+
输出
提示
这是一个提示
注意
这是一个警告
警告
这是一个危险警告
这是一个 details 标签
输入
::: danger STOP
+危险区域,禁止通行
+:::
+
+::: details 点击查看代码
+
+```ts
+console.log('你好,VuePress!')
+```
+
+:::
+
输出
STOP
危险区域,禁止通行
console.log('你好,VuePress!')
+
输入
:::: code-group
+::: code-group-item FOO
+
+```ts
+const foo = 'foo'
+```
+
+:::
+
+::: code-group-item BAR
+
+```ts
+const bar = 'bar'
+```
+
+:::
+::::
+
输出
const foo = 'foo'
+
const bar = 'bar'
+
你可以通过 themePlugins
设置默认主题使用的插件。
默认主题使用了一些插件,如果你确实不需要该插件,你可以选择禁用它。在禁用插件之前,请确保你已了解它的用途。
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ themePlugins: {
+ // 在这里自定义主题插件
+ },
+ }),
+}
+
类型: boolean
默认值: true
详情:
类型: BackToTopPluginOptions | boolean
默认值: true
详情:
是否启用 @vuepress/plugin-back-to-top 。
支持对象格式以作为插件选项。
类型: Record<ContainerType, boolean>
详情:
是否启用由 @vuepress/plugin-container 支持的自定义容器。
ContainerType
类型为:
tip
warning
danger
details
codeGroup
codeGroupItem
参考:
类型: CopyCodePluginOptions | boolean
默认值: true
详情:
是否启用 @vuepress/plugin-copy-code 。
支持对象格式以作为插件选项。
类型: boolean
默认值: true
详情:
类型: boolean
默认值: true
详情:
是否启用 @vuepress/plugin-git 。
类型: boolean
默认值: true
详情:
是否启用 @vuepress/plugin-medium-zoom 。
类型: boolean
默认值: true
详情:
是否启用 @vuepress/plugin-nprogress 。
类型: SeoPluginOptions | boolean
默认值: true
详情:
是否启用 @vuepress/plugin-seo 。
支持对象格式以作为插件选项。
类型: SitemapPluginOptions | boolean
默认值: true
详情:
是否启用 @vuepress/plugin-sitemap 。
支持对象格式以作为插件选项。
默认主题使用 SASS 作为 CSS 预处理器。
用户可以通过 palette 文件 来自定义样式变量,还可以通过 style 文件 来添加额外的样式。
Palette 文件的路径是 .vuepress/styles/palette.scss
。
你可以利用它来覆盖默认主题的预定义 SASS 变量。
// responsive breakpoints
+$MQNarrow: 959px !default;
+$MQMobile: 719px !default;
+$MQMobileNarrow: 419px !default;
+
Style 文件的路径是 .vuepress/styles/index.scss
。
你可以在这里添加额外的样式,或者覆盖默认样式:
:root {
+ scroll-behavior: smooth;
+}
+
你也可以利用它来覆盖默认主题的预定义 CSS 变量。
:root {
+ // brand colors
+ --c-brand: #3eaf7c;
+ --c-brand-light: #4abf8a;
+
+ // background colors
+ --c-bg: #ffffff;
+ --c-bg-light: #f3f4f5;
+ --c-bg-lighter: #eeeeee;
+ --c-bg-dark: #ebebec;
+ --c-bg-darker: #e6e6e6;
+ --c-bg-navbar: var(--c-bg);
+ --c-bg-sidebar: var(--c-bg);
+ --c-bg-arrow: #cccccc;
+
+ // text colors
+ --c-text: #2c3e50;
+ --c-text-accent: var(--c-brand);
+ --c-text-light: #3a5169;
+ --c-text-lighter: #4e6e8e;
+ --c-text-lightest: #6a8bad;
+ --c-text-quote: #999999;
+
+ // border colors
+ --c-border: #eaecef;
+ --c-border-dark: #dfe2e5;
+
+ // custom container colors
+ --c-tip: #42b983;
+ --c-tip-bg: var(--c-bg-light);
+ --c-tip-title: var(--c-text);
+ --c-tip-text: var(--c-text);
+ --c-tip-text-accent: var(--c-text-accent);
+ --c-warning: #ffc310;
+ --c-warning-bg: #fffae3;
+ --c-warning-bg-light: #fff3ba;
+ --c-warning-bg-lighter: #fff0b0;
+ --c-warning-border-dark: #f7dc91;
+ --c-warning-details-bg: #fff5ca;
+ --c-warning-title: #f1b300;
+ --c-warning-text: #746000;
+ --c-warning-text-accent: #edb100;
+ --c-warning-text-light: #c1971c;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #f11e37;
+ --c-danger-bg: #ffe0e0;
+ --c-danger-bg-light: #ffcfde;
+ --c-danger-bg-lighter: #ffc9c9;
+ --c-danger-border-dark: #f1abab;
+ --c-danger-details-bg: #ffd4d4;
+ --c-danger-title: #ed1e2c;
+ --c-danger-text: #660000;
+ --c-danger-text-accent: #bd1a1a;
+ --c-danger-text-light: #b5474d;
+ --c-danger-text-quote: #c15b5b;
+ --c-details-bg: #eeeeee;
+
+ // badge component colors
+ --c-badge-tip: var(--c-tip);
+ --c-badge-warning: #ecc808;
+ --c-badge-warning-text: var(--c-bg);
+ --c-badge-danger: #dc2626;
+ --c-badge-danger-text: var(--c-bg);
+
+ // code group colors
+ --c-code-group-tab-title: rgba(255, 255, 255, 0.9);
+ --c-code-group-tab-bg: var(--code-bg-color);
+ --c-code-group-tab-outline: var(var(--c-code-group-tab-title));
+ --c-code-group-tab-active-border: var(--c-brand);
+
+ // transition vars
+ --t-color: 0.3s ease;
+ --t-transform: 0.3s ease;
+
+ // code blocks vars
+ --code-bg-color: #282c34;
+ --code-hl-bg-color: rgba(0, 0, 0, 0.66);
+ --code-ln-color: #9e9e9e;
+ --code-ln-wrapper-width: 3.5rem;
+
+ // font vars
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
+ Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
+ --font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+
+ // layout vars
+ --navbar-height: 3.6rem;
+ --navbar-padding-v: 0.7rem;
+ --navbar-padding-h: 1.5rem;
+ --sidebar-width: 20rem;
+ --sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
+ --content-width: 740px;
+ --homepage-width: 960px;
+}
+
+// plugin-back-to-top
+.back-to-top {
+ --back-to-top-color: var(--c-brand);
+ --back-to-top-color-hover: var(--c-brand-light);
+ --back-to-top-bg-color: var(--c-bg);
+}
+
+// plugin-docsearch
+.DocSearch {
+ --docsearch-primary-color: var(--c-brand);
+ --docsearch-text-color: var(--c-text);
+ --docsearch-highlight-color: var(--c-brand);
+ --docsearch-muted-color: var(--c-text-quote);
+ --docsearch-container-background: rgba(9, 10, 17, 0.8);
+ --docsearch-modal-background: var(--c-bg-light);
+ --docsearch-searchbox-background: var(--c-bg-lighter);
+ --docsearch-searchbox-focus-background: var(--c-bg);
+ --docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
+ --docsearch-hit-color: var(--c-text-light);
+ --docsearch-hit-active-color: var(--c-bg);
+ --docsearch-hit-background: var(--c-bg);
+ --docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
+ --docsearch-footer-background: var(--c-bg);
+}
+
+// plugin-external-link-icon
+.external-link-icon {
+ --external-link-icon-color: var(--c-text-quote);
+}
+
+// plugin-medium-zoom
+.medium-zoom-overlay {
+ --medium-zoom-bg-color: var(--c-bg);
+}
+
+// plugin-nprogress
+#nprogress {
+ --nprogress-color: var(--c-brand);
+}
+
+// plugin-pwa-popup
+.pwa-popup {
+ --pwa-popup-text-color: var(--c-text);
+ --pwa-popup-bg-color: var(--c-bg);
+ --pwa-popup-border-color: var(--c-brand);
+ --pwa-popup-shadow: 0 4px 16px var(--c-brand);
+ --pwa-popup-btn-text-color: var(--c-bg);
+ --pwa-popup-btn-bg-color: var(--c-brand);
+ --pwa-popup-btn-hover-bg-color: var(--c-brand-light);
+}
+
+// plugin-search
+.search-box {
+ --search-bg-color: var(--c-bg);
+ --search-accent-color: var(--c-brand);
+ --search-text-color: var(--c-text);
+ --search-border-color: var(--c-border);
+
+ --search-item-text-color: var(--c-text-lighter);
+ --search-item-focus-bg-color: var(--c-bg-light);
+}
+
html.dark {
+ // brand colors
+ --c-brand: #3aa675;
+ --c-brand-light: #349469;
+
+ // background colors
+ --c-bg: #22272e;
+ --c-bg-light: #2b313a;
+ --c-bg-lighter: #262c34;
+ --c-bg-dark: #343b44;
+ --c-bg-darker: #37404c;
+
+ // text colors
+ --c-text: #adbac7;
+ --c-text-light: #96a7b7;
+ --c-text-lighter: #8b9eb0;
+ --c-text-lightest: #8094a8;
+
+ // border colors
+ --c-border: #3e4c5a;
+ --c-border-dark: #34404c;
+
+ // custom container colors
+ --c-tip: #318a62;
+ --c-warning: #e0ad15;
+ --c-warning-bg: #2d2f2d;
+ --c-warning-bg-light: #423e2a;
+ --c-warning-bg-lighter: #44442f;
+ --c-warning-border-dark: #957c35;
+ --c-warning-details-bg: #39392d;
+ --c-warning-title: #fdca31;
+ --c-warning-text: #d8d96d;
+ --c-warning-text-accent: #ffbf00;
+ --c-warning-text-light: #ddb84b;
+ --c-warning-text-quote: #ccab49;
+ --c-danger: #fc1e38;
+ --c-danger-bg: #39232c;
+ --c-danger-bg-light: #4b2b35;
+ --c-danger-bg-lighter: #553040;
+ --c-danger-border-dark: #a25151;
+ --c-danger-details-bg: #482936;
+ --c-danger-title: #fc2d3b;
+ --c-danger-text: #ea9ca0;
+ --c-danger-text-accent: #fd3636;
+ --c-danger-text-light: #d9777c;
+ --c-danger-text-quote: #d56b6b;
+ --c-details-bg: #323843;
+
+ // badge component colors
+ --c-badge-warning: var(--c-warning);
+ --c-badge-warning-text: #3c2e05;
+ --c-badge-danger: var(--c-danger);
+ --c-badge-danger-text: #401416;
+
+ // code blocks vars
+ --code-hl-bg-color: #363b46;
+}
+
+// plugin-docsearch
+html.dark .DocSearch {
+ --docsearch-logo-color: var(--c-text);
+ --docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
+ --docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
+ 0 2px 2px 0 rgba(3, 4, 9, 0.3);
+ --docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
+ --docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
+ 0 -4px 8px 0 rgba(0, 0, 0, 0.2);
+}
+