+
+
+
diff --git a/assets/404.html-DDgrP_l5.js b/assets/404.html-DDgrP_l5.js
new file mode 100644
index 0000000000..b5f9cd223c
--- /dev/null
+++ b/assets/404.html-DDgrP_l5.js
@@ -0,0 +1 @@
+import{_ as e,o as t,c as s,b as o}from"./app-3y2wReKQ.js";const n={},r=o("p",null,"404 Not Found",-1),a=[r];function c(p,l){return t(),s("div",null,a)}const i=e(n,[["render",c],["__file","404.html.vue"]]),y=JSON.parse('{"path":"/404.html","title":"","lang":"en-US","frontmatter":{"layout":"NotFound","description":"404 Not Found","head":[["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/404.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:description","content":"404 Not Found"}],["meta",{"property":"og:type","content":"website"}],["meta",{"property":"og:locale","content":"en-US"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"WebPage\\",\\"name\\":\\"\\",\\"description\\":\\"404 Not Found\\"}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[],"git":{},"autoDesc":true,"filePathRelative":null}');export{i as comp,y as data};
diff --git a/assets/NpmBadge-D_cZ1c7M.js b/assets/NpmBadge-D_cZ1c7M.js
new file mode 100644
index 0000000000..60244b0bf7
--- /dev/null
+++ b/assets/NpmBadge-D_cZ1c7M.js
@@ -0,0 +1 @@
+import{f as r,g as t,o,c as p,b as g,_ as d}from"./app-3y2wReKQ.js";const l=["href","title"],i=["src","alt"],m=r({__name:"NpmBadge",props:{package:{type:String,required:!0},distTag:{type:String,required:!1,default:"next"}},setup(a){const e=a,n=t(()=>`https://www.npmjs.com/package/${e.package}`),c=t(()=>e.distTag?`${e.package}@${e.distTag}`:e.package),s=t(()=>`https://badgen.net/npm/v/${e.package}/${e.distTag}?label=${encodeURIComponent(c.value)}`);return(u,_)=>(o(),p("a",{class:"npm-badge",href:n.value,title:a.package,target:"_blank",rel:"noopener noreferrer"},[g("img",{src:s.value,alt:a.package},null,8,i)],8,l))}}),k=d(m,[["__scopeId","data-v-c758b2a0"],["__file","NpmBadge.vue"]]);export{k as default};
diff --git a/assets/active-header-links.html-7I9ep0JH.js b/assets/active-header-links.html-7I9ep0JH.js
new file mode 100644
index 0000000000..7be3988a1b
--- /dev/null
+++ b/assets/active-header-links.html-7I9ep0JH.js
@@ -0,0 +1,11 @@
+import{_ as r,r as n,o as p,c,a,b as e,d as s,e as t}from"./app-3y2wReKQ.js";const i={},d=e("h1",{id:"active-header-links",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#active-header-links"},[e("span",null,"active-header-links")])],-1),h=t(`
',4);function C(b,E){const o=n("NpmBadge"),l=n("ExternalLinkIcon");return p(),c("div",null,[d,a(o,{package:"@vuepress/plugin-active-header-links"}),h,e("ul",null,[m,u,e("li",null,[k,y,e("p",null,[s("你通常不需要设置该选项,除非你通过 "),e("a",f,[s("markdown.anchor"),a(l)]),s(" 修改了 "),e("a",g,[s("markdown-it-anchor"),a(l)]),s(" 的 "),_,s(" 选项。")])]),e("li",null,[v,e("ul",null,[e("li",null,[e("a",D,[s("指南 > Markdown > 语法扩展 > 标题锚点"),a(l)])])])])]),x])}const j=r(i,[["render",C],["__file","active-header-links.html.vue"]]),z=JSON.parse('{"path":"/zh/plugins/active-header-links.html","title":"active-header-links","lang":"zh-CN","frontmatter":{"description":"active-header-links","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/active-header-links.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/active-header-links.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"active-header-links"}],["meta",{"property":"og:description","content":"active-header-links"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"active-header-links\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"配置项","slug":"配置项","link":"#配置项","children":[{"level":3,"title":"headerLinkSelector","slug":"headerlinkselector","link":"#headerlinkselector","children":[]},{"level":3,"title":"headerAnchorSelector","slug":"headeranchorselector","link":"#headeranchorselector","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"offset","slug":"offset","link":"#offset","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/active-header-links.md"}');export{j as comp,z as data};
diff --git a/assets/active-header-links.html-C0d8EiS9.js b/assets/active-header-links.html-C0d8EiS9.js
new file mode 100644
index 0000000000..120d960607
--- /dev/null
+++ b/assets/active-header-links.html-C0d8EiS9.js
@@ -0,0 +1,11 @@
+import{_ as r,r as n,o as i,c,a,b as e,d as s,e as l}from"./app-3y2wReKQ.js";const p={},h=e("h1",{id:"active-header-links",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#active-header-links"},[e("span",null,"active-header-links")])],-1),d=l(`
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.
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.
`,8);function u(y,g){const n=a("NpmBadge"),o=a("RouteLink");return p(),r("div",null,[h,s(n,{package:"@vuepress/plugin-append-date"}),e("p",null,[t("该插件会基于 "),s(o,{to:"/zh/plugins/git.html"},{default:c(()=>[t("@vuepress/plugin-git")]),_:1}),t(" 为 frontmatter 追加写作日期。")]),m])}const k=l(d,[["render",u],["__file","append-date.html.vue"]]),f=JSON.parse('{"path":"/zh/plugins/append-date.html","title":"back-to-top","lang":"zh-CN","frontmatter":{"description":"back-to-top","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/append-date.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/append-date.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"back-to-top"}],["meta",{"property":"og:description","content":"back-to-top"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:49:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:49:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"back-to-top\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:49:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"key","slug":"key","link":"#key","children":[]},{"level":3,"title":"format","slug":"format","link":"#format","children":[]}]}],"git":{"updatedTime":1710146995000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/append-date.md"}');export{k as comp,f as data};
diff --git a/assets/append-date.html-DLhGFOdo.js b/assets/append-date.html-DLhGFOdo.js
new file mode 100644
index 0000000000..0895e82113
--- /dev/null
+++ b/assets/append-date.html-DLhGFOdo.js
@@ -0,0 +1,7 @@
+import{_ as p,r as a,o as l,c as r,a as s,b as e,d as t,w as i,e as c}from"./app-3y2wReKQ.js";const d={},u=e("h1",{id:"back-to-top",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#back-to-top"},[e("span",null,"back-to-top")])],-1),m=c(`
`,8);function h(y,g){const o=a("NpmBadge"),n=a("RouteLink");return l(),r("div",null,[u,s(o,{package:"@vuepress/plugin-append-date"}),e("p",null,[t("This plugin will append writing date to frontmatter with "),s(n,{to:"/plugins/git.html"},{default:i(()=>[t("@vuepress/plugin-git")]),_:1}),t(".")]),m])}const f=p(d,[["render",h],["__file","append-date.html.vue"]]),k=JSON.parse('{"path":"/plugins/append-date.html","title":"back-to-top","lang":"en-US","frontmatter":{"description":"back-to-top","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/append-date.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/append-date.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"back-to-top"}],["meta",{"property":"og:description","content":"back-to-top"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:49:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:49:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"back-to-top\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:49:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"key","slug":"key","link":"#key","children":[]},{"level":3,"title":"format","slug":"format","link":"#format","children":[]}]}],"git":{"updatedTime":1710146995000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/append-date.md"}');export{f as comp,k as data};
diff --git a/assets/back-to-top.html-BFyMPlSO.js b/assets/back-to-top.html-BFyMPlSO.js
new file mode 100644
index 0000000000..f67caba14e
--- /dev/null
+++ b/assets/back-to-top.html-BFyMPlSO.js
@@ -0,0 +1,15 @@
+import{_ as a,r as o,o as t,c as l,a as n,b as s,e as p}from"./app-3y2wReKQ.js";const c={},r=s("h1",{id:"back-to-top",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#back-to-top"},[s("span",null,"back-to-top")])],-1),i=p(`
`,13);function d(D,h){const e=o("NpmBadge");return t(),l("div",null,[r,n(e,{package:"@vuepress/plugin-back-to-top"}),i])}const m=a(c,[["render",d],["__file","back-to-top.html.vue"]]),u=JSON.parse('{"path":"/zh/plugins/back-to-top.html","title":"back-to-top","lang":"zh-CN","frontmatter":{"description":"back-to-top","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/back-to-top.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/back-to-top.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"back-to-top"}],["meta",{"property":"og:description","content":"back-to-top"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:33:32.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:33:32.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"back-to-top\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:33:32.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"threshold","slug":"threshold","link":"#threshold","children":[]},{"level":3,"title":"progress","slug":"progress","link":"#progress","children":[]}]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]}],"git":{"updatedTime":1706960012000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/back-to-top.md"}');export{m as comp,u as data};
diff --git a/assets/back-to-top.html-C3gKvy7j.js b/assets/back-to-top.html-C3gKvy7j.js
new file mode 100644
index 0000000000..0f18b7e0d1
--- /dev/null
+++ b/assets/back-to-top.html-C3gKvy7j.js
@@ -0,0 +1,15 @@
+import{_ as a,r as t,o,c as l,a as n,b as s,e as p}from"./app-3y2wReKQ.js";const c={},r=s("h1",{id:"back-to-top",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#back-to-top"},[s("span",null,"back-to-top")])],-1),i=p(`
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.
`,13);function d(h,D){const e=t("NpmBadge");return o(),l("div",null,[r,n(e,{package:"@vuepress/plugin-back-to-top"}),i])}const u=a(c,[["render",d],["__file","back-to-top.html.vue"]]),m=JSON.parse('{"path":"/plugins/back-to-top.html","title":"back-to-top","lang":"en-US","frontmatter":{"description":"back-to-top","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/back-to-top.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/back-to-top.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"back-to-top"}],["meta",{"property":"og:description","content":"back-to-top"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:33:32.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:33:32.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"back-to-top\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:33:32.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"threshold","slug":"threshold","link":"#threshold","children":[]},{"level":3,"title":"progress","slug":"progress","link":"#progress","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1706960012000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/back-to-top.md"}');export{u as comp,m as data};
diff --git a/assets/baidu-analytics.html-4L8a17sa.js b/assets/baidu-analytics.html-4L8a17sa.js
new file mode 100644
index 0000000000..71786d8221
--- /dev/null
+++ b/assets/baidu-analytics.html-4L8a17sa.js
@@ -0,0 +1,11 @@
+import{_ as o,r as n,o as i,c,a,b as e,d as s,e as p}from"./app-3y2wReKQ.js";const r={},d=e("h1",{id:"baidu-analytics",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#baidu-analytics"},[e("span",null,"baidu-analytics")])],-1),h={href:"https://tongji.baidu.com/",target:"_blank",rel:"noopener noreferrer"},u={class:"custom-container tip"},m=e("p",{class:"custom-container-title"},"提示",-1),y={href:"https://tongji.baidu.com/web/help/article?id=324&type=0",target:"_blank",rel:"noopener noreferrer"},_=p(`
Details: The ID of Baidu Analytics, which is the query of hm.js URL.
',3);function f(E,C){const o=n("NpmBadge"),t=n("ExternalLinkIcon");return p(),r("div",null,[d,a(o,{package:"@vuepress/plugin-baidu-analytics"}),e("p",null,[s("Integrate "),e("a",u,[s("Baidu Analytics"),a(t)]),s(" into VuePress.")]),e("div",h,[y,e("p",null,[s("Do not enable "),e("a",m,[s("SPA mode in Baidu Analytics"),a(t)]),s(". The plugin will report page view events correctly.")])]),g,e("p",null,[s("Besides, a global "),D,s(" array is available on the "),b,s(" object, and you can use it for "),e("a",_,[s("custom events reporting"),a(t)]),s(".")]),v])}const x=i(c,[["render",f],["__file","baidu-analytics.html.vue"]]),A=JSON.parse('{"path":"/plugins/baidu-analytics.html","title":"baidu-analytics","lang":"en-US","frontmatter":{"description":"baidu-analytics","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/baidu-analytics.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/baidu-analytics.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"baidu-analytics"}],["meta",{"property":"og:description","content":"baidu-analytics"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-25T07:11:23.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-25T07:11:23.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"baidu-analytics\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-25T07:11:23.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[{"level":3,"title":"Reporting Events","slug":"reporting-events","link":"#reporting-events","children":[]}]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"id","slug":"id","link":"#id","children":[]}]}],"git":{"updatedTime":1711350683000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2},{"name":"Zihan Hu","email":"hu-zihan@foxmail.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/baidu-analytics.md"}');export{x as comp,A as data};
diff --git a/assets/bundler.html-B13T36Ue.js b/assets/bundler.html-B13T36Ue.js
new file mode 100644
index 0000000000..4e2e74b3b3
--- /dev/null
+++ b/assets/bundler.html-B13T36Ue.js
@@ -0,0 +1,176 @@
+import{_ as s,o as n,c as a,e as l}from"./app-3y2wReKQ.js";const e={},p=l(`
import { configWebpack } from '@vuepress/helper'
+
+configWebpack(bundlerOptions, app, (config, isServer, isBuild) => {
+ // do some customize here
+})
+
`,21),o=[p];function t(c,r){return n(),a("div",null,o)}const D=s(e,[["render",t],["__file","bundler.html.vue"]]),d=JSON.parse('{"path":"/tools/helper/node/bundler.html","title":"Bundler Related","lang":"en-US","frontmatter":{"description":"Bundler Related Bundler function is for appending or modifying bundler options in theme and plugins. All functions should be called in extendsBundlerOptions lifecycle hook. TIP ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/tools/helper/node/bundler.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Bundler Related"}],["meta",{"property":"og:description","content":"Bundler Related Bundler function is for appending or modifying bundler options in theme and plugins. All functions should be called in extendsBundlerOptions lifecycle hook. TIP ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:34:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:34:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Bundler Related\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:34:35.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Common methods","slug":"common-methods","link":"#common-methods","children":[{"level":3,"title":"getBundlerName","slug":"getbundlername","link":"#getbundlername","children":[]},{"level":3,"title":"addCustomElement","slug":"addcustomelement","link":"#addcustomelement","children":[]},{"level":3,"title":"customizeDevServer","slug":"customizedevserver","link":"#customizedevserver","children":[]}]},{"level":2,"title":"Vite Related","slug":"vite-related","link":"#vite-related","children":[]},{"level":2,"title":"Webpack Related","slug":"webpack-related","link":"#webpack-related","children":[]}],"git":{"updatedTime":1706960075000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"tools/helper/node/bundler.md"}');export{D as comp,d as data};
diff --git a/assets/bundler.html-ZSpuLzXC.js b/assets/bundler.html-ZSpuLzXC.js
new file mode 100644
index 0000000000..45aaa4b30a
--- /dev/null
+++ b/assets/bundler.html-ZSpuLzXC.js
@@ -0,0 +1,179 @@
+import{_ as s,o as n,c as a,e as l}from"./app-3y2wReKQ.js";const p={},e=l(`
The plugin will sort pages by order in the following way:
// order positive numbers from small to large
+Project with order 1
+Project with order 2
+...
+Project with order 10
+...
+// Project without order
+Project without order
+Project without order
+...
+// order negative numbers from small to large
+Project with order -10
+// ...
+Project with order -2
+Project with order -1
+
`,20);function k(_,F){const t=l("NpmBadge"),p=l("ExternalLinkIcon"),o=l("Badge");return c(),r("div",null,[D,a(t,{package:"@vuepress/plugin-catalog"}),u,s("p",null,[n("You can then import "),g,n(" from "),y,n(" and use it in "),s("a",m,[n("client config file"),a(p)]),n(" to extract catalog info from meta.")]),h,s("h3",C,[s("a",v,[s("span",null,[n("level "),a(o,{text:"Built-in component only"})])])]),f,s("h3",b,[s("a",E,[s("span",null,[n("index "),a(o,{text:"Built-in component only"})])])]),x])}const B=i(d,[["render",k],["__file","catalog.html.vue"]]),P=JSON.parse('{"path":"/plugins/catalog.html","title":"catalog","lang":"en-US","frontmatter":{"description":"catalog","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/catalog.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/catalog.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"catalog"}],["meta",{"property":"og:description","content":"catalog"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-27T16:53:41.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-27T16:53:41.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"catalog\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-27T16:53:41.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"level","slug":"level","link":"#level","children":[]},{"level":3,"title":"index","slug":"index","link":"#index","children":[]},{"level":3,"title":"frontmatter","slug":"frontmatter","link":"#frontmatter","children":[]},{"level":3,"title":"exclude","slug":"exclude","link":"#exclude","children":[]},{"level":3,"title":"component","slug":"component","link":"#component","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Client options","slug":"client-options","link":"#client-options","children":[{"level":3,"title":"defineCatalogInfoGetter","slug":"definecataloginfogetter","link":"#definecataloginfogetter","children":[]}]},{"level":2,"title":"Components","slug":"components","link":"#components","children":[{"level":3,"title":"Catalog","slug":"catalog-1","link":"#catalog-1","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1709052821000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"plugins/catalog.md"}');export{B as comp,P as data};
diff --git a/assets/channel.html-BGBDBbnO.js b/assets/channel.html-BGBDBbnO.js
new file mode 100644
index 0000000000..cb2078daa2
--- /dev/null
+++ b/assets/channel.html-BGBDBbnO.js
@@ -0,0 +1,15 @@
+import{_ as a,r as s,o as t,c as i,b as e,d as n,a as c,e as o}from"./app-3y2wReKQ.js";const r={},p=o(`
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 y(f,b){const l=s("ExternalLinkIcon");return i(),c("div",null,[h,e("details",p,[d,e("div",u,[m,e("p",null,[n("For details, see "),e("a",g,[n("Websub"),o(l)]),n(".")])])])])}const D=t(r,[["render",y],["__file","channel.html.vue"]]),k=JSON.parse('{"path":"/plugins/feed/channel.html","title":"Channel Config","lang":"en-US","frontmatter":{"description":"Channel Config The channel plugin option is used to config the feed channel. channel.title Type: string Default: SiteConfig.title Channel title channel.link Type: string Default...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/channel.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/channel.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Channel Config"}],["meta",{"property":"og:description","content":"Channel Config The channel plugin option is used to config the feed channel. channel.title Type: string Default: SiteConfig.title Channel title channel.link Type: string Default..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Channel Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"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}]},"autoDesc":true,"filePathRelative":"plugins/feed/channel.md"}');export{D as comp,k as data};
diff --git a/assets/client.html-BFEBU_em.js b/assets/client.html-BFEBU_em.js
new file mode 100644
index 0000000000..80f06aff67
--- /dev/null
+++ b/assets/client.html-BFEBU_em.js
@@ -0,0 +1,22 @@
+import{_ as s,o as e,c as a,e as l}from"./app-3y2wReKQ.js";const n={},o=l(`
`,11),t=[o];function p(c,r){return e(),a("div",null,t)}const d=s(n,[["render",p],["__file","client.html.vue"]]),y=JSON.parse('{"path":"/tools/helper/client.html","title":"Client Related","lang":"en-US","frontmatter":{"description":"Client Related Composables APIs hasGlobalComponent Check whether a component is registered globally. TIP Local import of the component does not affect the result. When calling o...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/tools/helper/client.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/tools/helper/client.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Client Related"}],["meta",{"property":"og:description","content":"Client Related Composables APIs hasGlobalComponent Check whether a component is registered globally. TIP Local import of the component does not affect the result. When calling o..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:34:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:34:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Client Related\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:34:35.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Composables APIs","slug":"composables-apis","link":"#composables-apis","children":[{"level":3,"title":"hasGlobalComponent","slug":"hasglobalcomponent","link":"#hasglobalcomponent","children":[]},{"level":3,"title":"useLocaleConfig","slug":"uselocaleconfig","link":"#uselocaleconfig","children":[]}]}],"git":{"updatedTime":1706960075000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"tools/helper/client.md"}');export{d as comp,y as data};
diff --git a/assets/client.html-Bdon6fq5.js b/assets/client.html-Bdon6fq5.js
new file mode 100644
index 0000000000..49f43b9fa9
--- /dev/null
+++ b/assets/client.html-Bdon6fq5.js
@@ -0,0 +1,22 @@
+import{_ as s,o as a,c as e,e as n}from"./app-3y2wReKQ.js";const l={},o=n(`
`,7),_=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")]),e(`
+`),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"}},"yarn"),s("span",{style:{color:"#CE9178"}}," install")]),e(`
+`),s("span",{class:"line"})])])],-1),f=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")]),e(`
+`),s("span",{class:"line"})])])],-1),k={class:"custom-container warning"},x=s("p",{class:"custom-container-title"},"WARNING",-1),q=s("p",null,[e("You must add an empty line between the starting tag of "),s("code",null,""),e(" and the code fence, otherwise the code fence will not be parsed correctly by Markdown.")],-1),G=s("p",null,"All content must be valid Markdown first, and then a Vue SFC.",-1),B={href:"https://v2.vuepress.vuejs.org/advanced/cookbook/markdown-and-vue-sfc.html",target:"_blank",rel:"noopener noreferrer"};function F(w,I){const c=l("NpmBadge"),t=l("Badge"),o=l("CodeGroupItem"),i=l("CodeGroup"),r=l("ExternalLinkIcon"),d=l("RouteLink");return m(),y("div",null,[h,n(c,{package:"@vuepress/theme-default"}),s("h2",v,[s("a",C,[s("span",null,[e("Badge "),n(t,{text:"badge"})])])]),g,s("ul",null,[s("li",null,[e("VuePress - "),n(t,{type:"tip",text:"v2",vertical:"top"})]),s("li",null,[e("VuePress - "),n(t,{type:"warning",text:"v2",vertical:"middle"})]),s("li",null,[e("VuePress - "),n(t,{type:"danger",text:"v2",vertical:"bottom"})])]),b,n(i,null,{default:a(()=>[n(o,{title:"pnpm"},{default:a(()=>[_]),_:1}),n(o,{title:"yarn"},{default:a(()=>[E]),_:1}),n(o,{title:"npm",active:""},{default:a(()=>[f]),_:1})]),_:1}),s("div",k,[x,q,G,s("p",null,[e("Learn more: "),s("a",B,[e("Cookbook > Markdown and Vue SFC"),n(r)])]),s("p",null,[e("Alternatively, you can use the "),n(d,{to:"/themes/default/markdown.html#custom-containers"},{default:a(()=>[e("custom containers")]),_:1}),e(".")])])])}const P=u(D,[["render",F],["__file","components.html.vue"]]),A=JSON.parse('{"path":"/themes/default/components.html","title":"Built-in Components","lang":"en-US","frontmatter":{"description":"Built-in Components","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/components.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/components.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Built-in Components"}],["meta",{"property":"og:description","content":"Built-in Components"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T14:33:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T14:33:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Built-in Components\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T14:33:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"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}]},"autoDesc":true,"filePathRelative":"themes/default/components.md"}');export{P as comp,A as data};
diff --git a/assets/config.html-BZsXc2dd.js b/assets/config.html-BZsXc2dd.js
new file mode 100644
index 0000000000..032a0e8731
--- /dev/null
+++ b/assets/config.html-BZsXc2dd.js
@@ -0,0 +1 @@
+import{_ as i,r as s,o as p,c as n,b as e,d as t,a as o,w as r,e as l}from"./app-3y2wReKQ.js";const c={},d=l('
// 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.
',29),h=e("div",{class:"custom-container tip"},[e("p",{class:"custom-container-title"},"The plugin has a built-in getter, only set this if you want full control of feed generation.")],-1),m=e("h2",{id:"locales",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#locales"},[e("span",null,"locales")])],-1),D=e("ul",null,[e("li",null,[s("Type: "),e("code",null,"Record")])],-1),f=e("p",null,"You can use it to specific options for each locale.",-1),y=e("p",null,[s("Any options above are supported except "),e("code",null,"hostname"),s(".")],-1);function g(v,C){const l=p("RouteLink");return i(),r("div",null,[d,e("p",null,[s("For available options, please see "),a(l,{to:"/plugins/feed/channel.html"},{default:t(()=>[s("Config → Channel")]),_:1})]),u,e("p",null,[s("Feed generation controller, see "),a(l,{to:"/plugins/feed/getter.html"},{default:t(()=>[s("Feed Getter")]),_:1}),s(".")]),h,m,D,f,y])}const b=o(c,[["render",g],["__file","config.html.vue"]]),E=JSON.parse('{"path":"/plugins/feed/config.html","title":"Plugin Config","lang":"en-US","frontmatter":{"description":"Plugin Config hostname Type: string Required: Yes The domain name of the deployment site. atom Type: boolean Default: false Whether to output Atom syntax files. json Type: boole...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Plugin Config"}],["meta",{"property":"og:description","content":"Plugin Config hostname Type: string Required: Yes The domain name of the deployment site. atom Type: boolean Default: false Whether to output Atom syntax files. json Type: boole..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-02T06:14:30.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-02T06:14:30.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Plugin Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-02T06:14:30.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"hostname","slug":"hostname","link":"#hostname","children":[]},{"level":2,"title":"atom","slug":"atom","link":"#atom","children":[]},{"level":2,"title":"json","slug":"json","link":"#json","children":[]},{"level":2,"title":"rss","slug":"rss","link":"#rss","children":[]},{"level":2,"title":"image","slug":"image","link":"#image","children":[]},{"level":2,"title":"icon","slug":"icon","link":"#icon","children":[]},{"level":2,"title":"count","slug":"count","link":"#count","children":[]},{"level":2,"title":"preservedElements","slug":"preservedelements","link":"#preservedelements","children":[]},{"level":2,"title":"filter","slug":"filter","link":"#filter","children":[]},{"level":2,"title":"sorter","slug":"sorter","link":"#sorter","children":[]},{"level":2,"title":"channel","slug":"channel","link":"#channel","children":[]},{"level":2,"title":"devServer","slug":"devserver","link":"#devserver","children":[]},{"level":2,"title":"devHostname","slug":"devhostname","link":"#devhostname","children":[]},{"level":2,"title":"atomOutputFilename","slug":"atomoutputfilename","link":"#atomoutputfilename","children":[]},{"level":2,"title":"atomXslTemplate","slug":"atomxsltemplate","link":"#atomxsltemplate","children":[]},{"level":2,"title":"atomXslFilename","slug":"atomxslfilename","link":"#atomxslfilename","children":[]},{"level":2,"title":"jsonOutputFilename","slug":"jsonoutputfilename","link":"#jsonoutputfilename","children":[]},{"level":2,"title":"rssOutputFilename","slug":"rssoutputfilename","link":"#rssoutputfilename","children":[]},{"level":2,"title":"rssXslTemplate","slug":"rssxsltemplate","link":"#rssxsltemplate","children":[]},{"level":2,"title":"rssXslFilename","slug":"rssxslfilename","link":"#rssxslfilename","children":[]},{"level":2,"title":"getter","slug":"getter","link":"#getter","children":[]},{"level":2,"title":"locales","slug":"locales","link":"#locales","children":[]}],"git":{"updatedTime":1706854470000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"plugins/feed/config.md"}');export{b as comp,E as data};
diff --git a/assets/config.html-C41O55i_.js b/assets/config.html-C41O55i_.js
new file mode 100644
index 0000000000..65f95b475e
--- /dev/null
+++ b/assets/config.html-C41O55i_.js
@@ -0,0 +1,140 @@
+import{_ as o,r as p,o as i,c as t,b as s,d as n,a as e,e as l}from"./app-3y2wReKQ.js";const c={},r=l('
`,2),m=s("p",null,"Reference:",-1),y={href:"https://waline.js.org/en/guide/features/emoji.html",target:"_blank",rel:"noopener noreferrer"},D=s("li",null,[s("p",null,"Details: Emoji settings.")],-1),h=s("h3",{id:"dark",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#dark"},[s("span",null,"dark")])],-1),g=s("li",null,[s("p",null,[e("Type: "),s("code",null,"string | boolean")])],-1),v=s("li",null,[s("p",null,[e("Default: "),s("code",null,"false")])],-1),C=s("p",null,"Reference:",-1),b={href:"https://waline.js.org/en/guide/features/style.html",target:"_blank",rel:"noopener noreferrer"},f=s("li",null,[s("p",null,"Details:"),s("p",null,"Darkmode support"),s("ul",null,[s("li",null,"Setting a boolean will set the dark mode according to its value."),s("li",null,[e("Set it to "),s("code",null,"'auto'"),e(" will display darkmode due to device settings.")]),s("li",null,"Filling in a CSS selector will enable darkmode only when the selector match waline ancestor nodes.")])],-1),E=l('
type WalineImageUploader = (image: File) => Promise<string>
+
`,1),x=s("p",null,"Reference:",-1),w={href:"https://waline.js.org/en/cookbook/customize/upload-image.html",target:"_blank",rel:"noopener noreferrer"},B=s("li",null,[s("p",null,"Details:"),s("p",null,[e("Custom image upload method. The default behavior is to embed images Base 64 encoded, you can set this to "),s("code",null,"false"),e(" to disable image uploading.")]),s("p",null,"The function should receive an image object and return a Promise that provides the image address.")],-1),j={id:"highlighter",tabindex:"-1"},T={class:"header-anchor",href:"#highlighter"},W=l(`
Type: WalineHighlighter | false
type WalineHighlighter = (code: string, lang: string) => string
+
`,1),F=s("p",null,"Reference:",-1),R={href:"https://waline.js.org/en/cookbook/customize/highlighter.html",target:"_blank",rel:"noopener noreferrer"},S=s("li",null,[s("p",null,"Details:"),s("p",null,[s("strong",null,"Code highlighting"),e(", use "),s("code",null,"hanabi"),e(" by default. The function passes in original content of code block and language of the code block. You should return a string directly.")]),s("p",null,[e("You can pass in a code highlighter of your own, or set to "),s("code",null,"false"),e(" to disable code highlighting.")])],-1),P={id:"texrenderer",tabindex:"-1"},z={class:"header-anchor",href:"#texrenderer"},I=l(`
Type: WalineTexRenderer | false
type WalineTexRenderer = (blockMode: boolean, tex: string) => string
+
`,1),L=s("p",null,"Reference:",-1),O={href:"https://waline.js.org/en/cookbook/customize/tex-renderer.html",target:"_blank",rel:"noopener noreferrer"},U={href:"https://www.mathjax.org/",target:"_blank",rel:"noopener noreferrer"},V={href:"https://katex.org/",target:"_blank",rel:"noopener noreferrer"},q=s("li",null,[s("p",null,"Details:"),s("p",null,"Customize TeX rendering, the default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters, the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content, and return a HTML string as render result."),s("p",null,[e("You can import TeX renderer to provide preview feature. We recommend you to use Katex or MathJax, or you can set to "),s("code",null,"false"),e(" to disable parsing TeX.")])],-1),Y={id:"search",tabindex:"-1"},N={class:"header-anchor",href:"#search"},H=l(`
Type: WalineSearchOptions | false
interface WalineSearchImageData extends Record<string, unknown> {
+ /**
+ * Image link
+ */
+ src: string
+
+ /**
+ * Image title
+ *
+ * @description Used for alt attribute of image
+ */
+ title?: string
+
+ /**
+ * Image preview link
+ *
+ * @description For better loading performance, we will use this thumbnail first in the list
+ *
+ * @default src
+ */
+ preview?: string
+}
+
+type WalineSearchResult = WalineSearchImageData[]
+
+interface WalineSearchOptions {
+ /**
+ * Search action
+ */
+ search: (word: string) => Promise<WalineSearchResult>
+
+ /**
+ * Default result when opening list
+ *
+ * @default () => search('')
+ */
+ default?: () => Promise<WalineSearchResult>
+
+ /**
+ * Fetch more action
+ *
+ * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling
+ *
+ * @default (word) => search(word)
+ */
+ more?: (word: string, currentCount: number) => Promise<WalineSearchResult>
+}
+
Details: Customize search features, you can disable search function by setting it to false.
Add emoji interaction function to the article, set it to true to provide the default emoji, you can also customize the emoji image by setting the emoji url array, and supports a maximum of 8 emojis.
`,5),M={id:"metaicon",tabindex:"-1"},X={class:"header-anchor",href:"#metaicon"},K=s("ul",null,[s("li",null,[e("Type: "),s("code",null,"boolean")]),s("li",null,[e("Default: "),s("code",null,"true")]),s("li",null,"Details: Whether import meta icon.")],-1),J={id:"locales",tabindex:"-1"},Z={class:"header-anchor",href:"#locales"},G=l(`
',3),u=s("li",null,[s("p",null,[n("Type: "),s("code",null,"(page: Page) => Record")])],-1),y=s("li",null,[s("p",null,"Required: No")],-1),D=s("p",null,"Reference:",-1),g=s("li",null,[s("p",null,"Details:"),s("p",null,"Function getting article info."),s("p",null,"Article info will be injected in route meta so that they will be available later in client composables.")],-1),m=s("h3",{id:"filter",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#filter"},[s("span",null,"filter")])],-1),v=s("li",null,[s("p",null,[n("Type: "),s("code",null,"(page: Page) => boolean")])],-1),h=s("li",null,[s("p",null,[n("Default: "),s("code",null,"(page) => Boolean(page.filePathRelative) && !page.frontmatter.home")])],-1),C=s("p",null,"Reference:",-1),b=s("li",null,[s("p",null,"Details:"),s("p",null,"Page filter, determine whether a page should be included."),s("p",null,"By default, all the pages generated from Markdown files but not homepage will be included as articles.")],-1),f=s("h3",{id:"category",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#category"},[s("span",null,"category")])],-1),E=s("li",null,[n("Type: "),s("code",null,"BlogCategoryOptions[]")],-1),B=s("li",null,"Required: No",-1),A=s("li",null,[n("Details: Blog category config, see "),s("a",{href:"#blog-category-config"},"Blog Category Config")],-1),_=s("h3",{id:"type",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#type"},[s("span",null,"type")])],-1),x=s("li",null,[n("Type: "),s("code",null,"BlogTypeOptions[]")],-1),k=s("li",null,"Required: No",-1),F=s("li",null,[n("Details: Blog type config, see "),s("a",{href:"#blog-type-config"},"Blog Type Config")],-1),w=s("h3",{id:"slugify",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#slugify"},[s("span",null,"slugify")])],-1),T=s("ul",null,[s("li",null,[n("Type: "),s("code",null,"(name: string) => string")]),s("li",null,[n("Default: "),s("code",null,`(name) => name.replace(/ _/g, '-').replace(/[:?*|\\\\/<>]/g, "").toLowerCase()`)]),s("li",null,"Details: Slugify function, used to convert key name which they are register in routes.")],-1),R=s("h3",{id:"excerpt",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#excerpt"},[s("span",null,"excerpt")])],-1),P=s("li",null,[n("Type: "),s("code",null,"boolean")],-1),I=s("li",null,[n("Default: "),s("code",null,"true")],-1),q=s("li",null,"Details: Whether generate excerpt for page.",-1),G=s("h3",{id:"excerptseparator",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#excerptseparator"},[s("span",null,"excerptSeparator")])],-1),S=s("li",null,[n("Type: "),s("code",null,"string")],-1),j=s("li",null,[n("Default: "),s("code",null,"")],-1),N=s("li",null,"Details: Separator used to split excerpt from page content.",-1),L=s("h3",{id:"excerptlength",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#excerptlength"},[s("span",null,"excerptLength")])],-1),O=s("li",null,[s("p",null,[n("Type: "),s("code",null,"number")])],-1),z=s("li",null,[s("p",null,[n("Default: "),s("code",null,"300")])],-1),V=s("p",null,"Reference:",-1),U=s("li",null,[s("p",null,"Details:"),s("p",null,"Length of excerpt when auto generating."),s("div",{class:"custom-container tip"},[s("p",{class:"custom-container-title"},"TIP"),s("p",null,"Excerpt length will be the minimal possible length reaching this value."),s("p",null,[n("You can set it to "),s("code",null,"0"),n(" to disable auto excerpt generation.")])])],-1),M=s("h3",{id:"excerptfilter",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#excerptfilter"},[s("span",null,"excerptFilter")])],-1),W=s("li",null,[s("p",null,[n("Type: "),s("code",null,"(page: Page) => boolean")])],-1),Y=s("li",null,[s("p",null,[n("Default: "),s("code",null,"filter"),n(" option")])],-1),Z=s("p",null,"Reference:",-1),J=s("li",null,[s("p",null,"Details:"),s("p",null,"Page filter, determine whether the plugin should generate excerpt for it."),s("div",{class:"custom-container tip"},[s("p",{class:"custom-container-title"},"TIP"),s("p",null,[n("You should use this to skip pages that you don't need to generate excerpt for. E.g.: If users set "),s("code",null,"excerpt"),n(" or "),s("code",null,"description"),n(" in frontmatter, you may want to use them directly.")])])],-1),H=s("h3",{id:"iscustomelement",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#iscustomelement"},[s("span",null,"isCustomElement")])],-1),K=s("li",null,[s("p",null,[n("Type: "),s("code",null,"(tagName: string) => boolean")])],-1),Q=s("li",null,[s("p",null,[n("Default: "),s("code",null,"() => false")])],-1),X=s("p",null,"Reference:",-1),$=s("li",null,[s("p",null,"Details:"),s("p",null,"Tags which is considered as custom elements."),s("p",null,"This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.")],-1),ss=o(`
It's disabled by default because it does have performance impact in sites with a lot of categories and types. And it can slow down hotReload speed when editing Markdown.
If users are adding or organizing your categories or tags, you may tell them to enable this, for the rest it's better to keep it disabled.
Also, you can try to detect number of pages in users project and decide whether to enable it.
"disabled": Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
"available": Only display update popup when the new service worker is available
"hint": Display a hint to let user choose to refresh immediately
This is helpful when you want users to see new docs immediately.
TIP
If users choose to refresh, the current service worker will be unregister, and request will start coming to web. Later the new service worker will start installing and control current page after installed.
"force": unregister current service worker immediately then refresh to get new content
DANGER
Although this ensures users are viewing the latest content, it may affect viewing experiences.
TIP
How docs are updated is controlled by a previous version, so the current option only effect next update from this version.
`,5),b=s("p",null,"Details:",-1),f=s("p",null,"Returns the event emitter of this plugin.",-1),E={href:"https://github.com/yyx990803/register-service-worker",target:"_blank",rel:"noopener noreferrer"},w=s("li",null,[s("p",null,"Example:")],-1),k=e(`
`,22);function A(x,F){const a=i("ExternalLinkIcon");return p(),t("div",null,[c,s("ul",null,[d,s("li",null,[D,s("ul",null,[s("li",null,[s("a",u,[n("MDN Web Docs: Web App Manifest"),l(a)])]),s("li",null,[s("a",y,[n("W3C: Web App Manifest"),l(a)])])])])]),v,s("ul",null,[s("li",null,[h,s("p",null,[n("Options passed to "),m,n(", for details, see "),s("a",g,[n("Workbox documentation"),l(a)])])])]),C,s("ul",null,[s("li",null,[b,f,s("p",null,[n("You can add listener function to events that provided by "),s("a",E,[n("register-service-worker"),l(a)]),n(".")])]),w]),k])}const _=o(r,[["render",A],["__file","config.html.vue"]]),T=JSON.parse('{"path":"/plugins/pwa/config.html","title":"Config","lang":"en-US","frontmatter":{"description":"Config Options showInstall Type: boolean Default: false Details: Whether display install button when Service Worker is first registered successfully. manifest Type: AppManifest ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/pwa/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/pwa/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Config"}],["meta",{"property":"og:description","content":"Config Options showInstall Type: boolean Default: false Details: Whether display install button when Service Worker is first registered successfully. manifest Type: AppManifest ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-20T02:57:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-20T02:57:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-20T02:57:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"showInstall","slug":"showinstall","link":"#showinstall","children":[]},{"level":3,"title":"manifest","slug":"manifest","link":"#manifest","children":[]},{"level":3,"title":"favicon","slug":"favicon","link":"#favicon","children":[]},{"level":3,"title":"themeColor","slug":"themecolor","link":"#themecolor","children":[]},{"level":3,"title":"cacheHTML","slug":"cachehtml","link":"#cachehtml","children":[]},{"level":3,"title":"cacheImage","slug":"cacheimage","link":"#cacheimage","children":[]},{"level":3,"title":"maxSize","slug":"maxsize","link":"#maxsize","children":[]},{"level":3,"title":"maxImageSize","slug":"maximagesize","link":"#maximagesize","children":[]},{"level":3,"title":"update","slug":"update","link":"#update","children":[]},{"level":3,"title":"apple","slug":"apple","link":"#apple","children":[]},{"level":3,"title":"msTile","slug":"mstile","link":"#mstile","children":[]},{"level":3,"title":"foundComponent","slug":"foundcomponent","link":"#foundcomponent","children":[]},{"level":3,"title":"readyComponent","slug":"readycomponent","link":"#readycomponent","children":[]},{"level":3,"title":"appendBase","slug":"appendbase","link":"#appendbase","children":[]},{"level":3,"title":"generateSwConfig","slug":"generateswconfig","link":"#generateswconfig","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Composition API","slug":"composition-api","link":"#composition-api","children":[{"level":3,"title":"usePwaEvent","slug":"usepwaevent","link":"#usepwaevent","children":[]}]},{"level":2,"title":"Utilities","slug":"utilities","link":"#utilities","children":[{"level":3,"title":"forceUpdate","slug":"forceupdate","link":"#forceupdate","children":[]},{"level":3,"title":"registerSW","slug":"registersw","link":"#registersw","children":[]},{"level":3,"title":"skipWaiting","slug":"skipwaiting","link":"#skipwaiting","children":[]},{"level":3,"title":"unregisterSW","slug":"unregistersw","link":"#unregistersw","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1708397875000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/pwa/config.md"}');export{_ as comp,T as data};
diff --git a/assets/config.html-DXtp0w07.js b/assets/config.html-DXtp0w07.js
new file mode 100644
index 0000000000..2d63b63c9d
--- /dev/null
+++ b/assets/config.html-DXtp0w07.js
@@ -0,0 +1,141 @@
+import{_ as p,r as i,o as c,c as r,b as s,d as e,a as l,w as o,e as n}from"./app-3y2wReKQ.js";const d={},u=n('
',5),h=s("li",null,[s("p",null,[e("Type: "),s("code",null,"{ [path: string]: Partial }")])],-1),D=s("li",null,[s("p",null,[e("Default: "),s("code",null,"{}")])],-1),m=s("p",null,"Details:",-1),y=s("p",null,"Specify locales for i18n support.",-1),b=s("p",null,[e("All the options inside the "),s("a",{href:"#locale-config"},"Locale Config"),e(" section can be used in locales.")],-1),v=s("code",null,"locales",-1),f=s("p",null,"Also see:",-1),g={href:"https://v2.vuepress.vuejs.org/guide/i18n.html",target:"_blank",rel:"noopener noreferrer"},C=n('
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:
A NavbarItem object should have a text field and a link field, could have an optional activeMatch field.
A NavbarGroup object should have a text field and a children field. The children field should be a navbar array, too.
A string should be the path to the target page file. It will be converted to a NavbarItem object, using the page title as text, and the page route path as link.
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',
+ }),
+}
+
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:
A 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.
A string should be the path to the target page file. It will be converted to a 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:
The key should be the path prefix.
The value should be a sidebar array or set to 'heading' to automatically generate the sidebar from the page headers for just the corresponding path.
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
Set to 0 to disable all levels of headers.
Set to 1 to include <h2> headers.
Set to 2 to include <h2> and <h3> headers.
...
",3),Z={href:"https://v2.vuepress.vuejs.org/reference/config.html#markdown-headers",target:"_blank",rel:"noopener noreferrer"},J=s("p",null,[e("The default value of "),s("code",null,"markdown.headers.level"),e(" is "),s("code",null,"[2, 3]"),e(", so the default max value of "),s("code",null,"sidebarDepth"),e(" is "),s("code",null,"2"),e(".")],-1),W=s("h3",{id:"editlink",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#editlink"},[s("span",null,"editLink")])],-1),q=s("li",null,[s("p",null,[e("Type: "),s("code",null,"boolean")])],-1),K=s("li",null,[s("p",null,[e("Default: "),s("code",null,"true")])],-1),Q=s("p",null,"Details:",-1),X=s("p",null,[e("Enable the "),s("em",null,"edit this page"),e(" link or not.")],-1),$=n(`
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.
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.
`,11),ss=s("li",null,[s("p",null,[e("Type: "),s("code",null,"boolean")])],-1),es=s("li",null,[s("p",null,[e("Default: "),s("code",null,"true")])],-1),ls=s("p",null,"Details:",-1),ns=s("p",null,[e("Enable the "),s("em",null,"last updated timestamp"),e(" or not.")],-1),as=s("code",null,"false",-1),os=s("h3",{id:"contributors",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#contributors"},[s("span",null,"contributors")])],-1),ts=s("li",null,[s("p",null,[e("Type: "),s("code",null,"boolean")])],-1),is=s("li",null,[s("p",null,[e("Default: "),s("code",null,"true")])],-1),ps=s("p",null,"Details:",-1),cs=s("p",null,[e("Enable the "),s("em",null,"contributors list"),e(" or not.")],-1),rs=s("code",null,"false",-1);function ds(us,hs){const a=i("RouteLink"),t=i("ExternalLinkIcon");return c(),r("div",null,[u,s("ul",null,[h,D,s("li",null,[m,y,b,s("p",null,[e("This option will only take effect in default theme, so don't confuse with "),v,e(" in "),l(a,{to:"/themes/default/config.html#locales"},{default:o(()=>[e("Site Config")]),_:1}),e(".")])]),s("li",null,[f,s("ul",null,[s("li",null,[s("a",g,[e("Guide > I18n"),l(t)])])])])]),C,s("ul",null,[E,_,s("li",null,[k,x,s("p",null,[e("If set to "),T,e(", the initial color mode will be automatically set according to "),s("a",w,[e("prefers-color-scheme"),l(t)]),e(".")])]),F]),A,s("ul",null,[S,s("li",null,[j,s("ul",null,[I,s("li",null,[l(a,{to:"/themes/default/locale.html#togglecolormode"},{default:o(()=>[e("Default Theme > Locale Config > toggleColorMode")]),_:1})])])])]),L,s("ul",null,[s("li",null,[e("Also see: "),s("ul",null,[s("li",null,[s("a",N,[e("Guide > Assets > Public Files"),l(t)])])])])]),B,s("ul",null,[G,M,s("li",null,[P,R,s("p",null,[e("You can override this global option via "),l(a,{to:"/themes/default/frontmatter.html#sidebar"},{default:o(()=>[e("sidebar")]),_:1}),e(" frontmatter in your pages.")]),V]),U]),Y,s("ul",null,[H,z,s("li",null,[O,s("p",null,[e("The max value depends on which levels of headers you have extracted via "),s("a",Z,[e("markdown.headers.level"),l(t)]),e(".")]),J,s("p",null,[e("You can override this global option via "),l(a,{to:"/themes/default/frontmatter.html#sidebardepth"},{default:o(()=>[e("sidebarDepth")]),_:1}),e(" frontmatter in your pages.")])])]),W,s("ul",null,[q,K,s("li",null,[Q,X,s("p",null,[e("You can override this global option via "),l(a,{to:"/themes/default/frontmatter.html#editlink"},{default:o(()=>[e("editLink")]),_:1}),e(" frontmatter in your pages.")])])]),$,s("ul",null,[ss,es,s("li",null,[ls,ns,s("p",null,[e("You can override this global option via "),l(a,{to:"/themes/default/frontmatter.html#lastupdated"},{default:o(()=>[e("lastUpdated")]),_:1}),e(" frontmatter in your pages. Notice that if you have already set this option to "),as,e(", this feature will be disabled totally and could not be enabled in locales nor page frontmatter.")])])]),os,s("ul",null,[ts,is,s("li",null,[ps,cs,s("p",null,[e("You can override this global option via "),l(a,{to:"/themes/default/frontmatter.html#contributors"},{default:o(()=>[e("contributors")]),_:1}),e(" frontmatter in your pages. Notice that if you have already set this option to "),rs,e(", this feature will be disabled totally and could not be enabled in locales nor page frontmatter.")])])])])}const ms=p(d,[["render",ds],["__file","config.html.vue"]]),ys=JSON.parse('{"path":"/themes/default/config.html","title":"Config","lang":"en-US","frontmatter":{"description":"Config Basic Config hostname Type: string Details: Hostname to be deployed, e.g.: https://example.com locales Type: { [path: string]: Partial } Default: ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Config"}],["meta",{"property":"og:description","content":"Config Basic Config hostname Type: string Details: Hostname to be deployed, e.g.: https://example.com locales Type: { [path: string]: Partial } Default: ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-31T20:49:08.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-31T20:49:08.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-31T20:49:08.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Basic Config","slug":"basic-config","link":"#basic-config","children":[{"level":3,"title":"hostname","slug":"hostname","link":"#hostname","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Locale Config","slug":"locale-config","link":"#locale-config","children":[{"level":3,"title":"colorMode","slug":"colormode","link":"#colormode","children":[]},{"level":3,"title":"colorModeSwitch","slug":"colormodeswitch","link":"#colormodeswitch","children":[]},{"level":3,"title":"home","slug":"home","link":"#home","children":[]},{"level":3,"title":"navbar","slug":"navbar","link":"#navbar","children":[]},{"level":3,"title":"logo","slug":"logo","link":"#logo","children":[]},{"level":3,"title":"logoDark","slug":"logodark","link":"#logodark","children":[]},{"level":3,"title":"logoAlt","slug":"logoalt","link":"#logoalt","children":[]},{"level":3,"title":"repo","slug":"repo","link":"#repo","children":[]},{"level":3,"title":"sidebar","slug":"sidebar","link":"#sidebar","children":[]},{"level":3,"title":"sidebarDepth","slug":"sidebardepth","link":"#sidebardepth","children":[]},{"level":3,"title":"editLink","slug":"editlink","link":"#editlink","children":[]},{"level":3,"title":"editLinkPattern","slug":"editlinkpattern","link":"#editlinkpattern","children":[]},{"level":3,"title":"docsRepo","slug":"docsrepo","link":"#docsrepo","children":[]},{"level":3,"title":"docsBranch","slug":"docsbranch","link":"#docsbranch","children":[]},{"level":3,"title":"docsDir","slug":"docsdir","link":"#docsdir","children":[]},{"level":3,"title":"lastUpdated","slug":"lastupdated","link":"#lastupdated","children":[]},{"level":3,"title":"contributors","slug":"contributors","link":"#contributors","children":[]}]}],"git":{"updatedTime":1706734148000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":7}]},"autoDesc":true,"filePathRelative":"themes/default/config.md"}');export{ms as comp,ys as data};
diff --git a/assets/config.html-Dgszt0cD.js b/assets/config.html-Dgszt0cD.js
new file mode 100644
index 0000000000..5189c49745
--- /dev/null
+++ b/assets/config.html-Dgszt0cD.js
@@ -0,0 +1,45 @@
+import{_ as i,r as o,o as t,c as p,b as s,d as e,a as l,e as a}from"./app-3y2wReKQ.js";const r={},c=a('
',5),d=s("li",null,[e("Type: "),s("code",null,"string")],-1),u={href:"https://giscus.app/",target:"_blank",rel:"noopener noreferrer"},h=s("h3",{id:"category",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#category"},[s("span",null,"category")])],-1),y=s("ul",null,[s("li",null,[e("Type: "),s("code",null,"string")]),s("li",null,"Details: The name of the discussion category.")],-1),D=s("h3",{id:"categoryid",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#categoryid"},[s("span",null,"categoryId")])],-1),m=s("li",null,[e("Type: "),s("code",null,"string")],-1),g={href:"https://giscus.app/",target:"_blank",rel:"noopener noreferrer"},v=s("h3",{id:"mapping",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#mapping"},[s("span",null,"mapping")])],-1),f=s("li",null,[e("Type: "),s("code",null,"string")],-1),C=s("li",null,[e("Default: "),s("code",null,'"pathname"')],-1),b={href:"https://giscus.app/",target:"_blank",rel:"noopener noreferrer"},_=a(`
`,18);function k(E,x){const n=o("ExternalLinkIcon");return t(),p("div",null,[c,s("ul",null,[d,s("li",null,[e("Details: The ID of repository to store discussions. Generate through "),s("a",u,[e("Giscus Page"),l(n)])])]),h,y,D,s("ul",null,[m,s("li",null,[e("Details: The ID of the discussion category. Generate through "),s("a",g,[e("Giscus Page"),l(n)])])]),v,s("ul",null,[f,C,s("li",null,[e("Details: Page - Discussion mapping. For details see "),s("a",b,[e("Giscus Page"),l(n)])])]),_])}const G=i(r,[["render",k],["__file","config.html.vue"]]),P=JSON.parse('{"path":"/plugins/comment/giscus/config.html","title":"Giscus Options","lang":"en-US","frontmatter":{"description":"Giscus Options Config repo Type: string Details: The name of repository to store discussions. repoId Type: string Details: The ID of repository to store discussions. Generate th...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/giscus/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Giscus Options"}],["meta",{"property":"og:description","content":"Giscus Options Config repo Type: string Details: The name of repository to store discussions. repoId Type: string Details: The ID of repository to store discussions. Generate th..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Giscus Options\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Config","slug":"config","link":"#config","children":[{"level":3,"title":"repo","slug":"repo","link":"#repo","children":[]},{"level":3,"title":"repoId","slug":"repoid","link":"#repoid","children":[]},{"level":3,"title":"category","slug":"category","link":"#category","children":[]},{"level":3,"title":"categoryId","slug":"categoryid","link":"#categoryid","children":[]},{"level":3,"title":"mapping","slug":"mapping","link":"#mapping","children":[]},{"level":3,"title":"strict","slug":"strict","link":"#strict","children":[]},{"level":3,"title":"lazyLoading","slug":"lazyloading","link":"#lazyloading","children":[]},{"level":3,"title":"reactionsEnabled","slug":"reactionsenabled","link":"#reactionsenabled","children":[]},{"level":3,"title":"inputPosition","slug":"inputposition","link":"#inputposition","children":[]},{"level":3,"title":"lightTheme","slug":"lighttheme","link":"#lighttheme","children":[]},{"level":3,"title":"darkTheme","slug":"darktheme","link":"#darktheme","children":[]}]},{"level":2,"title":"Plugin Config","slug":"plugin-config","link":"#plugin-config","children":[]},{"level":2,"title":"Client Config","slug":"client-config","link":"#client-config","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/giscus/config.md"}');export{G as comp,P as data};
diff --git a/assets/config.html-G4t8QMRE.js b/assets/config.html-G4t8QMRE.js
new file mode 100644
index 0000000000..2d0e318b72
--- /dev/null
+++ b/assets/config.html-G4t8QMRE.js
@@ -0,0 +1 @@
+import{_ as a,r as s,o,c as n,b as e,d as t,a as p,w as r,e as l}from"./app-3y2wReKQ.js";const d={},c=l('
Last modify time getter. By default, the plugin will use the timestamp generated by git plugin.
',4);function f(y,v){const i=s("RouteLink");return o(),n("div",null,[c,e("ul",null,[h,m,e("li",null,[u,e("p",null,[t("Page default update frequency, will be overridden by "),p(i,{to:"/plugins/sitemap/frontmatter.html#sitemap-changefreq"},{default:r(()=>[t("sitemap.changefreq")]),_:1}),t(" in Frontmatter.")])])]),g])}const T=a(d,[["render",f],["__file","config.html.vue"]]),b=JSON.parse('{"path":"/plugins/sitemap/config.html","title":"Config","lang":"en-US","frontmatter":{"description":"Config hostname Type: string Required: Yes Details: The domain name where the current site is deployed, the plugin needs this option to work. extraUrls Type: string[] Details: E...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/sitemap/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Config"}],["meta",{"property":"og:description","content":"Config hostname Type: string Required: Yes Details: The domain name where the current site is deployed, the plugin needs this option to work. extraUrls Type: string[] Details: E..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-31T17:59:51.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-31T17:59:51.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-31T17:59:51.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"hostname","slug":"hostname","link":"#hostname","children":[]},{"level":2,"title":"extraUrls","slug":"extraurls","link":"#extraurls","children":[]},{"level":2,"title":"excludePaths","slug":"excludepaths","link":"#excludepaths","children":[]},{"level":2,"title":"devServer","slug":"devserver","link":"#devserver","children":[]},{"level":2,"title":"devHostname","slug":"devhostname","link":"#devhostname","children":[]},{"level":2,"title":"sitemapFilename","slug":"sitemapfilename","link":"#sitemapfilename","children":[]},{"level":2,"title":"sitemapXSLFilename","slug":"sitemapxslfilename","link":"#sitemapxslfilename","children":[]},{"level":2,"title":"sitemapXSLTemplate","slug":"sitemapxsltemplate","link":"#sitemapxsltemplate","children":[]},{"level":2,"title":"changefreq","slug":"changefreq","link":"#changefreq","children":[]},{"level":2,"title":"priority","slug":"priority","link":"#priority","children":[]},{"level":2,"title":"modifyTimeGetter","slug":"modifytimegetter","link":"#modifytimegetter","children":[]}],"git":{"updatedTime":1706723991000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"plugins/sitemap/config.md"}');export{T as comp,b as data};
diff --git a/assets/config.html-KSkfPrbt.js b/assets/config.html-KSkfPrbt.js
new file mode 100644
index 0000000000..069ffbb6dd
--- /dev/null
+++ b/assets/config.html-KSkfPrbt.js
@@ -0,0 +1,23 @@
+import{_ as s,o as n,c as e,e as l}from"./app-3y2wReKQ.js";const a={},o=l(`
`,7);function g(f,y){const n=l("ExternalLinkIcon");return o(),t("div",null,[c,d,e("p",null,[s("See "),e("a",m,[s("Artalk Configuration"),i(n)]),s(" for details.")]),u])}const v=a(r,[["render",g],["__file","config.html.vue"]]),C=JSON.parse('{"path":"/plugins/comment/artalk/config.html","title":"Artalk Options","lang":"en-US","frontmatter":{"description":"Artalk Options Config See Artalk Configuration for details. The el pageTitle, pageKey and site options are reserved for plugins, they will be inferred from VuePress config. Two ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/artalk/config.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/config.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Artalk Options"}],["meta",{"property":"og:description","content":"Artalk Options Config See Artalk Configuration for details. The el pageTitle, pageKey and site options are reserved for plugins, they will be inferred from VuePress config. Two ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Artalk Options\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Config","slug":"config","link":"#config","children":[]},{"level":2,"title":"Plugin Config","slug":"plugin-config","link":"#plugin-config","children":[]},{"level":2,"title":"Client Config","slug":"client-config","link":"#client-config","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/artalk/config.md"}');export{v as comp,C as data};
diff --git a/assets/config.html-ngwp0KsM.js b/assets/config.html-ngwp0KsM.js
new file mode 100644
index 0000000000..d3a152e0cc
--- /dev/null
+++ b/assets/config.html-ngwp0KsM.js
@@ -0,0 +1,104 @@
+import{_ as p,r as i,o as t,c,b as s,d as n,a as l,e}from"./app-3y2wReKQ.js";const r={},d=e('
`,5),J={id:"metaicon",tabindex:"-1"},K={class:"header-anchor",href:"#metaicon"},O=s("ul",null,[s("li",null,[s("p",null,[n("类型: "),s("code",null,"boolean")])]),s("li",null,[s("p",null,[n("默认值: "),s("code",null,"true")])]),s("li",null,[s("p",null,"详情:"),s("p",null,"是否导入 Meta 图标。")])],-1),Z={id:"locales",tabindex:"-1"},$={class:"header-anchor",href:"#locales"},G=e(`
`,9),m=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),g=s("p",null,"Details:",-1),C=s("p",null,"The type of the container.",-1),v=s("code",null,"name",-1),k={href:"https://github.com/markdown-it/markdown-it-container#api",target:"_blank",rel:"noopener noreferrer"},_=t(`
`,11),x=s("p",null,"Details:",-1),T=s("code",null,"render",-1),w={href:"https://github.com/markdown-it/markdown-it-container#api",target:"_blank",rel:"noopener noreferrer"},F=s("p",null,[n("This plugin uses a default "),s("code",null,"render"),n(" function. If you specify this option, the default "),s("code",null,"render"),n(" function will be replaced, and the "),s("a",{href:"#locales"},"locales"),n(", "),s("a",{href:"#before"},"before"),n(" and "),s("a",{href:"#after"},"after"),n(" options will be ignored.")],-1),B=s("h3",{id:"validate",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#validate"},[s("span",null,"validate")])],-1),A=s("li",null,[s("p",null,[n("Type: "),s("code",null,"(params: string) => boolean")])],-1),I=s("p",null,"Details:",-1),P=s("code",null,"validate",-1),j={href:"https://github.com/markdown-it/markdown-it-container#api",target:"_blank",rel:"noopener noreferrer"},N=s("h3",{id:"marker",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#marker"},[s("span",null,"marker")])],-1),S=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),V=s("p",null,"Details:",-1),R=s("code",null,"marker",-1),q={href:"https://github.com/markdown-it/markdown-it-container#api",target:"_blank",rel:"noopener noreferrer"};function z(L,M){const o=l("NpmBadge"),a=l("ExternalLinkIcon"),p=l("RouteLink");return i(),c("div",null,[D,e(o,{package:"@vuepress/plugin-container"}),y,s("p",null,[n("This plugin simplifies the use of "),s("a",h,[n("markdown-it-container"),e(a)]),n(", but also retains its original capabilities.")]),s("p",null,[n("The "),e(p,{to:"/themes/default/markdown.html#custom-containers"},{default:d(()=>[n("Custom Containers")]),_:1}),n(" of default theme is powered by this plugin.")]),f,s("ul",null,[m,s("li",null,[g,C,s("p",null,[n("It will be used as the "),v,n(" param of "),s("a",k,[n("markdown-it-container"),e(a)]),n(".")])])]),_,s("ul",null,[s("li",null,[n("Also see: "),s("ul",null,[s("li",null,[s("a",b,[n("Guide > I18n"),e(a)])])])])]),E,s("ul",null,[s("li",null,[x,s("p",null,[n("The "),T,n(" option of "),s("a",w,[n("markdown-it-container"),e(a)]),n(".")]),F])]),B,s("ul",null,[A,s("li",null,[I,s("p",null,[n("The "),P,n(" option of "),s("a",j,[n("markdown-it-container"),e(a)]),n(".")])])]),N,s("ul",null,[S,s("li",null,[V,s("p",null,[n("The "),R,n(" option of "),s("a",q,[n("markdown-it-container"),e(a)]),n(".")])])])])}const U=r(u,[["render",z],["__file","container.html.vue"]]),Z=JSON.parse('{"path":"/plugins/container.html","title":"container","lang":"en-US","frontmatter":{"description":"container","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/container.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/container.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"container"}],["meta",{"property":"og:description","content":"container"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"container\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Container Syntax","slug":"container-syntax","link":"#container-syntax","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"type","slug":"type","link":"#type","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"before","slug":"before","link":"#before","children":[]},{"level":3,"title":"after","slug":"after","link":"#after","children":[]},{"level":3,"title":"render","slug":"render","link":"#render","children":[]},{"level":3,"title":"validate","slug":"validate","link":"#validate","children":[]},{"level":3,"title":"marker","slug":"marker","link":"#marker","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/container.md"}');export{U as comp,Z as data};
diff --git a/assets/container.html-Cv51pmo2.js b/assets/container.html-Cv51pmo2.js
new file mode 100644
index 0000000000..cfaa37168e
--- /dev/null
+++ b/assets/container.html-Cv51pmo2.js
@@ -0,0 +1,39 @@
+import{_ as r,r as l,o as c,c as i,a as e,b as s,d as n,w as d,e as o}from"./app-3y2wReKQ.js";const D={},u=s("h1",{id:"container",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#container"},[s("span",null,"container")])],-1),y=s("p",null,"为你的 VuePress 站点注册自定义容器。",-1),h={href:"https://github.com/markdown-it/markdown-it-container",target:"_blank",rel:"noopener noreferrer"},m=o(`
`,20);function d(y,D){const n=l("NpmBadge");return a(),o("div",null,[c,p(n,{package:"@vuepress/plugin-copy-code"}),r])}const m=e(t,[["render",d],["__file","copy-code.html.vue"]]),g=JSON.parse('{"path":"/plugins/copy-code.html","title":"copy-code","lang":"en-US","frontmatter":{"description":"copy-code","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/copy-code.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/copy-code.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"copy-code"}],["meta",{"property":"og:description","content":"copy-code"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"copy-code\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]},{"level":3,"title":"showInMobile","slug":"showinmobile","link":"#showinmobile","children":[]},{"level":3,"title":"duration","slug":"duration","link":"#duration","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"plugins/copy-code.md"}');export{m as comp,g as data};
diff --git a/assets/copy-code.html-gN3nsk5o.js b/assets/copy-code.html-gN3nsk5o.js
new file mode 100644
index 0000000000..244fbc1701
--- /dev/null
+++ b/assets/copy-code.html-gN3nsk5o.js
@@ -0,0 +1,61 @@
+import{_ as l,r as a,o as e,c as p,a as o,b as s,e as c}from"./app-3y2wReKQ.js";const i={},t=s("h1",{id:"copy-code",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#copy-code"},[s("span",null,"copy-code")])],-1),r=c(`
`,20);function d(D,y){const n=a("NpmBadge");return e(),p("div",null,[t,o(n,{package:"@vuepress/plugin-copy-code"}),r])}const m=l(i,[["render",d],["__file","copy-code.html.vue"]]),v=JSON.parse('{"path":"/zh/plugins/copy-code.html","title":"copy-code","lang":"zh-CN","frontmatter":{"description":"copy-code","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/copy-code.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/copy-code.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"copy-code"}],["meta",{"property":"og:description","content":"copy-code"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"copy-code\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]},{"level":3,"title":"showInMobile","slug":"showinmobile","link":"#showinmobile","children":[]},{"level":3,"title":"duration","slug":"duration","link":"#duration","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":6}]},"autoDesc":true,"filePathRelative":"zh/plugins/copy-code.md"}');export{m as comp,v as data};
diff --git a/assets/copyright.html-BRX4pPJA.js b/assets/copyright.html-BRX4pPJA.js
new file mode 100644
index 0000000000..60ddf19994
--- /dev/null
+++ b/assets/copyright.html-BRX4pPJA.js
@@ -0,0 +1,66 @@
+import{_ as e,r as n,o as a,c as i,a as o,b as s,e as t}from"./app-3y2wReKQ.js";const c={},p=s("h1",{id:"copyright",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#copyright"},[s("span",null,"copyright")])],-1),r=t(`
`,50);function d(h,g){const l=n("NpmBadge");return a(),i("div",null,[p,o(l,{package:"@vuepress/plugin-copyright"}),r])}const u=e(c,[["render",d],["__file","copyright.html.vue"]]),m=JSON.parse('{"path":"/zh/plugins/copyright.html","title":"copyright","lang":"zh-CN","frontmatter":{"description":"copyright","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/copyright.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/copyright.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"copyright"}],["meta",{"property":"og:description","content":"copyright"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"copyright\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[{"level":3,"title":"启用版权信息","slug":"启用版权信息","link":"#启用版权信息","children":[]},{"level":3,"title":"禁用复制和选择","slug":"禁用复制和选择","link":"#禁用复制和选择","children":[]}]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"author","slug":"author","link":"#author","children":[]},{"level":3,"title":"license","slug":"license","link":"#license","children":[]},{"level":3,"title":"authorGetter","slug":"authorgetter","link":"#authorgetter","children":[]},{"level":3,"title":"licenseGetter","slug":"licensegetter","link":"#licensegetter","children":[]},{"level":3,"title":"copyrightGetter","slug":"copyrightgetter","link":"#copyrightgetter","children":[]},{"level":3,"title":"triggerLength","slug":"triggerlength","link":"#triggerlength","children":[]},{"level":3,"title":"maxLength","slug":"maxlength","link":"#maxlength","children":[]},{"level":3,"title":"global","slug":"global","link":"#global","children":[]},{"level":3,"title":"disableCopy","slug":"disablecopy","link":"#disablecopy","children":[]},{"level":3,"title":"disableSelection","slug":"disableselection","link":"#disableselection","children":[]},{"level":3,"title":"canonical","slug":"canonical","link":"#canonical","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"copy.triggerLength","slug":"copy-triggerlength","link":"#copy-triggerlength","children":[]},{"level":3,"title":"copy.maxLength","slug":"copy-maxlength","link":"#copy-maxlength","children":[]},{"level":3,"title":"copy.disableCopy","slug":"copy-disablecopy","link":"#copy-disablecopy","children":[]},{"level":3,"title":"copy.disableSelection","slug":"copy-disableselection","link":"#copy-disableselection","children":[]}]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"zh/plugins/copyright.md"}');export{u as comp,m as data};
diff --git a/assets/copyright.html-hNQYoBgt.js b/assets/copyright.html-hNQYoBgt.js
new file mode 100644
index 0000000000..ad78e5d201
--- /dev/null
+++ b/assets/copyright.html-hNQYoBgt.js
@@ -0,0 +1,66 @@
+import{_ as n,r as l,o as a,c as i,a as o,b as e,e as t}from"./app-3y2wReKQ.js";const p={},c=e("h1",{id:"copyright",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#copyright"},[e("span",null,"copyright")])],-1),r=t(`
This plugin can automatically append copyright information when visitors copy content from your site, and can also prohibit site copying or selection.
This plugin is disabled globally by default, you can:
Manually enable it by setting copy: true in page frontmatter
Set global: 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.
If you don't want users to copy your entire site or specific page text, you can set disableCopy in plugin options or copy.disableCopy in page frontmatter, the latter has higher priority.
If you don't want users to select your entire site or specific page text, you can set disableSelection in plugin options or copy.disableSelection in page frontmatter. This option has higher priority.
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.
`,1),_={class:"custom-container tip"},A=s("p",{class:"custom-container-title"},"TIP",-1),f={href:"https://crawler.algolia.com/admin/crawlers/",target:"_blank",rel:"noopener noreferrer"},x=s("h2",{id:"options",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#options"},[s("span",null,"Options")])],-1),B=s("h3",{id:"apikey",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#apikey"},[s("span",null,"apiKey")])],-1),F=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),k=s("li",null,[s("p",null,[n("Required: "),s("code",null,"true")])],-1),w=s("li",null,[s("p",null,"Details:"),s("p",null,[n("The "),s("code",null,"apiKey"),n(" that you received from the DocSearch team, or generated by yourself.")])],-1),S=s("p",null,"Also see:",-1),T={href:"https://docsearch.algolia.com/docs/api#apikey",target:"_blank",rel:"noopener noreferrer"},P=s("h3",{id:"indexname",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#indexname"},[s("span",null,"indexName")])],-1),I=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),N=s("li",null,[s("p",null,[n("Required: "),s("code",null,"true")])],-1),O=s("li",null,[s("p",null,"Details:"),s("p",null,[n("The "),s("code",null,"indexName"),n(" that you received from the DocSearch team, or generated by yourself.")])],-1),j=s("p",null,"Also see:",-1),R={href:"https://docsearch.algolia.com/docs/api#indexname",target:"_blank",rel:"noopener noreferrer"},U=s("h3",{id:"appid",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#appid"},[s("span",null,"appId")])],-1),z=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),Y=s("li",null,[s("p",null,[n("Required: "),s("code",null,"true")])],-1),q=s("li",null,[s("p",null,"Details:"),s("p",null,"It defines your own application ID.")],-1),V=s("p",null,"Also see:",-1),K={href:"https://docsearch.algolia.com/docs/api#appid",target:"_blank",rel:"noopener noreferrer"},W=s("h3",{id:"searchparameters",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#searchparameters"},[s("span",null,"searchParameters")])],-1),L=s("li",null,[s("p",null,[n("Type: "),s("code",null,"SearchParameters")])],-1),M=s("li",null,[s("p",null,"Details:"),s("p",null,"Parameters of Algolia Search API.")],-1),H=s("p",null,"Also see:",-1),X={href:"https://docsearch.algolia.com/docs/api/#searchparameters",target:"_blank",rel:"noopener noreferrer"},G={href:"https://www.algolia.com/doc/api-reference/search-api-parameters/",target:"_blank",rel:"noopener noreferrer"},Q=s("h3",{id:"placeholder",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#placeholder"},[s("span",null,"placeholder")])],-1),Z=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),J=s("li",null,[s("p",null,[n("Default: "),s("code",null,"'Search docs'")])],-1),$=s("li",null,[s("p",null,"Details:"),s("p",null,"The placeholder attribute of the search input.")],-1),ss=s("p",null,"Also see:",-1),ns={href:"https://docsearch.algolia.com/docs/api/#placeholder",target:"_blank",rel:"noopener noreferrer"},ls=s("h3",{id:"disableuserpersonalization",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#disableuserpersonalization"},[s("span",null,"disableUserPersonalization")])],-1),as=s("li",null,[s("p",null,[n("Type: "),s("code",null,"boolean")])],-1),es=s("li",null,[s("p",null,[n("Default: "),s("code",null,"false")])],-1),os=s("li",null,[s("p",null,"Details:"),s("p",null,"Whether to disable all personalized features: recent searches, favorite searches, etc.")],-1),ps=s("p",null,"Also see:",-1),rs={href:"https://docsearch.algolia.com/docs/api/#disableuserpersonalization",target:"_blank",rel:"noopener noreferrer"},cs=s("h3",{id:"initialquery",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#initialquery"},[s("span",null,"initialQuery")])],-1),ts=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),is=s("li",null,[s("p",null,"Details:"),s("p",null,"The initial query when the modal opens.")],-1),ds=s("p",null,"Also see:",-1),Ds={href:"https://docsearch.algolia.com/docs/api/#initialquery",target:"_blank",rel:"noopener noreferrer"},ys=s("h3",{id:"translations",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#translations"},[s("span",null,"translations")])],-1),hs=s("li",null,[s("p",null,[n("Type: "),s("code",null,"Partial")])],-1),us=s("li",null,[s("p",null,"Details:"),s("p",null,"Allow replacing the default text in the DocSearch button or modal.")],-1),vs=s("p",null,"Also see:",-1),Cs={href:"https://docsearch.algolia.com/docs/api/#translations",target:"_blank",rel:"noopener noreferrer"},ms=e(`
`,3),bs={href:"https://vuejs.press/guide/i18n.html",target:"_blank",rel:"noopener noreferrer"},Es=s("h3",{id:"indexbase",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#indexbase"},[s("span",null,"indexBase")])],-1),gs=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string")])],-1),_s={href:"https://vuejs.press/reference/config.html#base",target:"_blank",rel:"noopener noreferrer"},As=s("p",null,"Details:",-1),fs=s("p",null,"The base path of the search index.",-1),xs=s("p",null,[n("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 "),s("em",null,"index domain"),n(", and only submit the "),s("em",null,"index domain"),n(" to Docsearch for crawling search index. Then, you could reuse the search index across all deployments.")],-1),Bs={href:"https://vuejs.press/reference/config.html#base",target:"_blank",rel:"noopener noreferrer"},Fs={href:"https://vuejs.press/reference/config.html#base",target:"_blank",rel:"noopener noreferrer"},ks=s("em",null,"index domain",-1),ws=e('
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.
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.
`,5);function Ps(Is,Ns){const p=o("NpmBadge"),a=o("ExternalLinkIcon");return c(),t("div",null,[d,l(p,{package:"@vuepress/plugin-docsearch"}),s("p",null,[n("Integrate "),s("a",D,[n("Algolia DocSearch"),l(a)]),n(" into VuePress, which can provide search to your documentation site.")]),y,s("p",null,[n("You need to "),s("a",h,[n("submit the URL of your site"),l(a)]),n(" to join the DocSearch program. The DocSearch team will send "),u,n(" and "),v,n(" to your email once the index is generated. Then you can configure this plugin to enable DocSearch in VuePress.")]),s("p",null,[n("Alternatively, you can "),s("a",C,[n("run your own crawler"),l(a)]),n(" to generate the index, and then use your own "),m,n(", "),b,n(" and "),E,n(" to configure this plugin.")]),g,s("div",_,[A,s("p",null,[n("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 "),s("a",f,[n("Algolia Crawler"),l(a)]),n(", and edit your config with 'Editor' panel in project sidebar.")])]),x,B,s("ul",null,[F,k,w,s("li",null,[S,s("ul",null,[s("li",null,[s("a",T,[n("DocSearch > Options > apiKey"),l(a)])])])])]),P,s("ul",null,[I,N,O,s("li",null,[j,s("ul",null,[s("li",null,[s("a",R,[n("DocSearch > Options > indexName"),l(a)])])])])]),U,s("ul",null,[z,Y,q,s("li",null,[V,s("ul",null,[s("li",null,[s("a",K,[n("DocSearch > Options > appId"),l(a)])])])])]),W,s("ul",null,[L,M,s("li",null,[H,s("ul",null,[s("li",null,[s("a",X,[n("DocSearch > Options > searchParameters"),l(a)])]),s("li",null,[s("a",G,[n("Algolia > Search API Parameters"),l(a)])])])])]),Q,s("ul",null,[Z,J,$,s("li",null,[ss,s("ul",null,[s("li",null,[s("a",ns,[n("DocSearch > Options > placeholder"),l(a)])])])])]),ls,s("ul",null,[as,es,os,s("li",null,[ps,s("ul",null,[s("li",null,[s("a",rs,[n("DocSearch > Options > disableUserPersonalization"),l(a)])])])])]),cs,s("ul",null,[ts,is,s("li",null,[ds,s("ul",null,[s("li",null,[s("a",Ds,[n("DocSearch > Options > initialQuery"),l(a)])])])])]),ys,s("ul",null,[hs,us,s("li",null,[vs,s("ul",null,[s("li",null,[s("a",Cs,[n("DocSearch > Options > translations"),l(a)])])])])]),ms,s("ul",null,[s("li",null,[n("Also see: "),s("ul",null,[s("li",null,[s("a",bs,[n("Guide > I18n"),l(a)])])])])]),Es,s("ul",null,[gs,s("li",null,[s("p",null,[n("Default: "),s("a",_s,[n("base"),l(a)])])]),s("li",null,[As,fs,xs,s("p",null,[n("However, if the "),s("a",Bs,[n("base"),l(a)]),n(" of your deployments are different for different domains, you need to set the option to the "),s("a",Fs,[n("base"),l(a)]),n(" of your "),ks,n(", so that other deployments could reuse the search index correctly.")])])]),ws,s("p",null,[n("You can customize styles via CSS variables that provided by "),s("a",Ss,[n("@docsearch/css"),l(a)]),n(":")]),Ts])}const js=r(i,[["render",Ps],["__file","docsearch.html.vue"]]),Rs=JSON.parse('{"path":"/plugins/docsearch.html","title":"docsearch","lang":"en-US","frontmatter":{"description":"docsearch","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/docsearch.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/docsearch.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"docsearch"}],["meta",{"property":"og:description","content":"docsearch"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"docsearch\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Get Search Index","slug":"get-search-index","link":"#get-search-index","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"apiKey","slug":"apikey","link":"#apikey","children":[]},{"level":3,"title":"indexName","slug":"indexname","link":"#indexname","children":[]},{"level":3,"title":"appId","slug":"appid","link":"#appid","children":[]},{"level":3,"title":"searchParameters","slug":"searchparameters","link":"#searchparameters","children":[]},{"level":3,"title":"placeholder","slug":"placeholder","link":"#placeholder","children":[]},{"level":3,"title":"disableUserPersonalization","slug":"disableuserpersonalization","link":"#disableuserpersonalization","children":[]},{"level":3,"title":"initialQuery","slug":"initialquery","link":"#initialquery","children":[]},{"level":3,"title":"translations","slug":"translations","link":"#translations","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"indexBase","slug":"indexbase","link":"#indexbase","children":[]},{"level":3,"title":"injectStyles","slug":"injectstyles","link":"#injectstyles","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]},{"level":2,"title":"Components","slug":"components","link":"#components","children":[{"level":3,"title":"Docsearch","slug":"docsearch-1","link":"#docsearch-1","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"plugins/docsearch.md"}');export{js as comp,Rs as data};
diff --git a/assets/docsearch.html-DLY8yOIl.js b/assets/docsearch.html-DLY8yOIl.js
new file mode 100644
index 0000000000..c97be06c02
--- /dev/null
+++ b/assets/docsearch.html-DLY8yOIl.js
@@ -0,0 +1,203 @@
+import{_ as r,r as p,o as c,c as i,a as l,b as s,d as n,e}from"./app-3y2wReKQ.js";const t={},D=s("h1",{id:"docsearch",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#docsearch"},[s("span",null,"docsearch")])],-1),d={href:"https://docsearch.algolia.com/",target:"_blank",rel:"noopener noreferrer"},y=e(`
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.
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',
+ ),
+ },
+ }
+}
+
`,5);function h(g,b){const n=p("ExternalLinkIcon");return c(),r("div",null,[d,e("p",null,[s("Default theme has registered "),e("a",y,[s("alias"),a(n)]),s(" for every "),e("a",D,[s("non-global components"),a(n)]),s(" with a "),m,s(" prefix. For example, the alias of "),u,s(" is "),C,s(".")]),v])}const F=t(i,[["render",h],["__file","extending.html.vue"]]),x=JSON.parse('{"path":"/themes/default/extending.html","title":"Extending","lang":"en-US","frontmatter":{"description":"Extending VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease. Layout Slots Default them...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/extending.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Extending"}],["meta",{"property":"og:description","content":"Extending VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease. Layout Slots Default them..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://ecosystem.vuejs.press/ecosystem/images/cookbook/extending-a-theme-01.png"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T14:33:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T14:33:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Extending\\",\\"image\\":[\\"https://ecosystem.vuejs.press/ecosystem/images/cookbook/extending-a-theme-01.png\\"],\\"dateModified\\":\\"2024-01-30T14:33:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Layout Slots","slug":"layout-slots","link":"#layout-slots","children":[]},{"level":2,"title":"Components Replacement","slug":"components-replacement","link":"#components-replacement","children":[]},{"level":2,"title":"Developing a Child Theme","slug":"developing-a-child-theme","link":"#developing-a-child-theme","children":[]}],"git":{"updatedTime":1706625181000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"themes/default/extending.md"}');export{F as comp,x as data};
diff --git a/assets/external-link-icon.html-D91aC3AN.js b/assets/external-link-icon.html-D91aC3AN.js
new file mode 100644
index 0000000000..7e4abd2d3a
--- /dev/null
+++ b/assets/external-link-icon.html-D91aC3AN.js
@@ -0,0 +1,28 @@
+import{_ as i,r as a,o as p,c,a as e,b as n,d as s,e as t}from"./app-3y2wReKQ.js";const r={},d=n("h1",{id:"external-link-icon",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#external-link-icon"},[n("span",null,"external-link-icon")])],-1),h=t(`
This plugin has been integrated into the default theme.
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.
`,10);function y(m,x){const o=a("NpmBadge"),l=a("ExternalLinkIcon");return p(),c("div",null,[d,e(o,{package:"@vuepress/plugin-external-link-icon"}),n("p",null,[s("This plugin will add an icon to the external link in your markdown content, i.e. "),e(l)]),h,n("ul",null,[n("li",null,[s("Also see: "),n("ul",null,[n("li",null,[n("a",u,[s("Guide > I18n"),e(l)])])])])]),D])}const g=i(r,[["render",y],["__file","external-link-icon.html.vue"]]),v=JSON.parse('{"path":"/plugins/external-link-icon.html","title":"external-link-icon","lang":"en-US","frontmatter":{"description":"external-link-icon","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/external-link-icon.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/external-link-icon.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"external-link-icon"}],["meta",{"property":"og:description","content":"external-link-icon"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"external-link-icon\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"externalLinkIcon","slug":"externallinkicon","link":"#externallinkicon","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]},{"level":2,"title":"Components","slug":"components","link":"#components","children":[{"level":3,"title":"ExternalLinkIcon","slug":"externallinkicon-1","link":"#externallinkicon-1","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/external-link-icon.md"}');export{g as comp,v as data};
diff --git a/assets/external-link-icon.html-w4_SDA_y.js b/assets/external-link-icon.html-w4_SDA_y.js
new file mode 100644
index 0000000000..ee453c97a2
--- /dev/null
+++ b/assets/external-link-icon.html-w4_SDA_y.js
@@ -0,0 +1,28 @@
+import{_ as p,r as a,o as i,c as r,a as s,b as n,d as e,e as t}from"./app-3y2wReKQ.js";const c={},d=n("h1",{id:"external-link-icon",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#external-link-icon"},[n("span",null,"external-link-icon")])],-1),D=t(`
`,10);function y(m,k){const o=a("NpmBadge"),l=a("ExternalLinkIcon");return i(),r("div",null,[d,s(o,{package:"@vuepress/plugin-external-link-icon"}),n("p",null,[e("该插件会为你 Markdown 内容中的外部链接添加一个图标,即 "),s(l)]),D,n("ul",null,[n("li",null,[e("参考: "),n("ul",null,[n("li",null,[n("a",h,[e("指南 > 多语言支持"),s(l)])])])])]),u])}const v=p(c,[["render",y],["__file","external-link-icon.html.vue"]]),g=JSON.parse('{"path":"/zh/plugins/external-link-icon.html","title":"external-link-icon","lang":"zh-CN","frontmatter":{"description":"external-link-icon","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/external-link-icon.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/external-link-icon.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"external-link-icon"}],["meta",{"property":"og:description","content":"external-link-icon"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"external-link-icon\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"externalLinkIcon","slug":"externallinkicon","link":"#externallinkicon","children":[]}]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]},{"level":2,"title":"组件","slug":"组件","link":"#组件","children":[{"level":3,"title":"ExternalLinkIcon","slug":"externallinkicon-1","link":"#externallinkicon-1","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"zh/plugins/external-link-icon.md"}');export{v as comp,g as data};
diff --git a/assets/frontmatter.html-CGS3CY3-.js b/assets/frontmatter.html-CGS3CY3-.js
new file mode 100644
index 0000000000..d3fe860353
--- /dev/null
+++ b/assets/frontmatter.html-CGS3CY3-.js
@@ -0,0 +1,60 @@
+import{_ as r,r as i,o as c,c as d,a as s,b as e,d as l,w as a,e as t}from"./app-3y2wReKQ.js";const h={},u=e("h1",{id:"frontmatter",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#frontmatter"},[e("span",null,"Frontmatter")])],-1),D=e("h2",{id:"all-pages",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#all-pages"},[e("span",null,"All Pages")])],-1),m=e("p",null,"Frontmatter in this section will take effect in all types of pages.",-1),g=e("h3",{id:"externallinkicon",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#externallinkicon"},[e("span",null,"externalLinkIcon")])],-1),y=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),f=e("p",null,"Details:",-1),_=e("p",null,"Also see:",-1),b=e("h3",{id:"navbar",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#navbar"},[e("span",null,"navbar")])],-1),v=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),k=e("li",null,[e("p",null,"Details:"),e("p",null,"Show navbar on this page or not."),e("p",null,"If you disable navbar in theme config, this frontmatter will not take effect.")],-1),x=e("p",null,"Also see:",-1),C=t(`
`,8),T={href:"https://v2.vuepress.vuejs.org/guide/assets.html#public-files",target:"_blank",rel:"noopener noreferrer"},A=e("h3",{id:"heroimagedark",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#heroimagedark"},[e("span",null,"heroImageDark")])],-1),S=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),w=e("li",null,[e("p",null,"Details:"),e("p",null,"Specify the url of hero image to be used in dark mode."),e("p",null,"You can make use of this option if you want to use different heroImage config in dark mode.")],-1),L=e("p",null,"Also see:",-1),F=e("li",null,[e("a",{href:"#heroimage"},"Default Theme > Frontmatter > heroImage")],-1),P=t('
',3),I=e("li",null,[e("p",null,[l("Type: "),e("code",null,"number")])],-1),N=e("li",null,[e("p",null,[l("Default: "),e("code",null,"280")])],-1),j=e("p",null,"Details:",-1),V=e("p",null,[l("Specify the "),e("code",null,"height"),l(" attribute of the hero "),e("code",null,""),l(" tag.")],-1),H=e("p",null,"You may need to reduce this value if the height of your hero image is less than the default value.",-1),B={href:"https://web.dev/cls/",target:"_blank",rel:"noopener noreferrer"},M=e("h3",{id:"herotext",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#herotext"},[e("span",null,"heroText")])],-1),R=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string | null")])],-1),U=e("p",null,"Details:",-1),z=e("p",null,"Specify the the hero text.",-1),G={href:"https://v2.vuepress.vuejs.org/reference/config.html#title",target:"_blank",rel:"noopener noreferrer"},O=e("p",null,[l("Set to "),e("code",null,"null"),l(" to disable hero text.")],-1),Z=e("h3",{id:"tagline",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#tagline"},[e("span",null,"tagline")])],-1),J=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string | null")])],-1),Y=e("p",null,"Details:",-1),q=e("p",null,"Specify the the tagline.",-1),K={href:"https://v2.vuepress.vuejs.org/reference/config.html#description",target:"_blank",rel:"noopener noreferrer"},Q=e("p",null,[l("Set to "),e("code",null,"null"),l(" to disable tagline.")],-1),W=t(`
---
+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.
+---
+
`,17),X=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),$=e("li",null,[e("p",null,"Details:"),e("p",null,[l("Enable the "),e("em",null,"edit this page"),l(" link in this page or not.")])],-1),ee=e("p",null,"Also see:",-1),le=e("h3",{id:"editlinkpattern",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#editlinkpattern"},[e("span",null,"editLinkPattern")])],-1),se=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),ne=e("li",null,[e("p",null,"Details:"),e("p",null,[l("Specify the pattern of the "),e("em",null,"edit this page"),l(" link of this page.")])],-1),ae=e("p",null,"Also see:",-1),te=e("h3",{id:"lastupdated",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#lastupdated"},[e("span",null,"lastUpdated")])],-1),oe=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),ie=e("li",null,[e("p",null,"Details:"),e("p",null,[l("Enable the "),e("em",null,"last updated timestamp"),l(" in this page or not.")])],-1),pe=e("p",null,"Also see:",-1),re=e("h3",{id:"contributors",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contributors"},[e("span",null,"contributors")])],-1),ce=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),de=e("li",null,[e("p",null,"Details:"),e("p",null,[l("Enable the "),e("em",null,"contributors list"),l(" in this page or not.")])],-1),he=e("p",null,"Also see:",-1),ue=e("h3",{id:"sidebar",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#sidebar"},[e("span",null,"sidebar")])],-1),De=e("li",null,[e("p",null,[l("Type: "),e("code",null,"false | 'auto' | SidebarConfigArray | SidebarConfigObject")])],-1),me=e("li",null,[e("p",null,"Details:"),e("p",null,"Configure the sidebar of this page.")],-1),ge=e("p",null,"Also see:",-1),ye=e("h3",{id:"sidebardepth",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#sidebardepth"},[e("span",null,"sidebarDepth")])],-1),fe=e("li",null,[e("p",null,[l("Type: "),e("code",null,"number")])],-1),_e=e("li",null,[e("p",null,"Details:"),e("p",null,"Configure the sidebar depth of this page.")],-1),be=e("p",null,"Also see:",-1),ve=t(`
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:
A NavLink object should have a text field and a link field.
A string should be the path to the target page file. It will be converted to a NavLink object, whose text is the page title, and link is the page route path.
`,5);function ke(xe,Ce){const p=i("NpmBadge"),n=i("RouteLink"),o=i("ExternalLinkIcon");return c(),d("div",null,[u,s(p,{package:"@vuepress/theme-default"}),D,m,g,e("ul",null,[y,e("li",null,[f,e("p",null,[l("Provided by "),s(n,{to:"/plugins/external-link-icon.html#externallinkicon"},{default:a(()=>[l("@vuepress/plugin-external-link-icon")]),_:1}),l(".")])]),e("li",null,[_,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#themeplugins-externallinkicon"},{default:a(()=>[l("Default Theme > Config Reference > themePlugins.externalLinkIcon")]),_:1})])])])]),b,e("ul",null,[v,k,e("li",null,[x,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#navbar"},{default:a(()=>[l("Default Theme > Config > navbar")]),_:1})])])])]),C,e("ul",null,[e("li",null,[l("Also see: "),e("ul",null,[e("li",null,[s(n,{to:"/themes/default/styles.html#style-file"},{default:a(()=>[l("Default Theme > Styles > Style File")]),_:1})])])])]),E,e("ul",null,[e("li",null,[l("Also see: "),e("ul",null,[e("li",null,[e("a",T,[l("Guide > Assets > Public Files"),s(o)])])])])]),A,e("ul",null,[S,w,e("li",null,[L,e("ul",null,[F,e("li",null,[s(n,{to:"/themes/default/config.html#colormode"},{default:a(()=>[l("Default Theme > Config > colorMode")]),_:1})])])])]),P,e("ul",null,[I,N,e("li",null,[j,V,H,e("p",null,[l("Notice that the height is also constrained by CSS. This attribute is to reduce "),e("a",B,[l("Cumulative Layout Shift (CLS)"),s(o)]),l(" that caused by the loading of the hero image.")])])]),M,e("ul",null,[R,e("li",null,[U,z,e("p",null,[l("This will fallback to the site "),e("a",G,[l("title"),s(o)]),l(".")]),O])]),Z,e("ul",null,[J,e("li",null,[Y,q,e("p",null,[l("This will fallback to the site "),e("a",K,[l("description"),s(o)]),l(".")]),Q])]),W,e("ul",null,[X,$,e("li",null,[ee,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#editlink"},{default:a(()=>[l("Default Theme > Config > editLink")]),_:1})])])])]),le,e("ul",null,[se,ne,e("li",null,[ae,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#editlinkpattern"},{default:a(()=>[l("Default Theme > Config > editLinkPattern")]),_:1})])])])]),te,e("ul",null,[oe,ie,e("li",null,[pe,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#lastupdated"},{default:a(()=>[l("Default Theme > Config > lastUpdated")]),_:1})])])])]),re,e("ul",null,[ce,de,e("li",null,[he,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#contributors"},{default:a(()=>[l("Default Theme > Config > contributors")]),_:1})])])])]),ue,e("ul",null,[De,me,e("li",null,[ge,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#sidebar"},{default:a(()=>[l("Default Theme > Config > sidebar")]),_:1})])])])]),ye,e("ul",null,[fe,_e,e("li",null,[be,e("ul",null,[e("li",null,[s(n,{to:"/themes/default/config.html#sidebardepth"},{default:a(()=>[l("Default Theme > Config > sidebarDepth")]),_:1})])])])]),ve])}const Te=r(h,[["render",ke],["__file","frontmatter.html.vue"]]),Ae=JSON.parse('{"path":"/themes/default/frontmatter.html","title":"Frontmatter","lang":"en-US","frontmatter":{"description":"Frontmatter","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/frontmatter.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/frontmatter.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Frontmatter"}],["meta",{"property":"og:description","content":"Frontmatter"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T14:33:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T14:33:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Frontmatter\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T14:33:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"All Pages","slug":"all-pages","link":"#all-pages","children":[{"level":3,"title":"externalLinkIcon","slug":"externallinkicon","link":"#externallinkicon","children":[]},{"level":3,"title":"navbar","slug":"navbar","link":"#navbar","children":[]},{"level":3,"title":"pageClass","slug":"pageclass","link":"#pageclass","children":[]}]},{"level":2,"title":"Home Page","slug":"home-page","link":"#home-page","children":[{"level":3,"title":"home","slug":"home","link":"#home","children":[]},{"level":3,"title":"heroImage","slug":"heroimage","link":"#heroimage","children":[]},{"level":3,"title":"heroImageDark","slug":"heroimagedark","link":"#heroimagedark","children":[]},{"level":3,"title":"heroAlt","slug":"heroalt","link":"#heroalt","children":[]},{"level":3,"title":"heroHeight","slug":"heroheight","link":"#heroheight","children":[]},{"level":3,"title":"heroText","slug":"herotext","link":"#herotext","children":[]},{"level":3,"title":"tagline","slug":"tagline","link":"#tagline","children":[]},{"level":3,"title":"actions","slug":"actions","link":"#actions","children":[]},{"level":3,"title":"features","slug":"features","link":"#features","children":[]},{"level":3,"title":"footer","slug":"footer","link":"#footer","children":[]},{"level":3,"title":"footerHtml","slug":"footerhtml","link":"#footerhtml","children":[]}]},{"level":2,"title":"Normal Page","slug":"normal-page","link":"#normal-page","children":[{"level":3,"title":"editLink","slug":"editlink","link":"#editlink","children":[]},{"level":3,"title":"editLinkPattern","slug":"editlinkpattern","link":"#editlinkpattern","children":[]},{"level":3,"title":"lastUpdated","slug":"lastupdated","link":"#lastupdated","children":[]},{"level":3,"title":"contributors","slug":"contributors","link":"#contributors","children":[]},{"level":3,"title":"sidebar","slug":"sidebar","link":"#sidebar","children":[]},{"level":3,"title":"sidebarDepth","slug":"sidebardepth","link":"#sidebardepth","children":[]},{"level":3,"title":"prev","slug":"prev","link":"#prev","children":[]},{"level":3,"title":"next","slug":"next","link":"#next","children":[]}]}],"git":{"updatedTime":1706625181000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"themes/default/frontmatter.md"}');export{Te as comp,Ae as data};
diff --git a/assets/frontmatter.html-DGKUiubT.js b/assets/frontmatter.html-DGKUiubT.js
new file mode 100644
index 0000000000..b64697963e
--- /dev/null
+++ b/assets/frontmatter.html-DGKUiubT.js
@@ -0,0 +1 @@
+import{_ as r,r as o,o as l,c as i,b as e,d as t,a as n,w as p,e as a}from"./app-3y2wReKQ.js";const m={},c=a('
The identifier of feed item, used to identify the feed item.
You should ensure every feed has a unique guid.
`,46),i=[t];function o(r,p){return s(),n("div",null,i)}const d=e(l,[["render",o],["__file","frontmatter.html.vue"]]),m=JSON.parse('{"path":"/plugins/feed/frontmatter.html","title":"Frontmatter Config","lang":"en-US","frontmatter":{"description":"Frontmatter Config You can control each feed item generation by setting page frontmatter. Additions and Removals By default, all articles are added to the feed stream. Set feed:...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/frontmatter.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Frontmatter Config"}],["meta",{"property":"og:description","content":"Frontmatter Config You can control each feed item generation by setting page frontmatter. Additions and Removals By default, all articles are added to the feed stream. Set feed:..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Frontmatter Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Additions and Removals","slug":"additions-and-removals","link":"#additions-and-removals","children":[]},{"level":2,"title":"Frontmatter Information","slug":"frontmatter-information","link":"#frontmatter-information","children":[{"level":3,"title":"title","slug":"title","link":"#title","children":[]},{"level":3,"title":"description","slug":"description","link":"#description","children":[]},{"level":3,"title":"date","slug":"date","link":"#date","children":[]},{"level":3,"title":"article","slug":"article","link":"#article","children":[]},{"level":3,"title":"copyright","slug":"copyright","link":"#copyright","children":[]},{"level":3,"title":"cover / image / banner","slug":"cover-image-banner","link":"#cover-image-banner","children":[]}]},{"level":2,"title":"Frontmatter Options","slug":"frontmatter-options","link":"#frontmatter-options","children":[{"level":3,"title":"feed.title","slug":"feed-title","link":"#feed-title","children":[]},{"level":3,"title":"feed.description","slug":"feed-description","link":"#feed-description","children":[]},{"level":3,"title":"feed.content","slug":"feed-content","link":"#feed-content","children":[]},{"level":3,"title":"feed.author","slug":"feed-author","link":"#feed-author","children":[]},{"level":3,"title":"feed.contributor","slug":"feed-contributor","link":"#feed-contributor","children":[]},{"level":3,"title":"feed.guid","slug":"feed-guid","link":"#feed-guid","children":[]}]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/feed/frontmatter.md"}');export{d as comp,m as data};
diff --git a/assets/getter.html-Bl6IaHjG.js b/assets/getter.html-Bl6IaHjG.js
new file mode 100644
index 0000000000..6cece238f2
--- /dev/null
+++ b/assets/getter.html-Bl6IaHjG.js
@@ -0,0 +1,91 @@
+import{_ as s,o as e,c as n,e as a}from"./app-3y2wReKQ.js";const l={},t=a(`
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
+}
+
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
+}
+
`,46),i=[t];function r(p,o){return e(),n("div",null,i)}const d=s(l,[["render",r],["__file","getter.html.vue"]]),u=JSON.parse('{"path":"/plugins/feed/getter.html","title":"Feed Getter","lang":"en-US","frontmatter":{"description":"Feed Getter You can take full control of feed items generation by setting getter in the plugin options. getter.title Type: (page: Page) => string Item title getter getter.link T...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/getter.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/getter.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Feed Getter"}],["meta",{"property":"og:description","content":"Feed Getter You can take full control of feed items generation by setting getter in the plugin options. getter.title Type: (page: Page) => string Item title getter getter.link T..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Feed Getter\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"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}]},"autoDesc":true,"filePathRelative":"plugins/feed/getter.md"}');export{d as comp,u as data};
diff --git a/assets/getter.html-zrG8Ss32.js b/assets/getter.html-zrG8Ss32.js
new file mode 100644
index 0000000000..d5681a76b8
--- /dev/null
+++ b/assets/getter.html-zrG8Ss32.js
@@ -0,0 +1,91 @@
+import{_ as s,o as e,c as n,e as a}from"./app-3y2wReKQ.js";const l={},t=a(`
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.
This attribute would also include contributors to the files listed in gitInclude.
`,24);function C(b,v){const p=a("NpmBadge"),n=a("RouteLink"),l=a("ExternalLinkIcon");return c(),d("div",null,[h,t(p,{package:"@vuepress/plugin-git"}),g,s("p",null,[e("The "),t(n,{to:"/themes/default/config.html#lastupdated"},{default:o(()=>[e("lastUpdated")]),_:1}),e(" and "),t(n,{to:"/themes/default/config.html#contributors"},{default:o(()=>[e("contributors")]),_:1}),e(" of default theme is powered by this plugin.")]),m,s("p",null,[e("This plugin requires your project to be inside a "),s("a",D,[e("Git Repository"),t(l)]),e(", so that it can collect information from the commit history.")]),s("p",null,[e("You should ensure all commits are available when building your site. For example, CI workflows usually clone your repository with "),s("a",y,[e("--depth 1"),t(l)]),e(" to avoid fetching all commits, so you should disable the behavior to make this plugin work properly in CI.")]),f])}const E=r(u,[["render",C],["__file","git.html.vue"]]),x=JSON.parse('{"path":"/plugins/git.html","title":"git","lang":"en-US","frontmatter":{"description":"git","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/git.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/git.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"git"}],["meta",{"property":"og:description","content":"git"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"git\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"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":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/git.md"}');export{E as comp,x as data};
diff --git a/assets/git.html-BiuM6jA2.js b/assets/git.html-BiuM6jA2.js
new file mode 100644
index 0000000000..4e7b345bc2
--- /dev/null
+++ b/assets/git.html-BiuM6jA2.js
@@ -0,0 +1,30 @@
+import{_ as r,r as t,o as c,c as d,a,b as s,d as e,w as p,e as o}from"./app-3y2wReKQ.js";const u={},D=s("h1",{id:"git",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#git"},[s("span",null,"git")])],-1),h=s("p",null,"该插件会收集你的页面的 Git 信息,包括创建和更新时间、贡献者等。",-1),g=o(`
`,24);function f(b,k){const i=t("NpmBadge"),n=t("RouteLink"),l=t("ExternalLinkIcon");return c(),d("div",null,[D,a(i,{package:"@vuepress/plugin-git"}),h,s("p",null,[e("默认主题的 "),a(n,{to:"/zh/themes/default/config.html#lastupdated"},{default:p(()=>[e("lastUpdated")]),_:1}),e(" 和 "),a(n,{to:"/zh/themes/default/config.html#contributors"},{default:p(()=>[e("contributors")]),_:1}),e(" 就是由该插件支持的。")]),g,s("p",null,[e("该插件要求你的项目在 "),s("a",m,[e("Git 仓库"),a(l)]),e(" 下,这样它才能从提交历史记录中收集信息。")]),s("p",null,[e("在构建站点时,你应该确保所有的提交记录是可以获取到的。举例来说, CI 工作流通常会在克隆你的仓库时添加 "),s("a",y,[e("--depth 1"),a(l)]),e(" 参数来避免拉取全部的提交记录,因此你需要禁用这个功能,以便该插件在 CI 可以中正常使用。")]),C])}const x=r(u,[["render",f],["__file","git.html.vue"]]),E=JSON.parse('{"path":"/zh/plugins/git.html","title":"git","lang":"zh-CN","frontmatter":{"description":"git","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/git.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/git.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"git"}],["meta",{"property":"og:description","content":"git"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"git\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"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":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/git.md"}');export{x as comp,E as data};
diff --git a/assets/google-analytics.html-BMdoT1JC.js b/assets/google-analytics.html-BMdoT1JC.js
new file mode 100644
index 0000000000..06188a4c8d
--- /dev/null
+++ b/assets/google-analytics.html-BMdoT1JC.js
@@ -0,0 +1,26 @@
+import{_ as p,r as t,o as c,c as r,a as n,b as e,d as s,e as a}from"./app-3y2wReKQ.js";const i={},d=e("h1",{id:"google-analytics",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#google-analytics"},[e("span",null,"google-analytics")])],-1),g={href:"https://analytics.google.com/",target:"_blank",rel:"noopener noreferrer"},u={href:"https://developers.google.com/analytics/devguides/collection/gtagjs",target:"_blank",rel:"noopener noreferrer"},y={href:"https://support.google.com/analytics/answer/10089681",target:"_blank",rel:"noopener noreferrer"},h=a(`
`,4),D={href:"https://support.google.com/analytics/answer/9234069",target:"_blank",rel:"noopener noreferrer"},m=e("code",null,"page_view",-1),_=e("code",null,"first_visit",-1),f=e("p",null,[s("So if you only want to collect some basic data of your site, you don't need to do anything else except setting the "),e("a",{href:"#id"},"Measurement ID"),s(" correctly.")],-1),C=e("code",null,"gtag()",-1),v=e("code",null,"window",-1),b={href:"https://developers.google.com/analytics/devguides/collection/ga4/events",target:"_blank",rel:"noopener noreferrer"},k=e("h2",{id:"options",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#options"},[e("span",null,"Options")])],-1),E=e("h3",{id:"id",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#id"},[e("span",null,"id")])],-1),x=e("li",null,[e("p",null,[s("Type: "),e("code",null,"string")])],-1),A=e("p",null,"Details:",-1),X=e("p",null,[s("The Measurement ID of Google Analytics 4, which should start with "),e("code",null,"'G-'"),s(".")],-1),w={href:"https://support.google.com/analytics/answer/9539598",target:"_blank",rel:"noopener noreferrer"},j=e("li",null,[e("p",null,"Example:")],-1),V=a(`
`,1);function G(M,U){const o=t("NpmBadge"),l=t("ExternalLinkIcon");return c(),r("div",null,[d,n(o,{package:"@vuepress/plugin-google-analytics"}),e("p",null,[s("Integrate "),e("a",g,[s("Google Analytics"),n(l)]),s(" into VuePress.")]),e("p",null,[s("This plugin will import "),e("a",u,[s("gtag.js"),n(l)]),s(" for "),e("a",y,[s("Google Analytics 4"),n(l)]),s(".")]),h,e("p",null,[s("Google Analytics will "),e("a",D,[s("automatically collect some events"),n(l)]),s(", such as "),m,s(", "),_,s(", etc.")]),f,e("p",null,[s("After using this plugin, the global "),C,s(" function is available on the "),v,s(" object, and you can use it for "),e("a",b,[s("custom events reporting"),n(l)]),s(".")]),k,E,e("ul",null,[x,e("li",null,[A,X,e("p",null,[s("You can follow the instructions "),e("a",w,[s("here"),n(l)]),s(' 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).')])]),j]),V,e("ul",null,[F,e("li",null,[I,e("p",null,[s("Set to "),N,s(" to enable sending events to DebugView. "),e("a",P,[s("See more information on DebugView"),n(l)]),s(".")])]),S]),T])}const O=p(i,[["render",G],["__file","google-analytics.html.vue"]]),R=JSON.parse('{"path":"/plugins/google-analytics.html","title":"google-analytics","lang":"en-US","frontmatter":{"description":"google-analytics","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/google-analytics.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/google-analytics.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"google-analytics"}],["meta",{"property":"og:description","content":"google-analytics"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-06T12:45:47.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-06T12:45:47.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"google-analytics\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-06T12:45:47.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[{"level":3,"title":"Reporting Events","slug":"reporting-events","link":"#reporting-events","children":[]}]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"id","slug":"id","link":"#id","children":[]},{"level":3,"title":"debug","slug":"debug","link":"#debug","children":[]}]}],"git":{"updatedTime":1707223547000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/google-analytics.md"}');export{O as comp,R as data};
diff --git a/assets/google-analytics.html-L3Yxu37H.js b/assets/google-analytics.html-L3Yxu37H.js
new file mode 100644
index 0000000000..860e2c0904
--- /dev/null
+++ b/assets/google-analytics.html-L3Yxu37H.js
@@ -0,0 +1,26 @@
+import{_ as p,r as o,o as c,c as r,a as n,b as s,d as e,e as a}from"./app-3y2wReKQ.js";const i={},d=s("h1",{id:"google-analytics",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#google-analytics"},[s("span",null,"google-analytics")])],-1),g={href:"https://analytics.google.com/",target:"_blank",rel:"noopener noreferrer"},u={href:"https://developers.google.com/analytics/devguides/collection/gtagjs",target:"_blank",rel:"noopener noreferrer"},y={href:"https://support.google.com/analytics/answer/10089681",target:"_blank",rel:"noopener noreferrer"},h=a(`
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:
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.
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:
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.
`,16),f={href:"https://ogp.me/",target:"_blank",rel:"noopener noreferrer"},x=e("strong",null,"O",-1),b=e("strong",null,"G",-1),C=e("strong",null,"Pr",-1),k=e("p",null,[t("This plugin perfectly supports this protocol and will automatically generate "),e("code",null,""),t(" tags that conform to the protocol.")],-1),E={href:"https://www.w3.org/TR/json-ld-api/",target:"_blank",rel:"noopener noreferrer"},w=e("p",null,'This plugin will generate "NewsArticle" scheme for article pages.',-1),_={href:"https://www.w3.org/TR/rdfa-primer/",target:"_blank",rel:"noopener noreferrer"},v={href:"https://schema.org/",target:"_blank",rel:"noopener noreferrer"},O=e("p",null,"Schema definition site for structural markup",-1),S=e("h2",{id:"related-tools",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#related-tools"},[e("span",null,"Related Tools")])],-1),P={href:"https://search.google.com/test/rich-results",target:"_blank",rel:"noopener noreferrer"};function T(j,A){const n=o("ExternalLinkIcon"),r=o("RouteLink"),c=o("ProjectLink");return p(),d("div",null,[h,e("p",null,[t("This plugin will make your site fully support "),e("a",u,[t("Open Content Protocol OGP"),a(n)]),t(" and "),e("a",y,[t("JSON-LD 1.1"),a(n)]),t(" to enhance the SEO of the site.")]),m,e("p",null,[t("For detailed parameter structure, see "),a(r,{to:"/plugins/seo/config.html"},{default:s(()=>[t("Config")]),_:1}),t(".")]),D,e("ul",null,[e("li",null,[e("p",null,[e("a",f,[t("Open Content Protocol OGP"),a(n)]),t(" ("),x,t("pen "),b,t("raph "),C,t("otocol)")]),k]),e("li",null,[e("p",null,[e("a",E,[t("JSON-LD 1.1"),a(n)])]),w]),e("li",null,[e("p",null,[e("a",_,[t("RDFa 1.1"),a(n)])]),e("p",null,[t("RDFa mainly marks HTML structure. This is what the plugin cannot support. "),a(c,{type:"theme",name:"hope"},{default:s(()=>[t("vuepress-theme-hope")]),_:1}),t(" uses this feature to pass Google's rich media structure test. You can consider using it.")])]),e("li",null,[e("p",null,[e("a",v,[t("Schema.Org"),a(n)])]),O])]),S,e("p",null,[t("You can use "),e("a",P,[t("Google Rich Media Structure Test Tool"),a(n)]),t(" to test this site.")])])}const G=i(g,[["render",T],["__file","guide.html.vue"]]),L=JSON.parse('{"path":"/plugins/seo/guide.html","title":"Guide","lang":"en-US","frontmatter":{"description":"Guide This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site. Out of Box The plugin works out of the box. Without...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/seo/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"Guide This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site. Out of Box The plugin works out of the box. Without..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-10T14:51:27.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-10T14:51:27.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-10T14:51:27.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Out of Box","slug":"out-of-box","link":"#out-of-box","children":[{"level":3,"title":"Default OGP Generation","slug":"default-ogp-generation","link":"#default-ogp-generation","children":[]},{"level":3,"title":"Default JSON-LD Generation","slug":"default-json-ld-generation","link":"#default-json-ld-generation","children":[]}]},{"level":2,"title":"Setting Tags Directly","slug":"setting-tags-directly","link":"#setting-tags-directly","children":[]},{"level":2,"title":"Customize Generation","slug":"customize-generation","link":"#customize-generation","children":[{"level":3,"title":"Page Type","slug":"page-type","link":"#page-type","children":[]},{"level":3,"title":"OGP","slug":"ogp","link":"#ogp","children":[]},{"level":3,"title":"JSON-LD","slug":"json-ld","link":"#json-ld","children":[]}]},{"level":2,"title":"Canonical Link","slug":"canonical-link","link":"#canonical-link","children":[{"level":3,"title":"Customize head Tags","slug":"customize-head-tags","link":"#customize-head-tags","children":[]}]},{"level":2,"title":"SEO Introduction","slug":"seo-introduction","link":"#seo-introduction","children":[]},{"level":2,"title":"Related Documents","slug":"related-documents","link":"#related-documents","children":[]},{"level":2,"title":"Related Tools","slug":"related-tools","link":"#related-tools","children":[]}],"git":{"updatedTime":1710082287000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"plugins/seo/guide.md"}');export{G as comp,L as data};
diff --git a/assets/guide.html-BBYPiwMZ.js b/assets/guide.html-BBYPiwMZ.js
new file mode 100644
index 0000000000..5241fcd3f2
--- /dev/null
+++ b/assets/guide.html-BBYPiwMZ.js
@@ -0,0 +1,9 @@
+import{_ as e,o as s,c as t,e as a}from"./app-3y2wReKQ.js";const o={},p=a(`
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.
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):
Provide search engine spiders with links of the entire site;
Provide some links for search engine spiders to dynamic pages or pages that are difficult to reach by other methods;
If a visitor attempts to access a URL that does not exist within the site's domain, the visitor will be directed to a "file not found" error page, and the sitemap can be used as a navigation page.
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: /
+
`,26),n=[i];function l(p,r){return t(),a("div",null,n)}const d=e(s,[["render",l],["__file","guide.html.vue"]]),h=JSON.parse('{"path":"/plugins/sitemap/guide.html","title":"Guide","lang":"en-US","frontmatter":{"description":"Guide 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. I...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/sitemap/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"Guide 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. I..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-31T17:59:51.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-31T17:59:51.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-31T17:59:51.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Control Sitemap Link","slug":"control-sitemap-link","link":"#control-sitemap-link","children":[]},{"level":2,"title":"Output Location","slug":"output-location","link":"#output-location","children":[]},{"level":2,"title":"Change Frequency","slug":"change-frequency","link":"#change-frequency","children":[]},{"level":2,"title":"Priority","slug":"priority","link":"#priority","children":[]},{"level":2,"title":"Modify Time","slug":"modify-time","link":"#modify-time","children":[]},{"level":2,"title":"Sitemap Intro","slug":"sitemap-intro","link":"#sitemap-intro","children":[]}],"git":{"updatedTime":1706723991000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/sitemap/guide.md"}');export{d as comp,h as data};
diff --git a/assets/guide.html-BbcE5NPQ.js b/assets/guide.html-BbcE5NPQ.js
new file mode 100644
index 0000000000..7f54520e82
--- /dev/null
+++ b/assets/guide.html-BbcE5NPQ.js
@@ -0,0 +1 @@
+import{_ as d,r as a,o as c,c as i,b as e,d as t,a as o,w as s,e as r}from"./app-3y2wReKQ.js";const h={},p=r('
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
Demo
import { blogPlugin } from '@vuepress/plugin-blog'
+
+export default {
+ name: 'vuepress-theme-xxx',
+ plugins: [
+ blogPlugin({
+ filter: ({ filePathRelative, frontmatter }) => {
+ // drop those pages which is NOT generated from file
+ if (!filePathRelative) return false
+
+ // drop those pages in \`archives\` directory
+ if (filePathRelative.startsWith('archives/')) return false
+
+ // drop those pages which do not use default layout
+ if (frontmatter.home || frontmatter.layout) return false
+
+ return true
+ },
+
+ getInfo: ({ frontmatter, git = {}, data = {} }) => {
+ // getting page info
+ const info: Record<string, any> = {
+ author: frontmatter.author || '',
+ categories: frontmatter.categories || [],
+ date: frontmatter.date || git.createdTime || null,
+ tags: frontmatter.tags || [],
+ excerpt: data.excerpt || '',
+ }
+
+ return info
+ },
+ }),
+ // other plugins ...
+ ],
+}
+
Basically, you would want 2 types of collection in your blog:
Category:
"Category" means grouping articles with their labels.
For example, each article may have their "categories" and "tags".
Type:
"Type" means identifying articles with conditions.
For example, you may want to describe some of your articles as diary.
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
Let's start with 2 examples here.
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
interface BlogFrontmatterOptions {
+ /** Current type of the page */
+ type: 'category' | 'type'
+ /** Unique key under current category or tag */
+ key: string
+ /**
+ * Current category name
+ *
+ * @description Only available in category item page
+ */
+ name?: string
+}
+
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
Also, you can pass key you want as argument, then you will get information bind to that key.
So with node side settings above, you can get information about "tag" and "star" in client side:
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
Excerpt introduction
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default <!-- more -->, and you can customize it by setting excerptSeparator option.
If it cannot find a valid separator, it will parse content from the beginning of markdown file, and stop till its length reaches a preset value. The value is default 300, and you can customize it by setting excerptLength option.
To choose which page should generate excerpt, you can use excerptFilter option.
Example
Normally you may want to use frontmatter.description if users set them, so you can let filter function return false if frontmatter.description is not empty.
`,12);function C(u,v){const n=t("RouteLink");return c(),r("div",null,[D,o("p",null,[s("See, setting these 2 types is easy. For full options, please see "),a(n,{to:"/plugins/blog/config.html#blog-category-config"},{default:l(()=>[s("Category Config")]),_:1}),s(" and "),a(n,{to:"/plugins/blog/config.html#blog-type-config"},{default:l(()=>[s("Type Config")]),_:1}),s(".")]),y,o("p",null,[s("For return types, please see "),a(n,{to:"/plugins/blog/config.html#composition-api"},{default:l(()=>[s("Composition API Return Types")]),_:1}),s(".")]),d])}const g=e(i,[["render",C],["__file","guide.html.vue"]]),b=JSON.parse(`{"path":"/plugins/blog/guide.html","title":"Guide","lang":"en-US","frontmatter":{"title":"Guide","icon":"lightbulb","description":"With @vuepress/plugin-blog, you can easily bring blog feature into your theme. Collecting Articles The plugin filters all pages using filter option to drop pages you don't want....","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/blog/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"With @vuepress/plugin-blog, you can easily bring blog feature into your theme. Collecting Articles The plugin filters all pages using filter option to drop pages you don't want...."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-19T18:01:19.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-19T18:01:19.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-19T18:01:19.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Collecting Articles","slug":"collecting-articles","link":"#collecting-articles","children":[]},{"level":2,"title":"Gathering Info","slug":"gathering-info","link":"#gathering-info","children":[]},{"level":2,"title":"Customizing Categories and Types","slug":"customizing-categories-and-types","link":"#customizing-categories-and-types","children":[]},{"level":2,"title":"Using Composition API in Client-side","slug":"using-composition-api-in-client-side","link":"#using-composition-api-in-client-side","children":[]},{"level":2,"title":"I18n Support","slug":"i18n-support","link":"#i18n-support","children":[]},{"level":2,"title":"Generating Excerpt","slug":"generating-excerpt","link":"#generating-excerpt","children":[]}],"git":{"updatedTime":1708365679000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/blog/guide.md"}`);export{g as comp,b as data};
diff --git a/assets/guide.html-C0muE5Ge.js b/assets/guide.html-C0muE5Ge.js
new file mode 100644
index 0000000000..7e871da690
--- /dev/null
+++ b/assets/guide.html-C0muE5Ge.js
@@ -0,0 +1,23 @@
+import{_ as r,r as l,o as c,c as i,b as e,d as s,a as o,w as p,e as t}from"./app-3y2wReKQ.js";const d={},u=t('
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:
Convert the date of creating the feed to ISOString and write it into channel.pubDate
The update period of the content set in channel.ttl (unit: minutes)
Set copyright information via channel.copyright
Set the channel author via channel.author.
',5),m=e("h2",{id:"feed-generation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#feed-generation"},[e("span",null,"Feed Generation")])],-1),y=e("p",null,"By default, all articles are added to the feed stream.",-1),_=e("code",null,"feed",-1),v=e("code",null,"getter",-1),x=e("h3",{id:"i18n-config",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#i18n-config"},[e("span",null,"I18n Config")])],-1),S=e("p",null,"The plugin generates separate feeds for each language.",-1),b=e("p",null,[t("You can provide different settings for different languages via "),e("code",null,"locales"),t(" in the plugin options.")],-1);function k(w,C){const i=s("ExternalLinkIcon"),o=s("RouteLink");return d(),c("div",null,[p,e("p",null,[t("When you open the feed file in browser, we magically convert atom and rss feed xml to human readable html via xsl template. Check "),e("a",u,[t("atom"),n(i)]),t(" and "),e("a",f,[t("rss"),n(i)]),t(" feed of this site as an example!")]),g,e("p",null,[t("For detailed options and their default values, see "),n(o,{to:"/plugins/feed/channel.html"},{default:a(()=>[t("Channel Config")]),_:1})]),m,y,e("p",null,[t("You can set "),_,t(" and other options in page frontmatter to control contents of feed item. See "),n(o,{to:"/plugins/feed/frontmatter.html"},{default:a(()=>[t("Frontmatter Config")]),_:1}),t(" for how they are converted.")]),e("p",null,[t("You can take full control of feed items generation by configuring the "),v,t(" in the plugin options. For detailed options and their default values, see "),n(o,{to:"/plugins/feed/getter.html"},{default:a(()=>[t("Configuration → Feed Getter")]),_:1}),t(".")]),x,S,b])}const T=r(h,[["render",k],["__file","guide.html.vue"]]),N=JSON.parse('{"path":"/plugins/feed/guide.html","title":"Guide","lang":"en-US","frontmatter":{"description":"Guide Usage The plugin can generate feed files in the following three formats for you: Atom 1.0 JSON 1.1 RSS 2.0 Please set atom, json or rss to true in the plugin options accor...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"Guide Usage The plugin can generate feed files in the following three formats for you: Atom 1.0 JSON 1.1 RSS 2.0 Please set atom, json or rss to true in the plugin options accor..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-31T04:19:29.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-31T04:19:29.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-31T04:19:29.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Readable Preview","slug":"readable-preview","link":"#readable-preview","children":[]},{"level":2,"title":"Channel settings","slug":"channel-settings","link":"#channel-settings","children":[]},{"level":2,"title":"Feed Generation","slug":"feed-generation","link":"#feed-generation","children":[{"level":3,"title":"I18n Config","slug":"i18n-config","link":"#i18n-config","children":[]}]}],"git":{"updatedTime":1706674769000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/feed/guide.md"}');export{T as comp,N as data};
diff --git a/assets/guide.html-Dt9fgK9S.js b/assets/guide.html-Dt9fgK9S.js
new file mode 100644
index 0000000000..46b5b6d8a9
--- /dev/null
+++ b/assets/guide.html-Dt9fgK9S.js
@@ -0,0 +1,215 @@
+import{_ as e,r as t,o as c,c as r,b as o,d as s,a,w as l,e as p}from"./app-3y2wReKQ.js";const D={},i=p(`
To make your website fully compliant with PWA, a Web app manifests [3] file is needed, and your pwa should satisfy the installability [4] specification.
You can set manifest option to customize the manifest file, or provide a manifest.webmanifest or manifest.json in public folder. The former has higher priority.
The plugin will automatically generate manifest.webmanifest for you and add manifest link declaration in each page, while you should still at least set a valid icon through manifest.icons or other icon related options in the PWA plugin.
WARNING
The installability [4:1] specification requires at least one valid icon to be declared in the manifest.
So if you do not configure manifest.icons, visitors can only enjoy the offline accessibility brought by the Service Worker cache, while cannot install your site as a PWA.
Besides the plugin does not process anything in the manifest by default, but outputs them as-is. This means that if you plan to deploy to a subdirectory, you should append the URL prefix to manifest Urls yourself. If everything you need is all under base directory, you can set appendBase: true in plugin options to let the plugin append base to any links in manifest.
By default, the plugin will pre-cache all jscss files, and only homepage and 404 html are cached. The plugin will also cache font files (woff, woff2, eot, ttf, otf) and SVG icons.
If you have small sites, and would like to make document fully offline available, you can set cacheHTML to true to cache all HTML files.
Why only home and 404 page been cached by default?
Though VuePress generates HTML files through SSG[5] for all pages, these files are mainly used for SEO[6] and allow you to directly configure the backend without SPA[7] Visit any link.
VuePress is essentially an SPA. This means that you only need to cache the home page and enter from the home page to access all pages normally. Therefore, not caching other HTML by default can effectively reduce the cache size (40% smaller in size) and speed up the SW update speed.
But this also has the disadvantage. If the user enters the site directly from a non-home page, the HTML file for the first page still needs to be loaded from the internet. Also, in offline environment, users can only enter through the homepage and then navigate to the corresponding page by themselves. If they directly access a link, an inaccessible prompt will appear.
To prevent large files from being included in the pre-cache list, any files > 2 MB or images > 1 MB will be omitted. You can customize these limits with maxSize and maxImageSize options (in KB unit).
We provide the update option to control how users receive updates.
The default value of the update option is "available", which means that when new content available, the new SW will be installed and its resources will be fetched silently in the background. A pop-up window appears once the new SW is ready, and users can choose whether to refresh immediately to view new content. This means users are reading old content before a new SW is ready.
If your project is still in building stage, and you want to alert the user that he may be reading outdated content, you can set this to "hint". This allows users to be notified that new content has been published within seconds after visiting docs. But the negative effect of this is that if the user chooses to update before the new SW is ready, he will need to get all the resources of the page from the internet before the new SW installs and controls the page.
If your docs are stable, or you're hosting a blog and don't care much about users receiving the latest version right away, you can set this to "disabled", which means that the new SW will be installed completely silently in the background and start waiting, when all pages controlled by old SW are all closed, the new SW will start to take control and provide users with new content during next visit. This setting can prevent users from being disturbed during the visit.
To speed up user access under weak or no network conditions through SW, but also want users to always access new content, you can set this option to "force". This means any old SW will be removed as soon as a new SW is detected, and all pages are refreshed to ensure the user is browsing the latest content. The biggest disadvantage is that all users will experience unexpected sudden refresh within seconds after reentering an updated site.
When new content is detected (new SW detected), a update found popup appears; and when the new content is ready, an update ready popup appears.
If you are not satisfied with the default popup content, you can use your own component. Import PwaFoundPopup or PwaReadyPopup from @vuepress/plugin-pwa/client and use its slot to customize the popup content, then pass the component path to foundComponent or readyComponent option:
`,31),v=e("code",null,"generateSwConfig",-1),b=e("code",null,"workbox-build",-1),w=e("h2",{id:"further-reading",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#further-reading"},[e("span",null,"Further Reading")])],-1),D=e("p",null,"For more details, please see:",-1),_={href:"https://web.dev/progressive-web-apps/",target:"_blank",rel:"noopener noreferrer"},k={href:"https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps",target:"_blank",rel:"noopener noreferrer"},C={href:"https://w3c.github.io/manifest/",target:"_blank",rel:"noopener noreferrer"},W=e("hr",{class:"footnotes-sep"},null,-1),S={class:"footnotes"},P={class:"footnotes-list"},x={id:"footnote1",class:"footnote-item"},T=e("p",null,[e("strong",null,"PWA introduction")],-1),A=e("p",null,"PWA, full name Progressive Web app. PWA standard is stipulated by W3C.",-1),E=e("p",null,"It allows sites to install the site as an App on supported platform through a browser that supports this feature.",-1),F={href:"https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps",target:"_blank",rel:"noopener noreferrer"},q=e("a",{href:"#footnote-ref1",class:"footnote-backref"},"↩︎",-1),I=n('
Service Worker Introduction
The Service Worker will get and cache all the files registered in it during the registration process.
After the registration complete, the Service Worker is activated, and starts to proxy and control all your requests.
Whenever you want to initiate an access request through the browser, the Service Worker will check whether it exists in its own cache list, if it exists, it will directly return the cached result, otherwise it will call its own fetch method to get it. You can use a custom fetch method to fully control the result of the request for resources in the web page, such as providing a fallback web page when offline.
Every time the user reopens the site, the Service Worker will request to the link when it was registered. If a new version of Service Worker is detected, it will update itself and start caching the list of resources registered in the new Service Worker . After the content update is successfully obtained, the Service Worker will trigger the update event. The user can be notified through this event, for example, a pop-up window will be displayed in the lower right corner, prompting the user that new content is available and allowing the user to trigger an update.
',1),M={id:"footnote3",class:"footnote-item"},z=e("p",null,[e("strong",null,"Manifest File")],-1),N=e("p",null,"The manifest file uses the JSON format and is responsible for declaring various information of the PWA, such as name, description, icon, and shortcut actions.",-1),R=e("p",null,"In order for your site to be registered as a PWA, you need to meet the basic specifications of the manifest to make the browser consider the site as an installable PWA and allow users to install it.",-1),V={class:"custom-container tip"},j=e("p",{class:"custom-container-title"},"TIP",-1),G={href:"https://developer.mozilla.org/en-US/docs/Web/Manifest",target:"_blank",rel:"noopener noreferrer"},B={href:"https://w3c.github.io/manifest/",target:"_blank",rel:"noopener noreferrer"},L=e("a",{href:"#footnote-ref3",class:"footnote-backref"},"↩︎",-1),O=n('
Installable
To let the site be registered as a PWA, the site needs to successfully register a valid service worker by itself, and declare a valid manifest file with its link in meta tag.
The manifest file should contain at least name (or short_name) iconsstart_url.
On safari, the maximum cache size of the service worker is 50 MB. ↩︎↩︎
SPA: Single Page Application, most of them only have the homepage, and use history mode to handle routing instead of actually navigating between pages. ↩︎
',4);function U(H,J){const t=l("ExternalLinkIcon"),a=l("RouteLink");return p(),c("div",null,[h,e("p",null,[s("This plugin uses "),e("a",u,[s("workbox-build"),o(t)]),s(" to generate service worker file, and uses "),e("a",f,[s("register-service-worker"),o(t)]),s(" to register service worker.")]),e("div",g,[y,e("p",null,[s("If you enabled this plugin once and you want to disable it, you might need "),o(a,{to:"/plugins/remove-pwa.html"},{default:r(()=>[s("`@vuepress/plugin-remove-pwa")]),_:1}),s(" to remove the existing service worker.")])]),m,e("p",null,[s("The plugin also provides other PWA-related options, such as Microsoft tile icon and color settings, Apple icon and so on. If you are an advanced user, you can also set "),v,s(" to configure "),b,s(". Check "),o(a,{to:"/plugins/pwa/config.html#options"},{default:r(()=>[s("Plugin options")]),_:1}),s(" for more details.")]),w,D,e("ul",null,[e("li",null,[e("a",_,[s("Google PWA"),o(t)])]),e("li",null,[e("a",k,[s("MDN PWA"),o(t)])]),e("li",null,[e("a",C,[s("W3C Manifest Specification"),o(t)])])]),W,e("section",S,[e("ol",P,[e("li",x,[T,A,E,e("p",null,[s("See "),e("a",F,[s("https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps"),o(t)]),s(" for details. "),q])]),I,e("li",M,[z,N,R,e("div",V,[j,e("p",null,[s("For Manifest standards and specifications, please see "),e("a",G,[s("MDN Web app manifests"),o(t)]),s(" and "),e("a",B,[s("W3C Manifest"),o(t)]),s(".")])]),L]),O])])])}const Z=i(d,[["render",U],["__file","guide.html.vue"]]),K=JSON.parse('{"path":"/plugins/pwa/guide.html","title":"Guide","lang":"en-US","frontmatter":{"description":"Guide Intro Make your VuePress site a Progressive Web Application (PWA)[1]. This plugin uses workbox-build to generate service worker file, and uses register-service-worker to r...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/pwa/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/pwa/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"Guide Intro Make your VuePress site a Progressive Web Application (PWA)[1]. This plugin uses workbox-build to generate service worker file, and uses register-service-worker to r..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-20T02:57:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-20T02:57:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-20T02:57:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Intro","slug":"intro","link":"#intro","children":[]},{"level":2,"title":"Web App Manifests","slug":"web-app-manifests","link":"#web-app-manifests","children":[]},{"level":2,"title":"Cache Control","slug":"cache-control","link":"#cache-control","children":[{"level":3,"title":"Default cache","slug":"default-cache","link":"#default-cache","children":[]},{"level":3,"title":"Image Cache","slug":"image-cache","link":"#image-cache","children":[]},{"level":3,"title":"HTML Cache","slug":"html-cache","link":"#html-cache","children":[]},{"level":3,"title":"Size Control","slug":"size-control","link":"#size-control","children":[]}]},{"level":2,"title":"Update Control","slug":"update-control","link":"#update-control","children":[{"level":3,"title":"Popups","slug":"popups","link":"#popups","children":[]}]},{"level":2,"title":"Other Options","slug":"other-options","link":"#other-options","children":[]},{"level":2,"title":"Further Reading","slug":"further-reading","link":"#further-reading","children":[]}],"git":{"updatedTime":1708397875000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/pwa/guide.md"}');export{Z as comp,K as data};
diff --git a/assets/guide.html-VxwP9sGA.js b/assets/guide.html-VxwP9sGA.js
new file mode 100644
index 0000000000..2495d1f454
--- /dev/null
+++ b/assets/guide.html-VxwP9sGA.js
@@ -0,0 +1,29 @@
+import{_ as p,r as i,o as r,c as d,b as e,d as n,a as s,w as o,e as a}from"./app-3y2wReKQ.js";const m={},u=e("h1",{id:"guide",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#guide"},[e("span",null,"Guide")])],-1),h=e("h2",{id:"setting-options",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#setting-options"},[e("span",null,"Setting Options")])],-1),g={href:"https://vuejs.press/guide/configuration.html#client-config-file",target:"_blank",rel:"noopener noreferrer"},v=a(`
But here are some limitations you should remember:
`,5),y=e("p",null,[e("code",null,"provider"),n(", locales and other resource related option must be set in plugin options.")],-1),f=e("p",null,"To ensure tree-shaking works, we must optimize entries at node so that bundler can understand which resource should be included in the final bundle.",-1),b=e("p",null,"Options which can not be serialized to JSON must be set in client config.",-1),D=e("p",null,"Options that receives function values can not be set in plugin options, as plugins are running under Node.js environment, so we can not pass these values and their contexts to browser.",-1),C=a('
This plugin globally registers a component <CommentService />.
If you are a user, you should use alias and layout slots to insert the component. We recommended you to insert the comment component (<CommentService />) after the <PageNav /> component, and the current page is a demo with default theme.
If you are a theme developer, you should insert this component in the layout of your theme.
By default, <CommentService /> component is enabled globally, and you can use comment option in both plugin options and page frontmatter to control it.
You can disable it locally by setting comment: false in page frontmatter.
To keep it globally disabled, please set comment to false in the plugin options. Then you can set comment: true in page frontmatter to enable it locally.
You can set commentID option in page frontmatter to customize comment ID, which is used to identify comment storage item to use for a page. By default it will be the path of the page, which means if you are deploying the site to multiple places, page with same content across sites will share the same comment data.
Details: Whether to enable comment feature by default.
',3);function E(O,S){const c=i("ExternalLinkIcon"),l=i("Badge"),t=i("RouteLink");return r(),d("div",null,[u,h,e("p",null,[n("You can both set options with plugin options on Node side and set options in "),e("a",g,[n("client config file"),s(c)]),n(" on Browser side.")]),v,e("ul",null,[e("li",null,[y,f,e("p",null,[n("These options will be marked with "),s(l,{text:"Plugin Option Only",type:"warning",vertical:"baseline"}),n(" in config reference.")])]),e("li",null,[b,D,e("p",null,[n("These options will be marked with "),s(l,{text:"Client Config Only",type:"warning",vertical:"baseline"}),n(" in config reference.")])])]),C,e("p",null,[n("Currently, you can choose from "),s(t,{to:"/plugins/comment/giscus/"},{default:o(()=>[n("Giscus")]),_:1}),n(", "),s(t,{to:"/plugins/comment/waline/"},{default:o(()=>[n("Waline")]),_:1}),n(", "),s(t,{to:"/plugins/comment/artalk/"},{default:o(()=>[n("Artalk")]),_:1}),n(" and "),s(t,{to:"/plugins/comment/twikoo/"},{default:o(()=>[n("Twikoo")]),_:1}),n(".")]),_,k,e("h3",w,[e("a",x,[e("span",null,[n("provider "),s(l,{text:"Plugin Option Only",type:"warning"})])])]),A])}const N=p(m,[["render",E],["__file","guide.html.vue"]]),P=JSON.parse('{"path":"/plugins/comment/guide.html","title":"Guide","lang":"en-US","frontmatter":{"layout":"CommentPage","description":"Guide Setting Options You can both set options with plugin options on Node side and set options in client config file on Browser side. With Plugin Options With Client Config Fil...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/guide.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/guide.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Guide"}],["meta",{"property":"og:description","content":"Guide Setting Options You can both set options with plugin options on Node side and set options in client config file on Browser side. With Plugin Options With Client Config Fil..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Guide\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Setting Options","slug":"setting-options","link":"#setting-options","children":[{"level":3,"title":"With Plugin Options","slug":"with-plugin-options","link":"#with-plugin-options","children":[]},{"level":3,"title":"With Client Config File","slug":"with-client-config-file","link":"#with-client-config-file","children":[]}]},{"level":2,"title":"Adding Comment","slug":"adding-comment","link":"#adding-comment","children":[]},{"level":2,"title":"Available Comment Services","slug":"available-comment-services","link":"#available-comment-services","children":[]},{"level":2,"title":"Common Options","slug":"common-options","link":"#common-options","children":[{"level":3,"title":"provider","slug":"provider","link":"#provider","children":[]},{"level":3,"title":"comment","slug":"comment","link":"#comment","children":[]}]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/guide.md"}');export{N as comp,P as data};
diff --git a/assets/guide.html-mXmqiSUm.js b/assets/guide.html-mXmqiSUm.js
new file mode 100644
index 0000000000..3cf4ec0466
--- /dev/null
+++ b/assets/guide.html-mXmqiSUm.js
@@ -0,0 +1,37 @@
+import{_ as r,r as n,o as d,c as i,b as e,d as t,a as s,w as o,e as l}from"./app-3y2wReKQ.js";const h={},g=e("h1",{id:"指南",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#指南"},[e("span",null,"指南")])],-1),D=e("code",null,"",-1),y={href:"https://ogp.me/",target:"_blank",rel:"noopener noreferrer"},m={href:"https://www.w3.org/TR/json-ld-api/",target:"_blank",rel:"noopener noreferrer"},u=l(`
`,3);function m(d,y){const s=a("NpmBadge");return n(),p("div",null,[c,l(s,{package:"@vuepress/plugin-sitemap"}),i])}const u=t(r,[["render",m],["__file","index.html.vue"]]),D=JSON.parse('{"path":"/zh/plugins/sitemap/","title":"sitemap","lang":"zh-CN","frontmatter":{"description":"sitemap","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/sitemap/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"sitemap"}],["meta",{"property":"og:description","content":"sitemap"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"sitemap\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/sitemap/README.md"}');export{u as comp,D as data};
diff --git a/assets/index.html-Bb1yOMrB.js b/assets/index.html-Bb1yOMrB.js
new file mode 100644
index 0000000000..99a0a16ad9
--- /dev/null
+++ b/assets/index.html-Bb1yOMrB.js
@@ -0,0 +1 @@
+import{_ as t,r as s,o,c as l,a}from"./app-3y2wReKQ.js";const r={};function n(c,m){const e=s("Catalog");return o(),l("div",null,[a(e)])}const p=t(r,[["render",n],["__file","index.html.vue"]]),h=JSON.parse('{"path":"/zh/tools/","title":"Tools","lang":"en-US","frontmatter":{"title":"Tools","head":[["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[],"git":{},"filePathRelative":null}');export{p as comp,h as data};
diff --git a/assets/index.html-BejIaMKb.js b/assets/index.html-BejIaMKb.js
new file mode 100644
index 0000000000..eadf8b8083
--- /dev/null
+++ b/assets/index.html-BejIaMKb.js
@@ -0,0 +1,11 @@
+import{_ as a,r as t,o as n,c as o,a as p,b as e,e as l}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"feed",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#feed"},[e("span",null,"feed")])],-1),i=l(`
`,3);function d(m,g){const s=t("NpmBadge");return n(),o("div",null,[c,l(s,{package:"@vuepress/plugin-blog"}),i])}const u=a(r,[["render",d],["__file","index.html.vue"]]),h=JSON.parse('{"path":"/plugins/blog/","title":"blog","lang":"en-US","frontmatter":{"description":"blog","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/blog/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/blog/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"blog"}],["meta",{"property":"og:description","content":"blog"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-05T09:34:12.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-05T09:34:12.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"blog\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-05T09:34:12.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1707125652000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/blog/README.md"}');export{u as comp,h as data};
diff --git a/assets/index.html-BvEj3V-h.js b/assets/index.html-BvEj3V-h.js
new file mode 100644
index 0000000000..af456e280e
--- /dev/null
+++ b/assets/index.html-BvEj3V-h.js
@@ -0,0 +1,2 @@
+import{_ as i,a as c,b as r,c as p,d,e as m,f as h}from"./vercel-9-BeG_WJ35.js";import{_ as u,r as a,o as g,c as y,b as e,d as t,a as o,w as _,e as s}from"./app-3y2wReKQ.js";const v="/ecosystem/assets/leancloud-app-1-D7FJuXTc.jpg",b="/ecosystem/assets/leancloud-app-2-DRHKDfZN.jpg",f="/ecosystem/images/comment/vercel-2.png",k={},w=s(`
Enter the app, then select Settings > App Keys at the left bottom corner. You will see APP ID, APP Key and Master Key of your app. We will use them later
',1),j=e("h2",{id:"deploy-to-vercel-server",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#deploy-to-vercel-server"},[e("span",null,"Deploy to Vercel (Server)")])],-1),L={href:"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwalinejs%2Fwaline%2Ftree%2Fmain%2Fexample",target:"_blank",rel:"noopener noreferrer"},T=e("img",{src:"https://vercel.com/button",alt:"Vercel"},null,-1),N=s('
Click the dark button above, it will redirect you to vercel to deploy with waline template.
TIP
If you haven't logged in, we recommend you to sign in with GitHub.
Input your Vercel project name then click Create.
Repo which named you input before will be created and initialized automatically base on waline example template by Vercel.
After one minute or two, vercel should finish the deployment. Click Go to Dashboard button to redirect to your application dashboard.
Click Settings menu on the top, and Environment Variables button on the side to go to environment variables setting page. Then set LEAN_ID, LEAN_KEY and LEAN_MASTER_KEY. The variables' value should be the ones you got in the previous step. APP ID is the value of LEAN_ID, and APP Key to LEAN_KEY, Master Key to LEAN_MASTER_KEY.
To let your environment variables setting active, you need redeploy your application. Click Deployments menu on the top and find the latest deployment at the top of list, click Redeploy button in the right dropdown menu.
If everything is ok, vercel will redirect to Overview page to start redeployment. Wait a moment the STATUS will change to Ready. Now you can click Visit to visit the site. This link is your server address.
Set provider: "Waline" in the plugin options, and set serverURL as the link obtained in the previous step.
Then, place the <CommentService> component at a suitable location in your site (usually at the bottom of the page), you will be able to see the comment box.
',7),I={class:"custom-container tip"},V=e("p",{class:"custom-container-title"},"TIP",-1),P=e("code",null,"el",-1),R=e("h2",{id:"comment-management-management",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#comment-management-management"},[e("span",null,"Comment Management (Management)")])],-1),M=e("ol",null,[e("li",null,[t("After the deployment is complete, please visit "),e("code",null,"/ui/register"),t(" to register. The first person to register will be set as an administrator.")]),e("li",null,"After you log in as administrator, you can see the comment management interface. You can edit, mark or delete comments here."),e("li",null,"Users can also register their account through comment box, and they will be redirected to their profile page after logging in.")],-1);function F(K,W){const n=a("ExternalLinkIcon"),l=a("RouteLink");return g(),y("div",null,[w,e("ol",null,[e("li",null,[e("p",null,[e("a",C,[t("sign in"),o(n)]),t(" or "),e("a",A,[t("sign up"),o(n)]),t(" LeanCloud and enter "),e("a",x,[t("Console"),o(n)]),t(".")])]),e("li",null,[e("p",null,[t("Click "),e("a",E,[t("Create app"),o(n)]),t(" button to create a new app and enter a name you like:")]),D]),S]),j,e("p",null,[e("a",L,[T,o(n)])]),N,e("div",I,[V,e("p",null,[t("You can also pass in other options supported by Waline (except "),P,t("). For details, see "),o(l,{to:"/plugins/comment/waline/config.html"},{default:_(()=>[t("Waline Config")]),_:1})])]),R,M])}const O=u(k,[["render",F],["__file","index.html.vue"]]),z=JSON.parse('{"path":"/plugins/comment/waline/","title":"Waline","lang":"en-US","frontmatter":{"description":"Waline A safe comment system with backend. Install LeanCloud Settings (Database) sign in or sign up LeanCloud and enter Console. Click Create app button to create a new app and ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/waline/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Waline"}],["meta",{"property":"og:description","content":"Waline A safe comment system with backend. Install LeanCloud Settings (Database) sign in or sign up LeanCloud and enter Console. Click Create app button to create a new app and ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://vercel.com/button"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Waline\\",\\"image\\":[\\"https://vercel.com/button\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-2.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-3.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-4.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-5.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-6.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-7.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-8.png\\",\\"https://ecosystem.vuejs.press/ecosystem/images/comment/vercel-9.png\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Install","slug":"install","link":"#install","children":[]},{"level":2,"title":"LeanCloud Settings (Database)","slug":"leancloud-settings-database","link":"#leancloud-settings-database","children":[]},{"level":2,"title":"Deploy to Vercel (Server)","slug":"deploy-to-vercel-server","link":"#deploy-to-vercel-server","children":[]},{"level":2,"title":"Assign Domain (Optional)","slug":"assign-domain-optional","link":"#assign-domain-optional","children":[]},{"level":2,"title":"Client","slug":"client","link":"#client","children":[{"level":3,"title":"Using plugin","slug":"using-plugin","link":"#using-plugin","children":[]}]},{"level":2,"title":"Comment Management (Management)","slug":"comment-management-management","link":"#comment-management-management","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/waline/README.md"}');export{O as comp,z as data};
diff --git a/assets/index.html-Bw42ek0H.js b/assets/index.html-Bw42ek0H.js
new file mode 100644
index 0000000000..08b0547c3a
--- /dev/null
+++ b/assets/index.html-Bw42ek0H.js
@@ -0,0 +1,2 @@
+import{_ as a,a as r,b as i,c as p,d,e as m,f as h}from"./vercel-9-BeG_WJ35.js";import{_ as u,r as n,o as _,c as g,b as e,d as t,a as o,w as y,e as l}from"./app-3y2wReKQ.js";const v="/ecosystem/assets/leancloud-1-D6GvqV4-.png",f="/ecosystem/assets/leancloud-2-B5wKvXiY.png",b="/ecosystem/assets/leancloud-3-D7gbeXS0.png",k="/ecosystem/images/comment/vercel-1.png",x={},A=l(`
`,3);function d(m,y){const s=t("NpmBadge");return n(),o("div",null,[c,p(s,{package:"@vuepress/plugin-seo"}),i])}const h=a(r,[["render",d],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/plugins/seo/","title":"seo","lang":"en-US","frontmatter":{"description":"seo","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/seo/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/seo/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"seo"}],["meta",{"property":"og:description","content":"seo"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"seo\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/seo/README.md"}');export{h as comp,g as data};
diff --git a/assets/index.html-CWz01FIO.js b/assets/index.html-CWz01FIO.js
new file mode 100644
index 0000000000..978e3d17cf
--- /dev/null
+++ b/assets/index.html-CWz01FIO.js
@@ -0,0 +1 @@
+import{_ as s,r as o,o as n,c as a,a as r,b as e}from"./app-3y2wReKQ.js";const l={},p=e("h1",{id:"plugins",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#plugins"},[e("span",null,"Plugins")])],-1);function c(i,m){const t=o("Catalog");return n(),a("div",null,[p,r(t,{level:1})])}const d=s(l,[["render",c],["__file","index.html.vue"]]),h=JSON.parse('{"path":"/plugins/","title":"Plugins","lang":"en-US","frontmatter":{"description":"Plugins","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Plugins"}],["meta",{"property":"og:description","content":"Plugins"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-19T17:42:27.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-19T17:42:27.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Plugins\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-19T17:42:27.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[],"git":{"updatedTime":1708364547000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/README.md"}');export{d as comp,h as data};
diff --git a/assets/index.html-Cm94z7-j.js b/assets/index.html-Cm94z7-j.js
new file mode 100644
index 0000000000..8b42b7473f
--- /dev/null
+++ b/assets/index.html-Cm94z7-j.js
@@ -0,0 +1,11 @@
+import{_ as a,r as t,o as n,c as p,a as o,b as e,e as l}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"sitemap",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#sitemap"},[e("span",null,"sitemap")])],-1),i=l(`
`,3);function m(d,y){const s=t("NpmBadge");return n(),p("div",null,[c,o(s,{package:"@vuepress/plugin-sitemap"}),i])}const h=a(r,[["render",m],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/plugins/sitemap/","title":"sitemap","lang":"en-US","frontmatter":{"description":"sitemap","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/sitemap/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"sitemap"}],["meta",{"property":"og:description","content":"sitemap"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"sitemap\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/sitemap/README.md"}');export{h as comp,g as data};
diff --git a/assets/index.html-D-CeYnT_.js b/assets/index.html-D-CeYnT_.js
new file mode 100644
index 0000000000..74fdeaba9b
--- /dev/null
+++ b/assets/index.html-D-CeYnT_.js
@@ -0,0 +1,10 @@
+import{_ as r,r as s,o as c,c as i,b as e,d as o,a as t,w as p,e as n}from"./app-3y2wReKQ.js";const d={},h={href:"https://curl.qcloud.com/KnnJtUom",target:"_blank",rel:"noopener noreferrer"},u=n(`
`,3);function d(m,g){const s=a("NpmBadge");return n(),l("div",null,[c,o(s,{package:"@vuepress/plugin-blog"}),i])}const h=t(r,[["render",d],["__file","index.html.vue"]]),u=JSON.parse('{"path":"/zh/plugins/blog/","title":"blog","lang":"zh-CN","frontmatter":{"description":"blog","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/blog/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/blog/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"blog"}],["meta",{"property":"og:description","content":"blog"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-05T09:34:12.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-05T09:34:12.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"blog\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-05T09:34:12.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]}],"git":{"updatedTime":1707125652000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/blog/README.md"}');export{h as comp,u as data};
diff --git a/assets/index.html-DIaKO10i.js b/assets/index.html-DIaKO10i.js
new file mode 100644
index 0000000000..3d390034ce
--- /dev/null
+++ b/assets/index.html-DIaKO10i.js
@@ -0,0 +1,9 @@
+import{_ as t,r as a,o as n,c as l,a as o,b as e,e as p}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"theme-default",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#theme-default"},[e("span",null,"theme-default")])],-1),i=e("h2",{id:"usage",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#usage"},[e("span",null,"Usage")])],-1),d=p(`
Install @vuepress/theme-default :
npm install @vuepress/theme-default@next
+
import { defaultTheme } from '@vuepress/theme-default'
+
+export default {
+ theme: defaultTheme({
+ // set theme config here
+ }),
+}
+
`,3);function m(h,u){const s=a("NpmBadge");return n(),l("div",null,[c,i,o(s,{package:"@vuepress/theme-default"}),d])}const f=t(r,[["render",m],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/themes/default/","title":"theme-default","lang":"en-US","frontmatter":{"description":"theme-default Usage","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"theme-default"}],["meta",{"property":"og:description","content":"theme-default Usage"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-05T09:20:19.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-05T09:20:19.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"theme-default\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-05T09:20:19.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1707124819000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"themes/default/README.md"}');export{f as comp,g as data};
diff --git a/assets/index.html-DOjbibox.js b/assets/index.html-DOjbibox.js
new file mode 100644
index 0000000000..cf4f2f0349
--- /dev/null
+++ b/assets/index.html-DOjbibox.js
@@ -0,0 +1,11 @@
+import{_ as t,r as n,o as a,c as o,a as l,b as e,e as p}from"./app-3y2wReKQ.js";const c={},r=e("h1",{id:"comment",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#comment"},[e("span",null,"comment")])],-1),i=p(`
`,3);function m(d,y){const s=n("NpmBadge");return a(),o("div",null,[r,l(s,{package:"@vuepress/plugin-comment"}),i])}const u=t(c,[["render",m],["__file","index.html.vue"]]),D=JSON.parse('{"path":"/zh/plugins/comment/","title":"comment","lang":"zh-CN","frontmatter":{"description":"comment","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"comment"}],["meta",{"property":"og:description","content":"comment"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"comment\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/comment/README.md"}');export{u as comp,D as data};
diff --git a/assets/index.html-DT7zhwMS.js b/assets/index.html-DT7zhwMS.js
new file mode 100644
index 0000000000..b34ed42fdb
--- /dev/null
+++ b/assets/index.html-DT7zhwMS.js
@@ -0,0 +1,11 @@
+import{_ as t,r as n,o as a,c as o,a as p,b as e,e as l}from"./app-3y2wReKQ.js";const c={},r=e("h1",{id:"comment",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#comment"},[e("span",null,"comment")])],-1),i=l(`
`,3);function m(d,y){const s=n("NpmBadge");return a(),o("div",null,[r,p(s,{package:"@vuepress/plugin-comment"}),i])}const h=t(c,[["render",m],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/plugins/comment/","title":"comment","lang":"en-US","frontmatter":{"description":"comment","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"comment"}],["meta",{"property":"og:description","content":"comment"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"comment\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/README.md"}');export{h as comp,g as data};
diff --git a/assets/index.html-DXT1ftSK.js b/assets/index.html-DXT1ftSK.js
new file mode 100644
index 0000000000..9e00d725fb
--- /dev/null
+++ b/assets/index.html-DXT1ftSK.js
@@ -0,0 +1 @@
+import{_ as t,r as s,o,c as l,a}from"./app-3y2wReKQ.js";const r={};function n(c,m){const e=s("Catalog");return o(),l("div",null,[a(e)])}const p=t(r,[["render",n],["__file","index.html.vue"]]),_=JSON.parse('{"path":"/tools/","title":"Tools","lang":"en-US","frontmatter":{"title":"Tools","head":[["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[],"git":{},"filePathRelative":null}');export{p as comp,_ as data};
diff --git a/assets/index.html-DZrgbeU6.js b/assets/index.html-DZrgbeU6.js
new file mode 100644
index 0000000000..d049c9ca60
--- /dev/null
+++ b/assets/index.html-DZrgbeU6.js
@@ -0,0 +1 @@
+import{_ as n,r,o as a,c,a as t,b as e,w as l,d as s}from"./app-3y2wReKQ.js";const h={},i=e("h1",{id:"vuepress-helper",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#vuepress-helper"},[e("span",null,"@vuepress/helper")])],-1),u=e("p",null,"此包为 VuePress 开发者提供辅助函数。",-1),m=e("p",null,[e("code",null,"@vuepress/helper"),s(": Node.js 一侧的辅助函数。")],-1),d=e("code",null,"@vuepress/helper/client",-1),_=e("code",null,"@vuepress/helper/shared",-1);function y(f,v){const p=r("NpmBadge"),o=r("RouteLink");return a(),c("div",null,[i,t(p,{package:"@vuepress/helper"}),u,e("ul",null,[e("li",null,[m,e("ul",null,[e("li",null,[t(o,{to:"/zh/tools/helper/node/bundler.html"},{default:l(()=>[s("打包器相关")]),_:1})]),e("li",null,[t(o,{to:"/zh/tools/helper/node/page.html"},{default:l(()=>[s("页面相关")]),_:1})])])]),e("li",null,[e("p",null,[t(o,{to:"/zh/tools/helper/client.html"},{default:l(()=>[d]),_:1}),s(": 客户端一侧的辅助函数。")])]),e("li",null,[e("p",null,[t(o,{to:"/zh/tools/helper/shared.html"},{default:l(()=>[_]),_:1}),s(": Node.js 和客户端共享的辅助函数。")])])])])}const x=n(h,[["render",y],["__file","index.html.vue"]]),z=JSON.parse('{"path":"/zh/tools/helper/","title":"@vuepress/helper","lang":"zh-CN","frontmatter":{"description":"@vuepress/helper","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/tools/helper/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/tools/helper/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"@vuepress/helper"}],["meta",{"property":"og:description","content":"@vuepress/helper"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:34:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:34:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"@vuepress/helper\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:34:35.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[],"git":{"updatedTime":1706960075000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/tools/helper/README.md"}');export{x as comp,z as data};
diff --git a/assets/index.html-DbE9LrPE.js b/assets/index.html-DbE9LrPE.js
new file mode 100644
index 0000000000..5a74d17626
--- /dev/null
+++ b/assets/index.html-DbE9LrPE.js
@@ -0,0 +1,2 @@
+import{_ as n,r as a,o as c,c as p,b as t,d as e,a as r,w as i,e as s}from"./app-3y2wReKQ.js";const d={},h=s(`
`,3);function d(m,y){const s=a("NpmBadge");return n(),l("div",null,[c,o(s,{package:"@vuepress/plugin-feed"}),i])}const u=t(r,[["render",d],["__file","index.html.vue"]]),D=JSON.parse('{"path":"/zh/plugins/feed/","title":"feed","lang":"zh-CN","frontmatter":{"description":"feed","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/feed/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/feed/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"feed"}],["meta",{"property":"og:description","content":"feed"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-01T04:46:03.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T04:46:03.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"feed\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T04:46:03.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]}],"git":{"updatedTime":1706762763000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/feed/README.md"}');export{u as comp,D as data};
diff --git a/assets/index.html-DjfbyjAT.js b/assets/index.html-DjfbyjAT.js
new file mode 100644
index 0000000000..c4609239c8
--- /dev/null
+++ b/assets/index.html-DjfbyjAT.js
@@ -0,0 +1,11 @@
+import{_ as a,r as t,o as n,c as p,a as l,b as e,e as o}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"pwa",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#pwa"},[e("span",null,"pwa")])],-1),i=o(`
`,3);function d(m,y){const s=t("NpmBadge");return n(),p("div",null,[c,l(s,{package:"@vuepress/plugin-pwa"}),i])}const u=a(r,[["render",d],["__file","index.html.vue"]]),D=JSON.parse('{"path":"/zh/plugins/pwa/","title":"pwa","lang":"zh-CN","frontmatter":{"description":"pwa","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/pwa/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/pwa/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"pwa"}],["meta",{"property":"og:description","content":"pwa"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-19T18:06:19.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-19T18:06:19.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"pwa\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-19T18:06:19.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]}],"git":{"updatedTime":1708365979000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/pwa/README.md"}');export{u as comp,D as data};
diff --git a/assets/index.html-DvQe47f4.js b/assets/index.html-DvQe47f4.js
new file mode 100644
index 0000000000..a68193c7a7
--- /dev/null
+++ b/assets/index.html-DvQe47f4.js
@@ -0,0 +1,2 @@
+import{_ as l,r as a,o as i,c,b as t,d as e,a as o,w as p,e as n}from"./app-3y2wReKQ.js";const d={},m=n(`
`,6),h={href:"https://artalk.js.org/guide/deploy.html",target:"_blank",rel:"noopener noreferrer"},u=t("h2",{id:"configuration",tabindex:"-1"},[t("a",{class:"header-anchor",href:"#configuration"},[t("span",null,"Configuration")])],-1),y=t("p",null,[e("Please set "),t("code",null,'provider: "Artalk"'),e(" and pass your server link to "),t("code",null,"server"),e(" in the plugin options.")],-1),k=n('
TIP
The plugin retains the el option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the pageTitle, pageKey and site options for you according to the VuePress information.
To let Artalk apply the correct theme, you need to pass a boolean value to <CommentService /> through darkmode prop, representing whether the dark mode is currently enabled.
',3);function g(f,v){const r=a("ExternalLinkIcon"),s=a("RouteLink");return i(),c("div",null,[m,t("p",null,[e("See the "),t("a",h,[e("Artalk documentation"),o(r)]),e(".")]),u,y,t("p",null,[e("For other configuration items, see "),o(s,{to:"/plugins/comment/artalk/config.html"},{default:p(()=>[e("Artalk Config")]),_:1}),e(".")]),k])}const A=l(d,[["render",g],["__file","index.html.vue"]]),x=JSON.parse('{"path":"/plugins/comment/artalk/","title":"Artalk","lang":"en-US","frontmatter":{"description":"Artalk Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page. Come to your blog, or anywhere, place the Artal...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/artalk/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Artalk"}],["meta",{"property":"og:description","content":"Artalk Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page. Come to your blog, or anywhere, place the Artal..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Artalk\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Install","slug":"install","link":"#install","children":[]},{"level":2,"title":"Deploy Artalk Server","slug":"deploy-artalk-server","link":"#deploy-artalk-server","children":[]},{"level":2,"title":"Configuration","slug":"configuration","link":"#configuration","children":[]},{"level":2,"title":"Darkmode","slug":"darkmode","link":"#darkmode","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/artalk/README.md"}');export{A as comp,x as data};
diff --git a/assets/index.html-Dvizd_ni.js b/assets/index.html-Dvizd_ni.js
new file mode 100644
index 0000000000..96084c624a
--- /dev/null
+++ b/assets/index.html-Dvizd_ni.js
@@ -0,0 +1,9 @@
+import{_ as t,r as a,o as n,c as o,a as l,b as e,e as p}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"默认主题",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#默认主题"},[e("span",null,"默认主题")])],-1),i=e("h2",{id:"使用方法",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#使用方法"},[e("span",null,"使用方法")])],-1),d=p(`
`,4);function m(h,y){const s=a("NpmBadge");return n(),o("div",null,[c,i,l(s,{package:"@vuepress/theme-default"}),d])}const D=t(r,[["render",m],["__file","index.html.vue"]]),f=JSON.parse('{"path":"/zh/themes/default/","title":"默认主题","lang":"zh-CN","frontmatter":{"description":"默认主题 使用方法","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/themes/default/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"默认主题"}],["meta",{"property":"og:description","content":"默认主题 使用方法"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-05T09:20:19.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-05T09:20:19.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"默认主题\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-05T09:20:19.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]}],"git":{"updatedTime":1707124819000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/themes/default/README.md"}');export{D as comp,f as data};
diff --git a/assets/index.html-EC7JbQ-d.js b/assets/index.html-EC7JbQ-d.js
new file mode 100644
index 0000000000..19c3239eb8
--- /dev/null
+++ b/assets/index.html-EC7JbQ-d.js
@@ -0,0 +1 @@
+import{_ as c,r as a,o as r,c as l,b as e,d as t,a as o,w as p,e as n}from"./app-3y2wReKQ.js";const d={},m=e("h1",{id:"giscus",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#giscus"},[e("span",null,"Giscus")])],-1),u=e("p",null,"Giscus is a commenting system based on GitHub Discussion that is easy to start.",-1),h=e("h2",{id:"preparation",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#preparation"},[e("span",null,"Preparation")])],-1),g=e("li",null,[e("p",null,"Create a public repository and open discussion panel as a place to store comments.")],-1),y={href:"https://github.com/apps/giscus",target:"_blank",rel:"noopener noreferrer"},f={href:"https://giscus.app",target:"_blank",rel:"noopener noreferrer"},_=e("p",null,[t('You just need to fill in the repository and Discussion categories, then scroll to the "Enable giscus" section at the bottom of the page and obtain four attributes: '),e("code",null,"data-repo"),t(", "),e("code",null,"data-repo-id"),t(", "),e("code",null,"data-category"),t(" and "),e("code",null,"data-category-id"),t(".")],-1),b=n('
Please set provider: "Giscus" and pass data-repo, data-repo-id, data-category and data-category-id as plugin options as repo, repoId, categorycategoryId.
By default, the theme of Giscus is light or dark (based on darkmode status).
Darkmode
To let Giscus apply the correct theme, you need to pass a boolean value to <CommentService /> via darkmode property, indicating whether darkmode is currently enabled.
If you want to customize theme in lightmode and darkmode, you can set lightTheme and darkTheme option with a built-in theme keyword or a custom CSS link starting with https://.
',4);function v(x,G){const s=a("ExternalLinkIcon"),i=a("RouteLink");return r(),l("div",null,[m,u,h,e("ol",null,[g,e("li",null,[e("p",null,[t("Install the "),e("a",y,[t("Giscus App"),o(s)]),t(" to have permission to access the corresponding repository.")])]),e("li",null,[e("p",null,[t("After completing the above steps, please go to the "),e("a",f,[t("Giscus page"),o(s)]),t(" to get your settings.")]),_])]),b,e("p",null,[t("For other options, see "),o(i,{to:"/plugins/comment/giscus/config.html"},{default:p(()=>[t("Giscus Config")]),_:1}),t(".")]),k])}const E=c(d,[["render",v],["__file","index.html.vue"]]),P=JSON.parse('{"path":"/plugins/comment/giscus/","title":"Giscus","lang":"en-US","frontmatter":{"description":"Giscus Giscus is a commenting system based on GitHub Discussion that is easy to start. Preparation Create a public repository and open discussion panel as a place to store comme...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/giscus/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Giscus"}],["meta",{"property":"og:description","content":"Giscus Giscus is a commenting system based on GitHub Discussion that is easy to start. Preparation Create a public repository and open discussion panel as a place to store comme..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Giscus\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Preparation","slug":"preparation","link":"#preparation","children":[]},{"level":2,"title":"Config","slug":"config","link":"#config","children":[]},{"level":2,"title":"Theme","slug":"theme","link":"#theme","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/giscus/README.md"}');export{E as comp,P as data};
diff --git a/assets/index.html-NvxGbn4M.js b/assets/index.html-NvxGbn4M.js
new file mode 100644
index 0000000000..9923fee664
--- /dev/null
+++ b/assets/index.html-NvxGbn4M.js
@@ -0,0 +1,2 @@
+import{_ as a,r as s,o as r,c as i,b as e,d as t,a as o,w as c,e as p}from"./app-3y2wReKQ.js";const d={},m=e("h1",{id:"twikoo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#twikoo"},[e("span",null,"Twikoo")])],-1),h={href:"https://curl.qcloud.com/KnnJtUom",target:"_blank",rel:"noopener noreferrer"},u=p(`
`,3),g={href:"https://www.mongodb.com/cloud/atlas/register",target:"_blank",rel:"noopener noreferrer"},f=e("li",null,[e("p",null,[t("Create a free MongoDB database, the recommended region is "),e("code",null,"AWS / N. Virginia (us-east-1)")])],-1),_={href:"https://vercel.com/support/articles/how-to-allowlist-deployment-ip-address",target:"_blank",rel:"noopener noreferrer"},y=e("code",null,"",-1),k={href:"https://vercel.com/signup",target:"_blank",rel:"noopener noreferrer"},v=e("p",null,"Click the button below to deploy Twikoo to Vercel in one click",-1),b={href:"https://vercel.com/import/project?template=https://github.com/imaegoo/twikoo/tree/dev/src/vercel-min",target:"_blank",rel:"noopener noreferrer"},w=e("img",{src:"https://vercel.com/button",alt:"Vercel"},null,-1),x=e("li",null,[e("p",null,[t("Go to Settings - Environment Variables, add the environment variable "),e("code",null,"MONGODB_URI"),t(", the value is the database connection string in step 3")])],-1),D=e("li",null,[e("p",null,'Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt "Twikoo cloud function is running normally"')],-1),C=e("li",null,[e("p",null,[t("Vercel Domains (with "),e("code",null,"https://"),t(" prefix, e.g. "),e("code",null,"https://xxx.vercel.app"),t(") is your environment ID")])],-1),T=e("h2",{id:"configuration",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#configuration"},[e("span",null,"Configuration")])],-1),E=e("p",null,[t("Please set "),e("code",null,'provider: "Twikoo"'),t(" and set "),e("code",null,"envId"),t(" in the plugin options.")],-1);function V(A,N){const n=s("ExternalLinkIcon"),l=s("RouteLink");return r(),i("div",null,[m,e("p",null,[t("A concise, safe and free static site commenting system, based on "),e("a",h,[t("Tencent Cloud Development"),o(n)]),t(".")]),u,e("ol",null,[e("li",null,[e("p",null,[t("Apply for "),e("a",g,[t("MongoDB"),o(n)]),t(" account")])]),f,e("li",null,[e("p",null,[t("Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses ("),e("a",_,[t("Why?"),o(n)]),t("), create Database user, and record the database connection string, please change the "),y,t(" in the connection string to the database password")])]),e("li",null,[e("p",null,[t("Sign up for a "),e("a",k,[t("Vercel"),o(n)]),t(" account")])]),e("li",null,[v,e("p",null,[e("a",b,[w,o(n)])])]),x,D,C]),T,E,e("p",null,[t("For other configuration items, see "),o(l,{to:"/plugins/comment/twikoo/config.html"},{default:c(()=>[t("Twikoo Config")]),_:1}),t(".")])])}const I=a(d,[["render",V],["__file","index.html.vue"]]),M=JSON.parse('{"path":"/plugins/comment/twikoo/","title":"Twikoo","lang":"en-US","frontmatter":{"description":"Twikoo A concise, safe and free static site commenting system, based on Tencent Cloud Development. Install Getting started Apply for MongoDB account Create a free MongoDB databa...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/comment/twikoo/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/comment/twikoo/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Twikoo"}],["meta",{"property":"og:description","content":"Twikoo A concise, safe and free static site commenting system, based on Tencent Cloud Development. Install Getting started Apply for MongoDB account Create a free MongoDB databa..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:image","content":"https://vercel.com/button"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-11T08:20:01.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-11T08:20:01.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Twikoo\\",\\"image\\":[\\"https://vercel.com/button\\"],\\"dateModified\\":\\"2024-03-11T08:20:01.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Install","slug":"install","link":"#install","children":[]},{"level":2,"title":"Getting started","slug":"getting-started","link":"#getting-started","children":[]},{"level":2,"title":"Configuration","slug":"configuration","link":"#configuration","children":[]}],"git":{"updatedTime":1710145201000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/comment/twikoo/README.md"}');export{I as comp,M as data};
diff --git a/assets/index.html-b3lij7_s.js b/assets/index.html-b3lij7_s.js
new file mode 100644
index 0000000000..7a66552d79
--- /dev/null
+++ b/assets/index.html-b3lij7_s.js
@@ -0,0 +1,11 @@
+import{_ as a,r as t,o as n,c as p,a as o,b as e,e as l}from"./app-3y2wReKQ.js";const r={},c=e("h1",{id:"pwa",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#pwa"},[e("span",null,"pwa")])],-1),i=l(`
`,3);function d(m,y){const s=t("NpmBadge");return n(),p("div",null,[c,o(s,{package:"@vuepress/plugin-pwa"}),i])}const h=a(r,[["render",d],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/plugins/pwa/","title":"pwa","lang":"en-US","frontmatter":{"description":"pwa","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/pwa/"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/pwa/"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"pwa"}],["meta",{"property":"og:description","content":"pwa"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-19T18:06:19.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-19T18:06:19.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"pwa\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-19T18:06:19.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]}],"git":{"updatedTime":1708365979000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/pwa/README.md"}');export{h as comp,g as data};
diff --git a/assets/leancloud-1-D6GvqV4-.png b/assets/leancloud-1-D6GvqV4-.png
new file mode 100644
index 0000000000..9ffbd2e6b3
Binary files /dev/null and b/assets/leancloud-1-D6GvqV4-.png differ
diff --git a/assets/leancloud-2-B5wKvXiY.png b/assets/leancloud-2-B5wKvXiY.png
new file mode 100644
index 0000000000..969d1a3df9
Binary files /dev/null and b/assets/leancloud-2-B5wKvXiY.png differ
diff --git a/assets/leancloud-3-D7gbeXS0.png b/assets/leancloud-3-D7gbeXS0.png
new file mode 100644
index 0000000000..4acf707598
Binary files /dev/null and b/assets/leancloud-3-D7gbeXS0.png differ
diff --git a/assets/leancloud-app-1-D7FJuXTc.jpg b/assets/leancloud-app-1-D7FJuXTc.jpg
new file mode 100644
index 0000000000..49330b3592
Binary files /dev/null and b/assets/leancloud-app-1-D7FJuXTc.jpg differ
diff --git a/assets/leancloud-app-2-DRHKDfZN.jpg b/assets/leancloud-app-2-DRHKDfZN.jpg
new file mode 100644
index 0000000000..9d4006903f
Binary files /dev/null and b/assets/leancloud-app-2-DRHKDfZN.jpg differ
diff --git a/assets/links-check.html-Bfnr55f7.js b/assets/links-check.html-Bfnr55f7.js
new file mode 100644
index 0000000000..f2e6ab9e7a
--- /dev/null
+++ b/assets/links-check.html-Bfnr55f7.js
@@ -0,0 +1,27 @@
+import{_ as n,r as l,o as a,c as p,a as o,b as s,e as t}from"./app-3y2wReKQ.js";const c={},i=s("h1",{id:"links-check",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#links-check"},[s("span",null,"links-check")])],-1),r=t(`
`,12);function d(D,u){const e=l("NpmBadge");return a(),p("div",null,[i,o(e,{package:"@vuepress/plugin-links-check"}),r])}const y=n(c,[["render",d],["__file","links-check.html.vue"]]),m=JSON.parse('{"path":"/zh/plugins/links-check.html","title":"links-check","lang":"zh-CN","frontmatter":{"description":"links-check","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/links-check.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/links-check.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"links-check"}],["meta",{"property":"og:description","content":"links-check"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"links-check\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用","slug":"使用","link":"#使用","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"dev","slug":"dev","link":"#dev","children":[]},{"level":3,"title":"build","slug":"build","link":"#build","children":[]},{"level":3,"title":"exclude","slug":"exclude","link":"#exclude","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/links-check.md"}');export{y as comp,m as data};
diff --git a/assets/links-check.html-CYZOZ0ws.js b/assets/links-check.html-CYZOZ0ws.js
new file mode 100644
index 0000000000..7b064414e8
--- /dev/null
+++ b/assets/links-check.html-CYZOZ0ws.js
@@ -0,0 +1,27 @@
+import{_ as n,r as l,o as a,c as p,a as t,b as s,e as o}from"./app-3y2wReKQ.js";const i={},c=s("h1",{id:"links-check",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#links-check"},[s("span",null,"links-check")])],-1),r=o(`
This plugin will check dead links in your markdown files.
This plugin has been integrated into the default theme.
The links that should be excluded from checking. You can use a list of strings or regular expressions, or a function that returns a boolean.
Example:
linksCheckPlugin({
+ exclude: [
+ // exclude links by string
+ '/exclude-link',
+ // exclude links by regex
+ /\\/exclude-link-regex/,
+ ],
+
+ // or exclude links by function
+ exclude: (link, isDev) => {
+ if (isDev) {
+ return link.startsWith('/exclude-link-dev')
+ }
+ return link.startsWith('/exclude-link-build')
+ },
+})
+
`,12);function d(D,u){const e=l("NpmBadge");return a(),p("div",null,[c,t(e,{package:"@vuepress/plugin-links-check"}),r])}const y=n(i,[["render",d],["__file","links-check.html.vue"]]),m=JSON.parse('{"path":"/plugins/links-check.html","title":"links-check","lang":"en-US","frontmatter":{"description":"links-check","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/links-check.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/links-check.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"links-check"}],["meta",{"property":"og:description","content":"links-check"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"links-check\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"dev","slug":"dev","link":"#dev","children":[]},{"level":3,"title":"build","slug":"build","link":"#build","children":[]},{"level":3,"title":"exclude","slug":"exclude","link":"#exclude","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/links-check.md"}');export{y as comp,m as data};
diff --git a/assets/locale.html-CHU_6CEh.js b/assets/locale.html-CHU_6CEh.js
new file mode 100644
index 0000000000..b625b31ab3
--- /dev/null
+++ b/assets/locale.html-CHU_6CEh.js
@@ -0,0 +1,21 @@
+import{_ as p,r as o,o as c,c as r,b as e,d as l,a as n,w as s,e as t}from"./app-3y2wReKQ.js";const d={},u=e("h1",{id:"语言配置",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#语言配置"},[e("span",null,"语言配置")])],-1),h=e("p",null,"这些选项用于配置与语言相关的文本。",-1),g=e("p",null,"如果你的站点是以英语以外的其他语言提供服务的,你应该为每个语言设置这些选项来提供翻译。",-1),m=e("h2",{id:"repolabel",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#repolabel"},[e("span",null,"repoLabel")])],-1),_=e("li",null,[e("p",null,[l("类型: "),e("code",null,"string")])],-1),b=e("p",null,"详情:",-1),v=e("p",null,"项目仓库的标签。",-1),D=e("p",null,[l("它将被用作 "),e("em",null,"仓库链接"),l(" 的文字。"),e("em",null,"仓库链接"),l(" 将会显示为导航栏的最后一个元素。")],-1),y=e("h2",{id:"selectlanguagetext",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#selectlanguagetext"},[e("span",null,"selectLanguageText")])],-1),x=e("li",null,[e("p",null,[l("类型: "),e("code",null,"string")])],-1),f=e("p",null,"详情:",-1),k=e("p",null,[e("em",null,"选择语言菜单"),l(" 的文字。")],-1),E={href:"https://v2.vuepress.vuejs.org/zh/config.html#locales",target:"_blank",rel:"noopener noreferrer"},C=e("em",null,"选择语言菜单",-1),w=t('
',5),G=e("li",null,[e("p",null,[l("类型: "),e("code",null,"string")])],-1),J=e("li",null,[e("p",null,[l("默认值: "),e("code",null,"'open in new window'")])],-1),O=e("p",null,"详情:",-1),q=e("code",null,"sr-only",-1),K=e("p",null,"它主要是为了站点的可访问性 (a11y) 。",-1),Q=e("p",null,"参考:",-1),X=e("h2",{id:"togglecolormode",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#togglecolormode"},[e("span",null,"toggleColorMode")])],-1),Y=e("li",null,[e("p",null,[l("类型: "),e("code",null,"string")])],-1),$=e("li",null,[e("p",null,[l("默认值: "),e("code",null,"'toggle color mode'")])],-1),ee=e("li",null,[e("p",null,"详情:"),e("p",null,"切换颜色模式按钮的标题文字。"),e("p",null,"它主要是为了站点的可访问性 (a11y) 。")],-1),le=e("p",null,"参考:",-1),ne=t('
',6);function ae(se,te){const a=o("RouteLink"),i=o("ExternalLinkIcon");return c(),r("div",null,[u,h,g,m,e("ul",null,[_,e("li",null,[b,v,D,e("p",null,[l("如果你不明确指定该配置项,它将会根据 "),n(a,{to:"/zh/themes/default/config.html#repo"},{default:s(()=>[l("repo")]),_:1}),l(" 配置项自动推断。")])])]),y,e("ul",null,[x,e("li",null,[f,k,e("p",null,[l("如果你在站点配置中设置了多个 "),e("a",E,[l("locales"),n(i)]),l(" ,那么 "),C,l(" 就会显示在导航栏中仓库按钮的旁边。")])])]),w,e("ul",null,[L,e("li",null,[A,N,e("p",null,[l("该配置项 "),e("strong",null,[l("仅能在主题配置的 "),n(a,{to:"/zh/themes/default/config.html#locales"},{default:s(()=>[l("locales")]),_:1}),l(" 的内部生效")]),l(" 。它将被用作 locale 的语言名称,展示在 "),z,l(" 内。")])]),T]),F,e("ul",null,[B,S,e("li",null,[j,e("p",null,[l("Tip "),n(a,{to:"/zh/themes/default/markdown.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%B9%E5%99%A8"},{default:s(()=>[l("自定义容器")]),_:1}),l(" 的默认标题。")])])]),I,e("ul",null,[P,V,e("li",null,[R,e("p",null,[l("Warning "),n(a,{to:"/zh/themes/default/markdown.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%B9%E5%99%A8"},{default:s(()=>[l("自定义容器")]),_:1}),l(" 的默认标题。")])])]),M,e("ul",null,[U,W,e("li",null,[H,e("p",null,[l("Danger "),n(a,{to:"/zh/themes/default/markdown.html#%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AE%B9%E5%99%A8"},{default:s(()=>[l("自定义容器")]),_:1}),l(" 的默认标题。")])])]),Z,e("ul",null,[G,J,e("li",null,[O,e("p",null,[n(a,{to:"/zh/plugins/external-link-icon.html#externallinkicon"},{default:s(()=>[l("ExternalLinkIcon")]),_:1}),l(". 链接内的 "),q,l(" 文字。")]),K]),e("li",null,[Q,e("ul",null,[e("li",null,[n(a,{to:"/zh/themes/default/plugin.html#themeplugins-externallinkicon"},{default:s(()=>[l("默认主题 > 插件配置 > themePlugins.externalLinkIcon")]),_:1})])])])]),X,e("ul",null,[Y,$,ee,e("li",null,[le,e("ul",null,[e("li",null,[n(a,{to:"/zh/themes/default/config.html#colormodeswitch"},{default:s(()=>[l("默认主题 > 配置 > colorModeSwitch")]),_:1})])])])]),ne])}const ie=p(d,[["render",ae],["__file","locale.html.vue"]]),pe=JSON.parse('{"path":"/zh/themes/default/locale.html","title":"语言配置","lang":"zh-CN","frontmatter":{"description":"语言配置 这些选项用于配置与语言相关的文本。 如果你的站点是以英语以外的其他语言提供服务的,你应该为每个语言设置这些选项来提供翻译。 repoLabel 类型: string 详情: 项目仓库的标签。 它将被用作 仓库链接 的文字。仓库链接 将会显示为导航栏的最后一个元素。 如果你不明确指定该配置项,它将会根据 配置项自动推断。 selectLangu...","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/locale.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"语言配置"}],["meta",{"property":"og:description","content":"语言配置 这些选项用于配置与语言相关的文本。 如果你的站点是以英语以外的其他语言提供服务的,你应该为每个语言设置这些选项来提供翻译。 repoLabel 类型: string 详情: 项目仓库的标签。 它将被用作 仓库链接 的文字。仓库链接 将会显示为导航栏的最后一个元素。 如果你不明确指定该配置项,它将会根据 配置项自动推断。 selectLangu..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-03-25T11:54:39.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-25T11:54:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"语言配置\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-25T11:54:39.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"repoLabel","slug":"repolabel","link":"#repolabel","children":[]},{"level":2,"title":"selectLanguageText","slug":"selectlanguagetext","link":"#selectlanguagetext","children":[]},{"level":2,"title":"selectLanguageAriaLabel","slug":"selectlanguagearialabel","link":"#selectlanguagearialabel","children":[]},{"level":2,"title":"selectLanguageName","slug":"selectlanguagename","link":"#selectlanguagename","children":[]},{"level":2,"title":"navbarLabel","slug":"navbarlabel","link":"#navbarlabel","children":[]},{"level":2,"title":"pageNavbarLabel","slug":"pagenavbarlabel","link":"#pagenavbarlabel","children":[]},{"level":2,"title":"editLinkText","slug":"editlinktext","link":"#editlinktext","children":[]},{"level":2,"title":"lastUpdatedText","slug":"lastupdatedtext","link":"#lastupdatedtext","children":[]},{"level":2,"title":"contributorsText","slug":"contributorstext","link":"#contributorstext","children":[]},{"level":2,"title":"tip","slug":"tip","link":"#tip","children":[]},{"level":2,"title":"warning","slug":"warning","link":"#warning","children":[]},{"level":2,"title":"danger","slug":"danger","link":"#danger","children":[]},{"level":2,"title":"notFound","slug":"notfound","link":"#notfound","children":[]},{"level":2,"title":"backToHome","slug":"backtohome","link":"#backtohome","children":[]},{"level":2,"title":"openInNewWindow","slug":"openinnewwindow","link":"#openinnewwindow","children":[]},{"level":2,"title":"toggleColorMode","slug":"togglecolormode","link":"#togglecolormode","children":[]},{"level":2,"title":"toggleSidebar","slug":"togglesidebar","link":"#togglesidebar","children":[]},{"level":2,"title":"prev","slug":"prev","link":"#prev","children":[]},{"level":2,"title":"next","slug":"next","link":"#next","children":[]}],"git":{"updatedTime":1711367679000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"zh/themes/default/locale.md"}');export{ie as comp,pe as data};
diff --git a/assets/locale.html-DRfrqyL2.js b/assets/locale.html-DRfrqyL2.js
new file mode 100644
index 0000000000..48748ec0e3
--- /dev/null
+++ b/assets/locale.html-DRfrqyL2.js
@@ -0,0 +1,21 @@
+import{_ as o,r as i,o as p,c,b as e,d as l,a as t,w as a,e as s}from"./app-3y2wReKQ.js";const r={},d=e("h1",{id:"locale-config",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#locale-config"},[e("span",null,"Locale Config")])],-1),u=e("p",null,"These options configure locale-related texts.",-1),h=e("p",null,"If your site is served in a different language besides English, you should set these options per locale to provide translations.",-1),g=e("h2",{id:"repolabel",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#repolabel"},[e("span",null,"repoLabel")])],-1),m=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),f=e("p",null,"Details:",-1),y=e("p",null,"Specify the repository label of your project.",-1),b=e("p",null,[l("This will be used as the text of the "),e("em",null,"repository link"),l(", which will be displayed as the last item of the navbar.")],-1),_=e("h2",{id:"selectlanguagetext",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#selectlanguagetext"},[e("span",null,"selectLanguageText")])],-1),D=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),v=e("p",null,"Details:",-1),x=e("p",null,[l("Specify the text of the "),e("em",null,"select language menu"),l(".")],-1),k=e("em",null,"select language menu",-1),T=s('
',3),C=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),w=e("p",null,"Details:",-1),E=e("p",null,"Specify the name of the language of a locale.",-1),L=e("strong",null,"only take effect inside",-1),S=e("em",null,"select language menu",-1),N=e("li",null,[e("p",null,"Example:")],-1),F=s(`
',5),Z=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),G=e("li",null,[e("p",null,[l("Default: "),e("code",null,"'open in new window'")])],-1),J=e("p",null,"Details:",-1),O=e("code",null,"sr-only",-1),q=e("p",null,"This is mainly for a11y purpose.",-1),K=e("p",null,"Also see:",-1),Q=e("h2",{id:"togglecolormode",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#togglecolormode"},[e("span",null,"toggleColorMode")])],-1),X=e("li",null,[e("p",null,[l("Type: "),e("code",null,"string")])],-1),Y=e("li",null,[e("p",null,[l("Default: "),e("code",null,"'toggle color mode'")])],-1),$=e("li",null,[e("p",null,"Details:"),e("p",null,"Title text for the color mode toggle button."),e("p",null,"This is mainly for a11y purpose.")],-1),ee=e("p",null,"Also see:",-1),le=s('
',6);function ne(te,ae){const n=i("RouteLink");return p(),c("div",null,[d,u,h,g,e("ul",null,[m,e("li",null,[f,y,b,e("p",null,[l("If you don't set this option explicitly, it will be automatically inferred from the "),t(n,{to:"/themes/default/config.html#repo"},{default:a(()=>[l("repo")]),_:1}),l(" option.")])])]),_,e("ul",null,[D,e("li",null,[v,x,e("p",null,[l("The "),k,l(" will appear next to the repository button in the navbar when you set multiple "),t(n,{to:"/themes/default/config.html#locales"},{default:a(()=>[l("locales")]),_:1}),l(" in your site config.")])])]),T,e("ul",null,[C,e("li",null,[w,E,e("p",null,[l("This option will "),L,l(" the "),t(n,{to:"/themes/default/config.html#locales"},{default:a(()=>[l("locales")]),_:1}),l(" of your theme config. It will be used as the language name of the locale, which will be displayed in the "),S,l(".")])]),N]),F,e("ul",null,[I,A,e("li",null,[j,e("p",null,[l("Specify the default title of the tip "),t(n,{to:"/themes/default/markdown.html#custom-containers"},{default:a(()=>[l("custom containers")]),_:1}),l(".")])])]),P,e("ul",null,[V,z,e("li",null,[R,e("p",null,[l("Specify the default title of the warning "),t(n,{to:"/themes/default/markdown.html#custom-containers"},{default:a(()=>[l("custom containers")]),_:1}),l(".")])])]),U,e("ul",null,[M,B,e("li",null,[H,e("p",null,[l("Specify the default title of the danger "),t(n,{to:"/themes/default/markdown.html#custom-containers"},{default:a(()=>[l("custom containers")]),_:1}),l(".")])])]),W,e("ul",null,[Z,G,e("li",null,[J,e("p",null,[l("Specify the "),O,l(" text of the "),t(n,{to:"/plugins/external-link-icon.html#externallinkicon"},{default:a(()=>[l("ExternalLinkIcon")]),_:1}),l(".")]),q]),e("li",null,[K,e("ul",null,[e("li",null,[t(n,{to:"/themes/default/plugin.html#themeplugins-externallinkicon"},{default:a(()=>[l("Default Theme > Plugin Config > themePlugins.externalLinkIcon")]),_:1})])])])]),Q,e("ul",null,[X,Y,$,e("li",null,[ee,e("ul",null,[e("li",null,[t(n,{to:"/themes/default/config.html#colormodeswitch"},{default:a(()=>[l("Default Theme > Config > colorModeSwitch")]),_:1})])])])]),le])}const oe=o(r,[["render",ne],["__file","locale.html.vue"]]),ie=JSON.parse('{"path":"/themes/default/locale.html","title":"Locale Config","lang":"en-US","frontmatter":{"description":"Locale Config 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 tr...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/locale.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Locale Config"}],["meta",{"property":"og:description","content":"Locale Config 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 tr..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-03-25T11:54:39.000Z"}],["meta",{"property":"article:modified_time","content":"2024-03-25T11:54:39.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Locale Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-03-25T11:54:39.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"repoLabel","slug":"repolabel","link":"#repolabel","children":[]},{"level":2,"title":"selectLanguageText","slug":"selectlanguagetext","link":"#selectlanguagetext","children":[]},{"level":2,"title":"selectLanguageAriaLabel","slug":"selectlanguagearialabel","link":"#selectlanguagearialabel","children":[]},{"level":2,"title":"selectLanguageName","slug":"selectlanguagename","link":"#selectlanguagename","children":[]},{"level":2,"title":"navbarLabel","slug":"navbarlabel","link":"#navbarlabel","children":[]},{"level":2,"title":"pageNavbarLabel","slug":"pagenavbarlabel","link":"#pagenavbarlabel","children":[]},{"level":2,"title":"editLinkText","slug":"editlinktext","link":"#editlinktext","children":[]},{"level":2,"title":"lastUpdatedText","slug":"lastupdatedtext","link":"#lastupdatedtext","children":[]},{"level":2,"title":"contributorsText","slug":"contributorstext","link":"#contributorstext","children":[]},{"level":2,"title":"tip","slug":"tip","link":"#tip","children":[]},{"level":2,"title":"warning","slug":"warning","link":"#warning","children":[]},{"level":2,"title":"danger","slug":"danger","link":"#danger","children":[]},{"level":2,"title":"notFound","slug":"notfound","link":"#notfound","children":[]},{"level":2,"title":"backToHome","slug":"backtohome","link":"#backtohome","children":[]},{"level":2,"title":"openInNewWindow","slug":"openinnewwindow","link":"#openinnewwindow","children":[]},{"level":2,"title":"toggleColorMode","slug":"togglecolormode","link":"#togglecolormode","children":[]},{"level":2,"title":"toggleSidebar","slug":"togglesidebar","link":"#togglesidebar","children":[]},{"level":2,"title":"prev","slug":"prev","link":"#prev","children":[]},{"level":2,"title":"next","slug":"next","link":"#next","children":[]}],"git":{"updatedTime":1711367679000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"themes/default/locale.md"}');export{oe as comp,ie as data};
diff --git a/assets/markdown.html-BgkklRLU.js b/assets/markdown.html-BgkklRLU.js
new file mode 100644
index 0000000000..88f09567ac
--- /dev/null
+++ b/assets/markdown.html-BgkklRLU.js
@@ -0,0 +1,50 @@
+import{_ as r,r as l,o as d,c as u,a as n,b as s,w as a,d as e,e as p}from"./app-3y2wReKQ.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:"自定义容器",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#自定义容器"},[s("span",null,"自定义容器")])],-1),y=p(`
::: 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
Example 2 (custom title):
Input
::: danger STOP
+Danger zone, do not proceed
+:::
+
+::: details Click me to view the code
+
+\`\`\`ts
+console.log('Hello, VuePress!')
+\`\`\`
+
+:::
+
`,17),f=s("div",{class:"language-typescript","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"})])])],-1),w=s("div",{class:"language-typescript","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"})])])],-1);function x(F,T){const p=l("NpmBadge"),o=l("RouteLink"),t=l("CodeGroupItem"),c=l("CodeGroup");return d(),u("div",null,[D,e(p,{package:"@vuepress/theme-default"}),v,s("ul",null,[s("li",null,[y,s("ul",null,[h,g,b,k,s("li",null,[n("Alias of "),e(o,{to:"/themes/default/components.html#codegroup"},{default:a(()=>[n("CodeGroup")]),_:1}),n(" and "),e(o,{to:"/themes/default/components.html#codegroupitem"},{default:a(()=>[n("CodeGroupItem")]),_:1}),n(": "),_])])]),C]),E,e(c,null,{default:a(()=>[e(t,{title:"FOO"},{default:a(()=>[f]),_:1}),e(t,{title:"BAR"},{default:a(()=>[w]),_:1})]),_:1})])}const A=r(m,[["render",x],["__file","markdown.html.vue"]]),O=JSON.parse('{"path":"/themes/default/markdown.html","title":"Markdown","lang":"en-US","frontmatter":{"description":"Markdown","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/markdown.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Markdown"}],["meta",{"property":"og:description","content":"Markdown"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Markdown\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"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}]},"autoDesc":true,"filePathRelative":"themes/default/markdown.md"}');export{A as comp,O as data};
diff --git a/assets/medium-zoom.html-CHAkQyiv.js b/assets/medium-zoom.html-CHAkQyiv.js
new file mode 100644
index 0000000000..2518751b6a
--- /dev/null
+++ b/assets/medium-zoom.html-CHAkQyiv.js
@@ -0,0 +1,31 @@
+import{_ as t,r as a,o as i,c,a as n,b as s,d as e,e as o}from"./app-3y2wReKQ.js";const r={},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=o(`
`,5),f=s("p",null,"Details:",-1),C=s("code",null,"Zoom",-1),b={href:"https://github.com/francoischalifour/medium-zoom#methods",target:"_blank",rel:"noopener noreferrer"},z=s("p",null,"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.",-1),_=s("p",null,[e("This plugin adds an extra "),s("code",null,"refresh"),e(" method on the "),s("code",null,"Zoom"),e(" instance, which will call "),s("code",null,"zoom.detach()"),e(" then "),s("code",null,"zoom.attach()"),e(" with the "),s("a",{href:"#selector"},"selector"),e(" as the default parameter. It will help you to refresh the zoomable images for current page.")],-1),k=s("li",null,[s("p",null,"Example:")],-1),x=o(`
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()
+ })
+ },
+}
+
`,1);function E(A,w){const t=l("NpmBadge"),a=l("ExternalLinkIcon");return i(),c("div",null,[m,n(t,{package:"@vuepress/plugin-medium-zoom"}),s("p",null,[e("Integrate "),s("a",d,[e("medium-zoom"),n(a)]),e(" into VuePress, which can provide the ability to zoom images.")]),u,s("ul",null,[h,y,s("li",null,[D,s("ul",null,[s("li",null,[s("a",g,[e("medium-zoom > Options"),n(a)])])])])]),v,s("ul",null,[s("li",null,[f,s("p",null,[e("Returns the "),C,e(" instance that used by this plugin, so that you can use the instance "),s("a",b,[e("methods"),n(a)]),e(" directly.")]),z,_]),k]),x])}const T=p(r,[["render",E],["__file","medium-zoom.html.vue"]]),S=JSON.parse('{"path":"/plugins/medium-zoom.html","title":"medium-zoom","lang":"en-US","frontmatter":{"description":"medium-zoom","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/medium-zoom.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/medium-zoom.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"medium-zoom"}],["meta",{"property":"og:description","content":"medium-zoom"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"medium-zoom\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"zoomOptions","slug":"zoomoptions","link":"#zoomoptions","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]},{"level":2,"title":"Composition API","slug":"composition-api","link":"#composition-api","children":[{"level":3,"title":"useMediumZoom","slug":"usemediumzoom","link":"#usemediumzoom","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/medium-zoom.md"}');export{T as comp,S as data};
diff --git a/assets/nprogress.html-7nPo6B--.js b/assets/nprogress.html-7nPo6B--.js
new file mode 100644
index 0000000000..cc8198e371
--- /dev/null
+++ b/assets/nprogress.html-7nPo6B--.js
@@ -0,0 +1,11 @@
+import{_ as r,r as n,o as p,c as l,a,b as s,d as e,e as c}from"./app-3y2wReKQ.js";const i={},g=s("h1",{id:"nprogress-plugin",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#nprogress-plugin"},[s("span",null,"nprogress Plugin")])],-1),d={href:"https://github.com/rstacruz/nprogress",target:"_blank",rel:"noopener noreferrer"},y=c(`
This plugin has been integrated into the default theme.
`,7);function h(m,u){const t=n("NpmBadge"),o=n("ExternalLinkIcon");return p(),l("div",null,[g,a(t,{package:"@vuepress/plugin-nprogress"}),s("p",null,[e("Integrate "),s("a",d,[e("nprogress"),a(o)]),e(" into VuePress, which can provide a progress bar when navigating to another page.")]),y])}const C=r(i,[["render",h],["__file","nprogress.html.vue"]]),_=JSON.parse('{"path":"/plugins/nprogress.html","title":"nprogress","lang":"en-US","frontmatter":{"title":"nprogress","description":"nprogress Plugin","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/nprogress.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/nprogress.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"nprogress"}],["meta",{"property":"og:description","content":"nprogress Plugin"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"nprogress\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/nprogress.md"}');export{C as comp,_ as data};
diff --git a/assets/nprogress.html-UjaKTpXH.js b/assets/nprogress.html-UjaKTpXH.js
new file mode 100644
index 0000000000..13cc328e38
--- /dev/null
+++ b/assets/nprogress.html-UjaKTpXH.js
@@ -0,0 +1,11 @@
+import{_ as p,r as n,o as r,c as l,a,b as s,d as e,e as c}from"./app-3y2wReKQ.js";const i={},d=s("h1",{id:"nprogress-插件",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#nprogress-插件"},[s("span",null,"nprogress 插件")])],-1),g={href:"https://github.com/rstacruz/nprogress",target:"_blank",rel:"noopener noreferrer"},h=c(`
export interface PageTextOptions {
+ /**
+ * Whether convert text to single line content
+ *
+ * @default false
+ */
+ singleLine?: boolean
+
+ /**
+ * Length of text
+ *
+ * @description Text length will be the minimal possible length reaching this value
+ *
+ * @default 300
+ */
+ length?: number
+
+ /**
+ * Tags to be removed
+ *
+ * @description Table and code blocks are removed by default.
+ *
+ * @default ['table', 'pre']
+ */
+ removedTags?: string[]
+}
+
+export const getPageText: (
+ app: App,
+ page: Page,
+ options?: PageTextOptions,
+) => string
+
`,8),t=[p];function o(i,c){return n(),e("div",null,t)}const d=s(l,[["render",o],["__file","page.html.vue"]]),y=JSON.parse('{"path":"/tools/helper/node/page.html","title":"Page Related","lang":"en-US","frontmatter":{"description":"Page Related These functions generate common information for your pages. getPageExcerpt Get the excerpt of the page. getPageText Get plain text of the page.","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/tools/helper/node/page.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Page Related"}],["meta",{"property":"og:description","content":"Page Related These functions generate common information for your pages. getPageExcerpt Get the excerpt of the page. getPageText Get plain text of the page."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:34:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:34:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Page Related\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:34:35.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"getPageExcerpt","slug":"getpageexcerpt","link":"#getpageexcerpt","children":[]},{"level":2,"title":"getPageText","slug":"getpagetext","link":"#getpagetext","children":[]}],"git":{"updatedTime":1706960075000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"tools/helper/node/page.md"}');export{d as comp,y as data};
diff --git a/assets/page.html-Md1PFPyq.js b/assets/page.html-Md1PFPyq.js
new file mode 100644
index 0000000000..de9a1fa3e3
--- /dev/null
+++ b/assets/page.html-Md1PFPyq.js
@@ -0,0 +1,77 @@
+import{_ as s,o as n,c as a,e}from"./app-3y2wReKQ.js";const l={},p=e(`
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.
This option is used for generating tempPaletteFile and tempStyleFile, and you don't need to change this option in most cases.
`,27);function g(v,C){const p=a("NpmBadge"),t=a("ExternalLinkIcon");return i(),r("div",null,[d,l(p,{package:"@vuepress/plugin-palette"}),u,s("p",null,[e("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 "),s("a",y,[e("CSS variables"),l(t)]),e(", "),s("a",h,[e("SASS variables"),l(t)]),e(", "),s("a",m,[e("LESS variables"),l(t)]),e(" or "),s("a",f,[e("Stylus variables"),l(t)]),e(" in the palette, and then you can use those variables in your theme styles.")]),D])}const x=o(c,[["render",g],["__file","palette.html.vue"]]),E=JSON.parse('{"path":"/plugins/palette.html","title":"palette","lang":"en-US","frontmatter":{"description":"palette","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/palette.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/palette.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"palette"}],["meta",{"property":"og:description","content":"palette"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"palette\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Palette and Style","slug":"palette-and-style","link":"#palette-and-style","children":[]},{"level":2,"title":"Usage","slug":"usage-1","link":"#usage-1","children":[{"level":3,"title":"Usage of Palette","slug":"usage-of-palette","link":"#usage-of-palette","children":[]},{"level":3,"title":"Usage of Style","slug":"usage-of-style","link":"#usage-of-style","children":[]}]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"preset","slug":"preset","link":"#preset","children":[]},{"level":3,"title":"userPaletteFile","slug":"userpalettefile","link":"#userpalettefile","children":[]},{"level":3,"title":"tempPaletteFile","slug":"temppalettefile","link":"#temppalettefile","children":[]},{"level":3,"title":"userStyleFile","slug":"userstylefile","link":"#userstylefile","children":[]},{"level":3,"title":"tempStyleFile","slug":"tempstylefile","link":"#tempstylefile","children":[]},{"level":3,"title":"importCode","slug":"importcode","link":"#importcode","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/palette.md"}');export{x as comp,E as data};
diff --git a/assets/photo-swipe.html-BofHy_ep.js b/assets/photo-swipe.html-BofHy_ep.js
new file mode 100644
index 0000000000..977852c5d6
--- /dev/null
+++ b/assets/photo-swipe.html-BofHy_ep.js
@@ -0,0 +1,145 @@
+import{_ as i,r as n,o as t,c,a as l,b as s,d as a,e}from"./app-3y2wReKQ.js";const r={},D=s("h1",{id:"photo-swipe",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#photo-swipe"},[s("span",null,"photo-swipe")])],-1),d=e(`
`,10);function C(m,h){const p=n("NpmBadge"),o=n("ExternalLinkIcon");return t(),c("div",null,[D,l(p,{package:"@vuepress/plugin-photo-swipe"}),d,s("p",null,[a("传递给 "),s("a",y,[v,l(o)]),a(" 的额外选项。")]),u])}const g=i(r,[["render",C],["__file","photo-swipe.html.vue"]]),E=JSON.parse('{"path":"/zh/plugins/photo-swipe.html","title":"photo-swipe","lang":"zh-CN","frontmatter":{"description":"photo-swipe","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/photo-swipe.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/photo-swipe.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"photo-swipe"}],["meta",{"property":"og:description","content":"photo-swipe"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"photo-swipe\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]},{"level":3,"title":"scrollToClose","slug":"scrolltoclose","link":"#scrolltoclose","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"photoswipe","slug":"photoswipe","link":"#photoswipe","children":[]}]},{"level":2,"title":"客户端配置","slug":"客户端配置","link":"#客户端配置","children":[{"level":3,"title":"definePhotoSwipeConfig","slug":"definephotoswipeconfig","link":"#definephotoswipeconfig","children":[]}]},{"level":2,"title":"API","slug":"api","link":"#api","children":[]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"zh/plugins/photo-swipe.md"}');export{g as comp,E as data};
diff --git a/assets/photo-swipe.html-CqKKYhHS.js b/assets/photo-swipe.html-CqKKYhHS.js
new file mode 100644
index 0000000000..c88deaa124
--- /dev/null
+++ b/assets/photo-swipe.html-CqKKYhHS.js
@@ -0,0 +1,145 @@
+import{_ as o,r as n,o as i,c as t,a as l,b as s,d as c,e as a}from"./app-3y2wReKQ.js";const r={},D=s("h1",{id:"photo-swipe",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#photo-swipe"},[s("span",null,"photo-swipe")])],-1),d=a(`
This plugin will make the pictures in the body of the page enter the preview mode when clicked.
Swipe left and right to preview other pictures on the page in order
View the description of the picture
Zoom in and zoom out the picture
View pictures in full screen
Download pictures
Share pictures
TIP
Besides clicking "×" in the upper right corner to exit the preview mode, scrolling up and down more than a certain distance will also exit preview mode.
On mobile devices, or using the PC trackpad, you can use pan and zoom gestures to pan and zoom in the preview mode.
`,10);function m(C,h){const e=n("NpmBadge"),p=n("ExternalLinkIcon");return i(),t("div",null,[D,l(e,{package:"@vuepress/plugin-photo-swipe"}),d,s("p",null,[c("Options passed to "),s("a",y,[u,l(p)])]),v])}const b=o(r,[["render",m],["__file","photo-swipe.html.vue"]]),E=JSON.parse('{"path":"/plugins/photo-swipe.html","title":"photo-swipe","lang":"en-US","frontmatter":{"description":"photo-swipe","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/photo-swipe.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/photo-swipe.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"photo-swipe"}],["meta",{"property":"og:description","content":"photo-swipe"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T03:54:27.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T03:54:27.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"photo-swipe\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T03:54:27.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]},{"level":3,"title":"scrollToClose","slug":"scrolltoclose","link":"#scrolltoclose","children":[]},{"level":3,"title":"delay","slug":"delay","link":"#delay","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"photoSwipe","slug":"photoswipe","link":"#photoswipe","children":[]}]},{"level":2,"title":"Client Config","slug":"client-config","link":"#client-config","children":[{"level":3,"title":"definePhotoSwipeConfig","slug":"definephotoswipeconfig","link":"#definephotoswipeconfig","children":[]}]},{"level":2,"title":"API","slug":"api","link":"#api","children":[]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]}],"git":{"updatedTime":1708487667000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":4}]},"autoDesc":true,"filePathRelative":"plugins/photo-swipe.md"}');export{b as comp,E as data};
diff --git a/assets/plugin.html-B8thuhdW.js b/assets/plugin.html-B8thuhdW.js
new file mode 100644
index 0000000000..93e6cadb56
--- /dev/null
+++ b/assets/plugin.html-B8thuhdW.js
@@ -0,0 +1,10 @@
+import{_ as o,r as u,o as a,c as p,b as e,d as l,a as t,w as s,e as i}from"./app-3y2wReKQ.js";const c={},h=i(`
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.
`,5),r=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),d=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),m=e("p",null,"Details:",-1),g=e("h2",{id:"themeplugins-backtotop",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-backtotop"},[e("span",null,"themePlugins.backToTop")])],-1),_=e("li",null,[e("p",null,[l("Type: "),e("code",null,"BackToTopPluginOptions | boolean")])],-1),f=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),y=e("p",null,"Details:",-1),k=e("p",null,"Object value is supported as plugin options.",-1),b=e("h2",{id:"themeplugins-container",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-container"},[e("span",null,"themePlugins.container")])],-1),D=e("li",null,[e("p",null,[l("Type: "),e("code",null,"Record")])],-1),v=e("p",null,"Details:",-1),P=i("
ContainerType type is:
tip
warning
danger
details
codeGroup
codeGroupItem
",2),C=e("p",null,"Also see:",-1),x=e("h2",{id:"themeplugins-copycode",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-copycode"},[e("span",null,"themePlugins.copyCode")])],-1),T=e("li",null,[e("p",null,[l("Type: "),e("code",null,"CopyCodePluginOptions | boolean")])],-1),E=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),j=e("p",null,"Details:",-1),w=e("p",null,"Object value is supported as plugin options.",-1),O=e("h2",{id:"themeplugins-externallinkicon",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-externallinkicon"},[e("span",null,"themePlugins.externalLinkIcon")])],-1),z=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),S=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),V=e("p",null,"Details:",-1),L=e("h2",{id:"themeplugins-git",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-git"},[e("span",null,"themePlugins.git")])],-1),N=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),A=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),F=e("p",null,"Details:",-1),Y=e("h2",{id:"themeplugins-linkscheck",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-linkscheck"},[e("span",null,"themePlugins.linksCheck")])],-1),R=e("li",null,[e("p",null,[l("Type: "),e("code",null,"LinksCheckPluginOptions | boolean")])],-1),Z=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),B=e("p",null,"Details:",-1),M=e("h2",{id:"themeplugins-mediumzoom",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-mediumzoom"},[e("span",null,"themePlugins.mediumZoom")])],-1),H=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),I=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),G=e("p",null,"Details:",-1),J=e("h2",{id:"themeplugins-nprogress",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-nprogress"},[e("span",null,"themePlugins.nprogress")])],-1),U=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),q=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),K=e("p",null,"Details:",-1),Q=e("h2",{id:"themeplugins-prismjs",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-prismjs"},[e("span",null,"themePlugins.prismjs")])],-1),W=e("li",null,[e("p",null,[l("Type: "),e("code",null,"boolean")])],-1),X=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),$=e("p",null,"Details:",-1),ee=e("h2",{id:"themeplugins-seo",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-seo"},[e("span",null,"themePlugins.seo")])],-1),le=e("li",null,[e("p",null,[l("Type: "),e("code",null,"SeoPluginOptions | boolean")])],-1),ne=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),te=e("p",null,"Details:",-1),se=e("p",null,"Object value is supported as plugin options.",-1),ie=e("h2",{id:"themeplugins-sitemap",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#themeplugins-sitemap"},[e("span",null,"themePlugins.sitemap")])],-1),oe=e("li",null,[e("p",null,[l("Type: "),e("code",null,"SitemapPluginOptions | boolean")])],-1),ue=e("li",null,[e("p",null,[l("Default: "),e("code",null,"true")])],-1),ae=e("p",null,"Details:",-1),pe=e("p",null,"Object value is supported as plugin options.",-1);function ce(he,re){const n=u("RouteLink");return a(),p("div",null,[h,e("ul",null,[r,d,e("li",null,[m,e("p",null,[l("Enable "),t(n,{to:"/plugins/active-header-links.html"},{default:s(()=>[l("@vuepress/plugin-active-header-links")]),_:1}),l(" or not.")])])]),g,e("ul",null,[_,f,e("li",null,[y,e("p",null,[l("Enable "),t(n,{to:"/plugins/back-to-top.html"},{default:s(()=>[l("@vuepress/plugin-back-to-top")]),_:1}),l(" or not.")]),k])]),b,e("ul",null,[D,e("li",null,[v,e("p",null,[l("Enable custom containers that powered by "),t(n,{to:"/plugins/container.html"},{default:s(()=>[l("@vuepress/plugin-container")]),_:1}),l(" or not.")]),P]),e("li",null,[C,e("ul",null,[e("li",null,[t(n,{to:"/themes/default/markdown.html#custom-containers"},{default:s(()=>[l("Default Theme > Markdown > Custom Containers")]),_:1})])])])]),x,e("ul",null,[T,E,e("li",null,[j,e("p",null,[l("Enable "),t(n,{to:"/plugins/copy-code.html"},{default:s(()=>[l("@vuepress/plugin-copy-code")]),_:1}),l(" or not.")]),w])]),O,e("ul",null,[z,S,e("li",null,[V,e("p",null,[l("Enable "),t(n,{to:"/plugins/external-link-icon.html"},{default:s(()=>[l("@vuepress/plugin-external-link-icon")]),_:1}),l(" or not.")])])]),L,e("ul",null,[N,A,e("li",null,[F,e("p",null,[l("Enable "),t(n,{to:"/plugins/git.html"},{default:s(()=>[l("@vuepress/plugin-git")]),_:1}),l(" or not.")])])]),Y,e("ul",null,[R,Z,e("li",null,[B,e("p",null,[l("Enable "),t(n,{to:"/plugins/links-check.html"},{default:s(()=>[l("@vuepress/plugin-links-check")]),_:1}),l(" or not.")])])]),M,e("ul",null,[H,I,e("li",null,[G,e("p",null,[l("Enable "),t(n,{to:"/plugins/medium-zoom.html"},{default:s(()=>[l("@vuepress/plugin-medium-zoom")]),_:1}),l(" or not.")])])]),J,e("ul",null,[U,q,e("li",null,[K,e("p",null,[l("Enable "),t(n,{to:"/plugins/nprogress.html"},{default:s(()=>[l("@vuepress/plugin-nprogress")]),_:1}),l(" or not.")])])]),Q,e("ul",null,[W,X,e("li",null,[$,e("p",null,[l("Enable "),t(n,{to:"/plugins/prismjs.html"},{default:s(()=>[l("@vuepress/plugin-prismjs")]),_:1}),l(" or not.")])])]),ee,e("ul",null,[le,ne,e("li",null,[te,e("p",null,[l("Enable "),t(n,{to:"/plugins/seo/"},{default:s(()=>[l("@vuepress/plugin-seo")]),_:1}),l(" or not.")]),se])]),ie,e("ul",null,[oe,ue,e("li",null,[ae,e("p",null,[l("Enable "),t(n,{to:"/plugins/sitemap/"},{default:s(()=>[l("@vuepress/plugin-sitemap")]),_:1}),l(" or not.")]),pe])])])}const me=o(c,[["render",ce],["__file","plugin.html.vue"]]),ge=JSON.parse('{"path":"/themes/default/plugin.html","title":"Plugins Config","lang":"en-US","frontmatter":{"description":"Plugins Config 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...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/plugin.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Plugins Config"}],["meta",{"property":"og:description","content":"Plugins Config 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..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Plugins Config\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"themePlugins.activeHeaderLinks","slug":"themeplugins-activeheaderlinks","link":"#themeplugins-activeheaderlinks","children":[]},{"level":2,"title":"themePlugins.backToTop","slug":"themeplugins-backtotop","link":"#themeplugins-backtotop","children":[]},{"level":2,"title":"themePlugins.container","slug":"themeplugins-container","link":"#themeplugins-container","children":[]},{"level":2,"title":"themePlugins.copyCode","slug":"themeplugins-copycode","link":"#themeplugins-copycode","children":[]},{"level":2,"title":"themePlugins.externalLinkIcon","slug":"themeplugins-externallinkicon","link":"#themeplugins-externallinkicon","children":[]},{"level":2,"title":"themePlugins.git","slug":"themeplugins-git","link":"#themeplugins-git","children":[]},{"level":2,"title":"themePlugins.linksCheck","slug":"themeplugins-linkscheck","link":"#themeplugins-linkscheck","children":[]},{"level":2,"title":"themePlugins.mediumZoom","slug":"themeplugins-mediumzoom","link":"#themeplugins-mediumzoom","children":[]},{"level":2,"title":"themePlugins.nprogress","slug":"themeplugins-nprogress","link":"#themeplugins-nprogress","children":[]},{"level":2,"title":"themePlugins.prismjs","slug":"themeplugins-prismjs","link":"#themeplugins-prismjs","children":[]},{"level":2,"title":"themePlugins.seo","slug":"themeplugins-seo","link":"#themeplugins-seo","children":[]},{"level":2,"title":"themePlugins.sitemap","slug":"themeplugins-sitemap","link":"#themeplugins-sitemap","children":[]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"themes/default/plugin.md"}');export{me as comp,ge as data};
diff --git a/assets/plugin.html-DesPcAtO.js b/assets/plugin.html-DesPcAtO.js
new file mode 100644
index 0000000000..78d0cd3243
--- /dev/null
+++ b/assets/plugin.html-DesPcAtO.js
@@ -0,0 +1,10 @@
+import{_ as o,r as u,o as p,c as a,b as e,d as l,a as s,w as t,e as i}from"./app-3y2wReKQ.js";const c={},h=i(`
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.
`,7),u=e("li",null,[e("p",null,[s("Type: "),e("code",null,"string[]")])],-1),g=e("li",null,[e("p",null,[s("Default: "),e("code",null,"['markdown', 'jsdoc', 'yaml']")])],-1),y=e("p",null,"Details:",-1),D=e("p",null,"Languages to preload.",-1),_=e("p",null,"By default, languages will be loaded on demand when parsing markdown files.",-1),f={href:"https://github.com/PrismJS/prism/issues/2716",target:"_blank",rel:"noopener noreferrer"};function j(k,v){const l=t("NpmBadge"),n=t("ExternalLinkIcon");return p(),r("div",null,[d,a(l,{package:"@vuepress/plugin-prismjs"}),e("p",null,[s("This plugin will enable syntax highlighting for markdown code fence with "),e("a",m,[s("Prism.js"),a(n)]),s(".")]),h,e("ul",null,[u,g,e("li",null,[y,D,_,e("p",null,[s("However, Prism.js has "),e("a",f,[s("some potential issues"),a(n)]),s(" about loading languages dynamically. To avoid them, you can preload languages via this option.")])])])])}const C=o(c,[["render",j],["__file","prismjs.html.vue"]]),b=JSON.parse('{"path":"/plugins/prismjs.html","title":"prismjs","lang":"en-US","frontmatter":{"description":"prismjs","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/prismjs.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/prismjs.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"prismjs"}],["meta",{"property":"og:description","content":"prismjs"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"prismjs\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"preloadLanguages","slug":"preloadlanguages","link":"#preloadlanguages","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/prismjs.md"}');export{C as comp,b as data};
diff --git a/assets/prismjs.html-Dx0rbcK9.js b/assets/prismjs.html-Dx0rbcK9.js
new file mode 100644
index 0000000000..4a608f3ca0
--- /dev/null
+++ b/assets/prismjs.html-Dx0rbcK9.js
@@ -0,0 +1,11 @@
+import{_ as p,r as t,o,c as r,a,b as s,d as e,e as i}from"./app-3y2wReKQ.js";const c={},m=s("h1",{id:"prismjs",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#prismjs"},[s("span",null,"prismjs")])],-1),d={href:"https://prismjs.com/",target:"_blank",rel:"noopener noreferrer"},h=i(`
该插件已经集成到默认主题中。
需要注意的是,该插件仅会给代码块添加 HTML 标记,而不会添加样式。当你在一个自定义主题中使用它时,可能需要自己选择并引入 Prism.js 样式主题。
`,34);function d(D,y){const n=e("NpmBadge");return l(),p("div",null,[c,o(n,{package:"@vuepress/plugin-reading-time"}),r])}const m=a(t,[["render",d],["__file","reading-time.html.vue"]]),g=JSON.parse('{"path":"/zh/plugins/reading-time.html","title":"reading-time","lang":"zh-CN","frontmatter":{"description":"reading-time","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/reading-time.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/reading-time.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"reading-time"}],["meta",{"property":"og:description","content":"reading-time"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"reading-time\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[{"level":3,"title":"在 Node 侧获取数据","slug":"在-node-侧获取数据","link":"#在-node-侧获取数据","children":[]},{"level":3,"title":"在客户端侧获取数据","slug":"在客户端侧获取数据","link":"#在客户端侧获取数据","children":[]}]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"wordPerMinute","slug":"wordperminute","link":"#wordperminute","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"客户端 API","slug":"客户端-api","link":"#客户端-api","children":[{"level":3,"title":"useReadingTimeData","slug":"usereadingtimedata","link":"#usereadingtimedata","children":[]},{"level":3,"title":"useReadingTimeLocale","slug":"usereadingtimelocale","link":"#usereadingtimelocale","children":[]}]},{"level":2,"title":"高级使用","slug":"高级使用","link":"#高级使用","children":[]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/reading-time.md"}');export{m as comp,g as data};
diff --git a/assets/reading-time.html-CmM3QgM1.js b/assets/reading-time.html-CmM3QgM1.js
new file mode 100644
index 0000000000..a79e187d30
--- /dev/null
+++ b/assets/reading-time.html-CmM3QgM1.js
@@ -0,0 +1,95 @@
+import{_ as e,r as a,o as l,c as p,a as o,b as s,e as i}from"./app-3y2wReKQ.js";const t={},r=s("h1",{id:"reading-time",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#reading-time"},[s("span",null,"reading-time")])],-1),c=i(`
This plugin will generate word count and estimated reading time for each page.
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:
interface ReadingTime {
+ /** Expect reading time in minute unit */
+ minutes: number
+ /** Words count of content */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
When you register a plugin multiple times, vuepress will gives you warning about that telling you only the first one takes effect. The useReadingTimePlugin automatically detects if the plugin is registered and avoid registering multiple times.
If you access reading time data in 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
+ }
+}
+
`,34);function d(D,u){const n=a("NpmBadge");return l(),p("div",null,[r,o(n,{package:"@vuepress/plugin-reading-time"}),c])}const g=e(t,[["render",d],["__file","reading-time.html.vue"]]),m=JSON.parse('{"path":"/plugins/reading-time.html","title":"reading-time","lang":"en-US","frontmatter":{"description":"reading-time","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/reading-time.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/reading-time.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"reading-time"}],["meta",{"property":"og:description","content":"reading-time"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-18T16:44:22.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-18T16:44:22.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"reading-time\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-18T16:44:22.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[{"level":3,"title":"Getting data on Node Side","slug":"getting-data-on-node-side","link":"#getting-data-on-node-side","children":[]},{"level":3,"title":"Getting data on Client Side","slug":"getting-data-on-client-side","link":"#getting-data-on-client-side","children":[]}]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"wordPerMinute","slug":"wordperminute","link":"#wordperminute","children":[]},{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]}]},{"level":2,"title":"Client API","slug":"client-api","link":"#client-api","children":[{"level":3,"title":"useReadingTimeData","slug":"usereadingtimedata","link":"#usereadingtimedata","children":[]},{"level":3,"title":"useReadingTimeLocale","slug":"usereadingtimelocale","link":"#usereadingtimelocale","children":[]}]},{"level":2,"title":"Advanced Usage","slug":"advanced-usage","link":"#advanced-usage","children":[]}],"git":{"updatedTime":1708274662000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/reading-time.md"}');export{g as comp,m as data};
diff --git a/assets/redirect.html-B9BX4Qrk.js b/assets/redirect.html-B9BX4Qrk.js
new file mode 100644
index 0000000000..34ff13d560
--- /dev/null
+++ b/assets/redirect.html-B9BX4Qrk.js
@@ -0,0 +1,81 @@
+import{_ as a,r as l,o as n,c as o,a as t,b as s,e as p}from"./app-3y2wReKQ.js";const c={},i=s("h1",{id:"redirect",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#redirect"},[s("span",null,"redirect")])],-1),r=p(`
This plugin can automatically handle redirects for your site.
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:
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 asking
modal: When the user's language preference is different from the current page language, show a modal asking whether to switch language
By 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:
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.
`,54);function d(D,y){const a=e("NpmBadge");return n(),p("div",null,[r,o(a,{package:"@vuepress/plugin-rtl"}),i])}const h=l(t,[["render",d],["__file","redirect.html.vue"]]),C=JSON.parse('{"path":"/zh/plugins/redirect.html","title":"redirect","lang":"zh-CN","frontmatter":{"description":"redirect","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/redirect.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/redirect.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"redirect"}],["meta",{"property":"og:description","content":"redirect"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"redirect\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[{"level":3,"title":"设置重定向","slug":"设置重定向","link":"#设置重定向","children":[]},{"level":3,"title":"自动多语言","slug":"自动多语言","link":"#自动多语言","children":[]},{"level":3,"title":"自动切换语言","slug":"自动切换语言","link":"#自动切换语言","children":[]},{"level":3,"title":"自定义多语言配置","slug":"自定义多语言配置","link":"#自定义多语言配置","children":[]},{"level":3,"title":"重定向站点","slug":"重定向站点","link":"#重定向站点","children":[]}]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"config","slug":"config","link":"#config","children":[]},{"level":3,"title":"autoLocale","slug":"autolocale","link":"#autolocale","children":[]},{"level":3,"title":"switchLocale","slug":"switchlocale","link":"#switchlocale","children":[]},{"level":3,"title":"localeConfig","slug":"localeconfig","link":"#localeconfig","children":[]},{"level":3,"title":"localeFallback","slug":"localefallback","link":"#localefallback","children":[]},{"level":3,"title":"defaultBehavior","slug":"defaultbehavior","link":"#defaultbehavior","children":[]},{"level":3,"title":"defaultLocale","slug":"defaultlocale","link":"#defaultlocale","children":[]}]},{"level":2,"title":"Frontmatter","slug":"frontmatter","link":"#frontmatter","children":[{"level":3,"title":"redirectFrom","slug":"redirectfrom","link":"#redirectfrom","children":[]},{"level":3,"title":"redirectTo","slug":"redirectto","link":"#redirectto","children":[]}]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"zh/plugins/redirect.md"}');export{h as comp,C as data};
diff --git a/assets/register-components.html-CEAbZw5H.js b/assets/register-components.html-CEAbZw5H.js
new file mode 100644
index 0000000000..24f62e8994
--- /dev/null
+++ b/assets/register-components.html-CEAbZw5H.js
@@ -0,0 +1,49 @@
+import{_ as t,r as e,o as r,c,a,b as s,d as n,e as l}from"./app-3y2wReKQ.js";const i={},D=s("h1",{id:"register-components",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#register-components"},[s("span",null,"register-components")])],-1),d=l(`
Register Vue components from component files or directory automatically.
`,16),m=s("li",null,[s("p",null,[n("Type: "),s("code",null,"string[]")])],-1),y=s("li",null,[s("p",null,[n("Default: "),s("code",null,"['**/*.vue']")])],-1),u=s("p",null,"Details:",-1),h={href:"https://github.com/sindresorhus/globby",target:"_blank",rel:"noopener noreferrer"},C=s("p",null,[n("The patterns are relative to "),s("a",{href:"#componentsdir"},"componentsDir"),n(".")],-1),v=l('
Notice that the filename is a filepath relative to componentsDir.
',2);function g(b,f){const o=e("NpmBadge"),p=e("ExternalLinkIcon");return r(),c("div",null,[D,a(o,{package:"@vuepress/plugin-register-components"}),d,s("ul",null,[m,y,s("li",null,[u,s("p",null,[n("Patterns to match component files using "),s("a",h,[n("globby"),a(p)]),n(".")]),C])]),v])}const _=t(i,[["render",g],["__file","register-components.html.vue"]]),A=JSON.parse('{"path":"/plugins/register-components.html","title":"register-components","lang":"en-US","frontmatter":{"description":"register-components","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/register-components.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/register-components.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"register-components"}],["meta",{"property":"og:description","content":"register-components"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"register-components\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"components","slug":"components","link":"#components","children":[]},{"level":3,"title":"componentsDir","slug":"componentsdir","link":"#componentsdir","children":[]},{"level":3,"title":"componentsPatterns","slug":"componentspatterns","link":"#componentspatterns","children":[]},{"level":3,"title":"getComponentName","slug":"getcomponentname","link":"#getcomponentname","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/register-components.md"}');export{_ as comp,A as data};
diff --git a/assets/register-components.html-DsEQtmxG.js b/assets/register-components.html-DsEQtmxG.js
new file mode 100644
index 0000000000..54792488d3
--- /dev/null
+++ b/assets/register-components.html-DsEQtmxG.js
@@ -0,0 +1,49 @@
+import{_ as t,r as e,o as r,c,a,b as s,d as n,e as l}from"./app-3y2wReKQ.js";const i={},D=s("h1",{id:"register-components",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#register-components"},[s("span",null,"register-components")])],-1),d=l(`
',2);function g(b,E){const p=e("NpmBadge"),o=e("ExternalLinkIcon");return r(),c("div",null,[D,a(p,{package:"@vuepress/plugin-register-components"}),d,s("ul",null,[m,y,s("li",null,[u,s("p",null,[n("使用 "),s("a",C,[n("globby"),a(o)]),n(" 来匹配组件文件的 Patterns 。")]),v])]),h])}const _=t(i,[["render",g],["__file","register-components.html.vue"]]),A=JSON.parse('{"path":"/zh/plugins/register-components.html","title":"register-components","lang":"zh-CN","frontmatter":{"description":"register-components","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/register-components.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/register-components.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"register-components"}],["meta",{"property":"og:description","content":"register-components"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"register-components\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"配置项","slug":"配置项","link":"#配置项","children":[{"level":3,"title":"components","slug":"components","link":"#components","children":[]},{"level":3,"title":"componentsDir","slug":"componentsdir","link":"#componentsdir","children":[]},{"level":3,"title":"componentsPatterns","slug":"componentspatterns","link":"#componentspatterns","children":[]},{"level":3,"title":"getComponentName","slug":"getcomponentname","link":"#getcomponentname","children":[]}]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/register-components.md"}');export{_ as comp,A as data};
diff --git a/assets/remove-pwa.html-BHx1ihV6.js b/assets/remove-pwa.html-BHx1ihV6.js
new file mode 100644
index 0000000000..88cc3479c1
--- /dev/null
+++ b/assets/remove-pwa.html-BHx1ihV6.js
@@ -0,0 +1,11 @@
+import{_ as l,r as s,o as r,c as p,a as t,b as e,d as a,w as i,e as c}from"./app-3y2wReKQ.js";const d={},h=e("h1",{id:"remove-pwa",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#remove-pwa"},[e("span",null,"remove-pwa")])],-1),u=e("p",null,"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.",-1),m={class:"custom-container tip"},y=e("p",{class:"custom-container-title"},"Why this plugin is needed if you used PWA plugin once?",-1),v=e("code",null,"@vuepress/plugin-pwa",-1),g=e("p",null,"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.",-1),w=e("p",null,"To solve this problem:",-1),f=e("ol",null,[e("li",null,"A new service worker with empty contents shall be generated in the original place."),e("li",null,"The new service worker shall attempt to remove contents that old service worker cached, then it should unregister itself.")],-1),D=c(`
`,8);function _(k,x){const o=s("NpmBadge"),n=s("RouteLink");return r(),p("div",null,[h,t(o,{package:"@vuepress/plugin-remove-pwa"}),u,e("div",m,[y,e("p",null,[a("PWA plugins like "),t(n,{to:"/plugins/pwa/"},{default:i(()=>[v]),_:1}),a(" register service worker to your site, which will cache your site and make it available offline.")]),g,w,f]),D])}const b=l(d,[["render",_],["__file","remove-pwa.html.vue"]]),E=JSON.parse('{"path":"/plugins/remove-pwa.html","title":"remove-pwa","lang":"en-US","frontmatter":{"description":"remove-pwa","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/remove-pwa.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/remove-pwa.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"remove-pwa"}],["meta",{"property":"og:description","content":"remove-pwa"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-20T02:57:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-20T02:57:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"remove-pwa\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-20T02:57:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"cachePrefix","slug":"cacheprefix","link":"#cacheprefix","children":[]},{"level":3,"title":"swLocation","slug":"swlocation","link":"#swlocation","children":[]}]}],"git":{"updatedTime":1708397875000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"plugins/remove-pwa.md"}');export{b as comp,E as data};
diff --git a/assets/remove-pwa.html-Du5lzlD_.js b/assets/remove-pwa.html-Du5lzlD_.js
new file mode 100644
index 0000000000..b36a09b8b4
--- /dev/null
+++ b/assets/remove-pwa.html-Du5lzlD_.js
@@ -0,0 +1,11 @@
+import{_ as l,r as s,o as r,c as p,a,b as e,d as t,w as c,e as i}from"./app-3y2wReKQ.js";const d={},h=e("h1",{id:"remove-pwa",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#remove-pwa"},[e("span",null,"remove-pwa")])],-1),m=e("p",null,"此插件从你的 VuePress 站点中删除任何相关的 Service Worker,因此如果你在启用后任何 PWA 插件后移除它们,用户仍然可以获得更新。",-1),u={class:"custom-container tip"},v=e("p",{class:"custom-container-title"},"如果你启用过 PWA,为什么需要这个插件?",-1),y=e("code",null,"@vuepress/plugin-pwa",-1),g=e("p",null,"但是,如果你删除 PWA 插件,先前的 Service Worker 仍将在那里,但它们永远无法获得更新,因为他们永远无法找到要更新的新 Service Worker。 因此,用户将继续使用你网站的旧版本。",-1),D=e("p",null,"要解决这个问题:",-1),_=e("ol",null,[e("li",null,[e("p",null,"一个新的内容为空的 Service Worker 需要生成在原位置。")]),e("li",null,[e("p",null,"新的 Service Worker 应该尝试删除旧 Service Worker 缓存的内容,然后它应该注销自己。")])],-1),w=i(`
`,8);function k(f,x){const n=s("NpmBadge"),o=s("RouteLink");return r(),p("div",null,[h,a(n,{package:"@vuepress/plugin-remove-pwa"}),m,e("div",u,[v,e("p",null,[t("PWA 插件,如 "),a(o,{to:"/zh/plugins/pwa/"},{default:c(()=>[y]),_:1}),t(" 将 Service Worker 注册到你的站点,这将缓存你的站点并使其离线可用。")]),g,D,_]),w])}const P=l(d,[["render",k],["__file","remove-pwa.html.vue"]]),S=JSON.parse('{"path":"/zh/plugins/remove-pwa.html","title":"remove-pwa","lang":"zh-CN","frontmatter":{"description":"remove-pwa","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/remove-pwa.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/remove-pwa.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"remove-pwa"}],["meta",{"property":"og:description","content":"remove-pwa"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-20T02:57:55.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-20T02:57:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"remove-pwa\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-20T02:57:55.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"cachePrefix","slug":"cacheprefix","link":"#cacheprefix","children":[]},{"level":3,"title":"swLocation","slug":"swlocation","link":"#swlocation","children":[]}]}],"git":{"updatedTime":1708397875000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":3}]},"autoDesc":true,"filePathRelative":"zh/plugins/remove-pwa.md"}');export{P as comp,S as data};
diff --git a/assets/rtl.html-UfAxzvbR.js b/assets/rtl.html-UfAxzvbR.js
new file mode 100644
index 0000000000..4e0ff2ccd1
--- /dev/null
+++ b/assets/rtl.html-UfAxzvbR.js
@@ -0,0 +1,17 @@
+import{_ as l,r as a,o as n,c as t,a as o,b as s,e as p}from"./app-3y2wReKQ.js";const r={},c=s("h1",{id:"rtl",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#rtl"},[s("span",null,"rtl")])],-1),i=p(`
`,9);function d(D,m){const e=a("NpmBadge");return n(),t("div",null,[c,o(e,{package:"@vuepress/plugin-rtl"}),i])}const y=l(r,[["render",d],["__file","rtl.html.vue"]]),u=JSON.parse('{"path":"/zh/plugins/rtl.html","title":"rtl","lang":"zh-CN","frontmatter":{"description":"rtl","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/rtl.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/rtl.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"rtl"}],["meta",{"property":"og:description","content":"rtl"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-01T15:26:40.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T15:26:40.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"rtl\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T15:26:40.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"选项","slug":"选项","link":"#选项","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]}]}],"git":{"updatedTime":1706801200000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/plugins/rtl.md"}');export{y as comp,u as data};
diff --git a/assets/rtl.html-qXHsYrZl.js b/assets/rtl.html-qXHsYrZl.js
new file mode 100644
index 0000000000..68b077d401
--- /dev/null
+++ b/assets/rtl.html-qXHsYrZl.js
@@ -0,0 +1,17 @@
+import{_ as l,r as a,o as n,c as t,a as o,b as s,e as p}from"./app-3y2wReKQ.js";const r={},c=s("h1",{id:"rtl",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#rtl"},[s("span",null,"rtl")])],-1),i=p(`
This plugin will set direction to rtl on configured locales.
The default settings mean that the dir attribute of the html element will be set to rtl in rtl locales.
`,9);function d(D,m){const e=a("NpmBadge");return n(),t("div",null,[c,o(e,{package:"@vuepress/plugin-rtl"}),i])}const u=l(r,[["render",d],["__file","rtl.html.vue"]]),h=JSON.parse('{"path":"/plugins/rtl.html","title":"rtl","lang":"en-US","frontmatter":{"description":"rtl","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/rtl.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/rtl.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"rtl"}],["meta",{"property":"og:description","content":"rtl"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-01T15:26:40.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-01T15:26:40.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"rtl\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-01T15:26:40.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"selector","slug":"selector","link":"#selector","children":[]}]}],"git":{"updatedTime":1706801200000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"plugins/rtl.md"}');export{u as comp,h as data};
diff --git a/assets/search.html-CRG0twvM.js b/assets/search.html-CRG0twvM.js
new file mode 100644
index 0000000000..6ae5fb631a
--- /dev/null
+++ b/assets/search.html-CRG0twvM.js
@@ -0,0 +1,75 @@
+import{_ as c,r as e,o as r,c as i,a as n,b as s,d as a,w as d,e as l}from"./app-3y2wReKQ.js";const D={},y=s("h1",{id:"search",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#search"},[s("span",null,"search")])],-1),h=l(`
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;
+}
+
`,15);function k(_,F){const o=e("NpmBadge"),t=e("RouteLink"),p=e("ExternalLinkIcon");return r(),i("div",null,[y,n(o,{package:"@vuepress/plugin-search"}),h,s("p",null,[a("然而,当你的站点包含大量页面时,搜索索引文件也会变得非常大,它可能会拖慢你的页面加载速度。在这种情况下,我们建议你使用更成熟的解决方案 - "),n(t,{to:"/zh/plugins/docsearch.html"},{default:d(()=>[a("docsearch")]),_:1}),a(" 。")]),u,s("ul",null,[s("li",null,[a("参考: "),s("ul",null,[s("li",null,[s("a",v,[a("指南 > 多语言支持"),n(p)])])])])]),m,s("ul",null,[C,s("li",null,[g,s("p",null,[a("指定热键的 "),s("a",b,[a("event.key"),n(p)]),a(" 。")]),E,f])]),x])}const S=c(D,[["render",k],["__file","search.html.vue"]]),B=JSON.parse('{"path":"/zh/plugins/search.html","title":"search","lang":"zh-CN","frontmatter":{"description":"search","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/search.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/search.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"search"}],["meta",{"property":"og:description","content":"search"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"search\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"本地搜索索引","slug":"本地搜索索引","link":"#本地搜索索引","children":[]},{"level":2,"title":"配置项","slug":"配置项","link":"#配置项","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"hotKeys","slug":"hotkeys","link":"#hotkeys","children":[]},{"level":3,"title":"maxSuggestions","slug":"maxsuggestions","link":"#maxsuggestions","children":[]},{"level":3,"title":"isSearchable","slug":"issearchable","link":"#issearchable","children":[]},{"level":3,"title":"getExtraFields","slug":"getextrafields","link":"#getextrafields","children":[]}]},{"level":2,"title":"样式","slug":"样式","link":"#样式","children":[]},{"level":2,"title":"组件","slug":"组件","link":"#组件","children":[{"level":3,"title":"SearchBox","slug":"searchbox","link":"#searchbox","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/search.md"}');export{S as comp,B as data};
diff --git a/assets/search.html-De6wnbn-.js b/assets/search.html-De6wnbn-.js
new file mode 100644
index 0000000000..9f7719ccf6
--- /dev/null
+++ b/assets/search.html-De6wnbn-.js
@@ -0,0 +1,75 @@
+import{_ as c,r as l,o as i,c as r,a,b as s,d as e,w as d,e as n}from"./app-3y2wReKQ.js";const D={},h=s("h1",{id:"search",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#search"},[s("span",null,"search")])],-1),y=n(`
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.
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.
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;
+}
+
`,3),g=s("li",null,[s("p",null,[e("Default: "),s("code",null,"['s', '/']")])],-1),C=s("p",null,"Details:",-1),b={href:"http://keycode.info/",target:"_blank",rel:"noopener noreferrer"},f=s("p",null,"When hotkeys are pressed, the search box input will be focused.",-1),x=s("p",null,"Set to an empty array to disable hotkeys.",-1),E=n(`
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.
`,15);function k(_,A){const o=l("NpmBadge"),t=l("RouteLink"),p=l("ExternalLinkIcon");return i(),r("div",null,[h,a(o,{package:"@vuepress/plugin-search"}),y,s("p",null,[e("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 - "),a(t,{to:"/plugins/docsearch.html"},{default:d(()=>[e("docsearch")]),_:1}),e(".")]),u,s("ul",null,[s("li",null,[e("Also see: "),s("ul",null,[s("li",null,[s("a",m,[e("Guide > I18n"),a(p)])])])])]),v,s("ul",null,[g,s("li",null,[C,s("p",null,[e("Specify the "),s("a",b,[e("event.key"),a(p)]),e(" of the hotkeys.")]),f,x])]),E])}const w=c(D,[["render",k],["__file","search.html.vue"]]),S=JSON.parse('{"path":"/plugins/search.html","title":"search","lang":"en-US","frontmatter":{"description":"search","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/search.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/search.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"search"}],["meta",{"property":"og:description","content":"search"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"search\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Local Search Index","slug":"local-search-index","link":"#local-search-index","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"locales","slug":"locales","link":"#locales","children":[]},{"level":3,"title":"hotKeys","slug":"hotkeys","link":"#hotkeys","children":[]},{"level":3,"title":"maxSuggestions","slug":"maxsuggestions","link":"#maxsuggestions","children":[]},{"level":3,"title":"isSearchable","slug":"issearchable","link":"#issearchable","children":[]},{"level":3,"title":"getExtraFields","slug":"getextrafields","link":"#getextrafields","children":[]}]},{"level":2,"title":"Styles","slug":"styles","link":"#styles","children":[]},{"level":2,"title":"Components","slug":"components","link":"#components","children":[{"level":3,"title":"SearchBox","slug":"searchbox","link":"#searchbox","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/search.md"}');export{w as comp,S as data};
diff --git a/assets/shared.html-D0wa8tc_.js b/assets/shared.html-D0wa8tc_.js
new file mode 100644
index 0000000000..ea12896d25
--- /dev/null
+++ b/assets/shared.html-D0wa8tc_.js
@@ -0,0 +1,110 @@
+import{_ as s,o as n,c as e,e as a}from"./app-3y2wReKQ.js";const l={},o=a(`
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
So we provide encodeData and decodeData to zip and encode content.
getDate(x): Convert input x to a date. It can support Date, timestamp, and date string. The support degree of date string depends on the Date.parse support degree of the environment. Return null when it cannot be converted to a date.
Example
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
dateSorter: Sort the values that can be converted to dates from new to old, and the values that cannot be converted to dates will be at the end.
isLinkWithProtocol(x): Check if x is a valid URL with protocol.
isLinkExternal(x): Check if x is a valid external URL.
isLinkAbsolute(x): Check if x is a valid absolute URL.
ensureEndingSlash(x): Ensure x ends with a slash.
ensureLeadingSlash(x): Ensure x starts with a slash.
removeEndingSlash(x): Ensure x does not end with a slash.
removeLeadingSlash(x): Ensure x does not start with a slash.
`,20),p=[o];function t(i,c){return n(),e("div",null,p)}const d=s(l,[["render",t],["__file","shared.html.vue"]]),u=JSON.parse('{"path":"/tools/helper/shared.html","title":"Shared Methods","lang":"en-US","frontmatter":{"description":"Shared Methods The following functions are available on both Node.js and Client. Data Related Encode/decode and zip/unzip data. This is useful in markdown plugins when you want ...","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/tools/helper/shared.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Shared Methods"}],["meta",{"property":"og:description","content":"Shared Methods The following functions are available on both Node.js and Client. Data Related Encode/decode and zip/unzip data. This is useful in markdown plugins when you want ..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-03T11:34:35.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-03T11:34:35.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Shared Methods\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-03T11:34:35.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Data Related","slug":"data-related","link":"#data-related","children":[]},{"level":2,"title":"Type Helper","slug":"type-helper","link":"#type-helper","children":[]},{"level":2,"title":"String Related","slug":"string-related","link":"#string-related","children":[]},{"level":2,"title":"对象相关","slug":"对象相关","link":"#对象相关","children":[]},{"level":2,"title":"Date Related","slug":"date-related","link":"#date-related","children":[]},{"level":2,"title":"Link Related","slug":"link-related","link":"#link-related","children":[]}],"git":{"updatedTime":1706960075000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"tools/helper/shared.md"}');export{d as comp,u as data};
diff --git a/assets/shared.html-Do3WAFxL.js b/assets/shared.html-Do3WAFxL.js
new file mode 100644
index 0000000000..0b3b7b8226
--- /dev/null
+++ b/assets/shared.html-Do3WAFxL.js
@@ -0,0 +1,110 @@
+import{_ as s,o as n,c as a,e as l}from"./app-3y2wReKQ.js";const e={},o=l(`
getDate(x): 将输入 x 转换为日期,可以支持 Date,时间戳,日期字符串。日期字符串的支持度以环境的 Date.parse 支持度为准。当不能转换为日期时返回 null
示例
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
`,5),f=e("li",null,[e("p",null,[s("Type: "),e("code",null,"ShikiLang[]")])],-1),D=e("li",null,[e("p",null,"Details:"),e("p",null,"Languages of code blocks to be parsed by Shiki."),e("p",null,[s("This option will be forwarded to "),e("code",null,"getHighlighter()"),s(" method of Shiki.")]),e("p",null,"You'd better provide the languages list you are using explicitly, otherwise Shiki will load all languages and can affect performance.")],-1),b=e("p",null,"Also see:",-1),v={href:"https://shiki.style/languages",target:"_blank",rel:"noopener noreferrer"},C=e("h3",{id:"theme",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#theme"},[e("span",null,"theme")])],-1),x=o("
Type: ShikiTheme
Default: 'nord'
Details:
Theme of Shiki.
This option will be forwarded to codeToHtml() method of Shiki.
`,12);function C(v,b){const p=a("NpmBadge"),e=a("ExternalLinkIcon");return c(),D("div",null,[i,l(p,{package:"@vuepress/theme-default"}),s("p",null,[n("The default theme uses "),s("a",y,[n("SASS"),l(e)]),n(" as the CSS pre-processor.")]),d])}const m=o(t,[["render",C],["__file","styles.html.vue"]]),u=JSON.parse('{"path":"/themes/default/styles.html","title":"Styles","lang":"en-US","frontmatter":{"description":"Styles","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/styles.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/themes/default/styles.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"Styles"}],["meta",{"property":"og:description","content":"Styles"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"Styles\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Palette File","slug":"palette-file","link":"#palette-file","children":[]},{"level":2,"title":"Style File","slug":"style-file","link":"#style-file","children":[]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"themes/default/styles.md"}');export{m as comp,u as data};
diff --git a/assets/styles.html-icxS2iTp.js b/assets/styles.html-icxS2iTp.js
new file mode 100644
index 0000000000..fb237559d1
--- /dev/null
+++ b/assets/styles.html-icxS2iTp.js
@@ -0,0 +1,275 @@
+import{_ as e,r as a,o as c,c as D,a as l,b as s,d as n,e as r}from"./app-3y2wReKQ.js";const t={},i=s("h1",{id:"样式",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#样式"},[s("span",null,"样式")])],-1),y={href:"https://sass-lang.com/",target:"_blank",rel:"noopener noreferrer"},d=r(`
`,12);function C(v,b){const p=a("NpmBadge"),o=a("ExternalLinkIcon");return c(),D("div",null,[i,l(p,{package:"@vuepress/theme-default"}),s("p",null,[n("默认主题使用 "),s("a",y,[n("SASS"),l(o)]),n(" 作为 CSS 预处理器。")]),d])}const m=e(t,[["render",C],["__file","styles.html.vue"]]),u=JSON.parse('{"path":"/zh/themes/default/styles.html","title":"样式","lang":"zh-CN","frontmatter":{"description":"样式","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/themes/default/styles.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/themes/default/styles.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"样式"}],["meta",{"property":"og:description","content":"样式"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-01-30T09:08:43.000Z"}],["meta",{"property":"article:modified_time","content":"2024-01-30T09:08:43.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"样式\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-01-30T09:08:43.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"Palette 文件","slug":"palette-文件","link":"#palette-文件","children":[]},{"level":2,"title":"Style 文件","slug":"style-文件","link":"#style-文件","children":[]}],"git":{"updatedTime":1706605723000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":1}]},"autoDesc":true,"filePathRelative":"zh/themes/default/styles.md"}');export{m as comp,u as data};
diff --git a/assets/theme-data.html-8J8-E5uR.js b/assets/theme-data.html-8J8-E5uR.js
new file mode 100644
index 0000000000..12a76bdb84
--- /dev/null
+++ b/assets/theme-data.html-8J8-E5uR.js
@@ -0,0 +1,51 @@
+import{_ as p,r as a,o,c as i,a as n,b as s,d as e,e as c}from"./app-3y2wReKQ.js";const r={},d=s("h1",{id:"theme-data",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#theme-data"},[s("span",null,"theme-data")])],-1),D={href:"https://vuejs.press/guide/i18n.html",target:"_blank",rel:"noopener noreferrer"},m=c(`
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.
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.
`,17);function y(u,h){const l=a("NpmBadge"),t=a("ExternalLinkIcon");return o(),i("div",null,[d,n(l,{package:"@vuepress/plugin-theme-data"}),s("p",null,[e("Provide client data for your theme, with VuePress "),s("a",D,[e("i18n"),n(t)]),e(" support.")]),m])}const C=p(r,[["render",y],["__file","theme-data.html.vue"]]),b=JSON.parse('{"path":"/plugins/theme-data.html","title":"theme-data","lang":"en-US","frontmatter":{"description":"theme-data","head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/theme-data.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/theme-data.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"theme-data"}],["meta",{"property":"og:description","content":"theme-data"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"theme-data\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"themeData","slug":"themedata","link":"#themedata","children":[]}]},{"level":2,"title":"Composition API","slug":"composition-api","link":"#composition-api","children":[{"level":3,"title":"useThemeData","slug":"usethemedata","link":"#usethemedata","children":[]},{"level":3,"title":"useThemeLocaleData","slug":"usethemelocaledata","link":"#usethemelocaledata","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"plugins/theme-data.md"}');export{C as comp,b as data};
diff --git a/assets/theme-data.html-KLwmCASr.js b/assets/theme-data.html-KLwmCASr.js
new file mode 100644
index 0000000000..af138392b6
--- /dev/null
+++ b/assets/theme-data.html-KLwmCASr.js
@@ -0,0 +1,51 @@
+import{_ as t,r as e,o,c,a as n,b as s,d as a,e as i}from"./app-3y2wReKQ.js";const r={},D=s("h1",{id:"theme-data",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#theme-data"},[s("span",null,"theme-data")])],-1),d={href:"https://vuejs.press/zh/guide/i18n.html",target:"_blank",rel:"noopener noreferrer"},m=i(`
`,17);function y(h,u){const l=e("NpmBadge"),p=e("ExternalLinkIcon");return o(),c("div",null,[D,n(l,{package:"@vuepress/plugin-theme-data"}),s("p",null,[a("为你的主题提供客户端数据,包含 VuePress 的 "),s("a",d,[a("多语言支持"),n(p)]),a(" 。")]),m])}const v=t(r,[["render",y],["__file","theme-data.html.vue"]]),b=JSON.parse('{"path":"/zh/plugins/theme-data.html","title":"theme-data","lang":"zh-CN","frontmatter":{"description":"theme-data","head":[["link",{"rel":"alternate","hreflang":"en-us","href":"https://ecosystem.vuejs.press/ecosystem/plugins/theme-data.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/theme-data.html"}],["meta",{"property":"og:site_name","content":"VuePress 生态系统"}],["meta",{"property":"og:title","content":"theme-data"}],["meta",{"property":"og:description","content":"theme-data"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"zh-CN"}],["meta",{"property":"og:locale:alternate","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"theme-data\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/atom.xml","title":"VuePress 生态系统 Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/zh/feed.json","title":"VuePress 生态系统 JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/zh/rss.xml","title":"VuePress 生态系统 RSS Feed"}]]},"headers":[{"level":2,"title":"使用方法","slug":"使用方法","link":"#使用方法","children":[]},{"level":2,"title":"配置项","slug":"配置项","link":"#配置项","children":[{"level":3,"title":"themeData","slug":"themedata","link":"#themedata","children":[]}]},{"level":2,"title":"Composition API","slug":"composition-api","link":"#composition-api","children":[{"level":3,"title":"useThemeData","slug":"usethemedata","link":"#usethemedata","children":[]},{"level":3,"title":"useThemeLocaleData","slug":"usethemelocaledata","link":"#usethemelocaledata","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":2}]},"autoDesc":true,"filePathRelative":"zh/plugins/theme-data.md"}');export{v as comp,b as data};
diff --git a/assets/toc.html-DM1CDSLF.js b/assets/toc.html-DM1CDSLF.js
new file mode 100644
index 0000000000..e4bcc0c922
--- /dev/null
+++ b/assets/toc.html-DM1CDSLF.js
@@ -0,0 +1,74 @@
+import{_ as i,r as l,o as r,c as d,a,b as n,d as s,w as p,e}from"./app-3y2wReKQ.js";const y={},D=n("h1",{id:"toc",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#toc"},[n("span",null,"toc")])],-1),u=e(`
This plugin will provide a table-of-contents (TOC) component.
`,20);function E(b,k){const t=l("NpmBadge"),c=l("ExternalLinkIcon"),o=l("RouteLink");return r(),d("div",null,[D,a(t,{package:"@vuepress/plugin-toc"}),u,n("p",null,[s("Similar to the "),n("a",m,[s("Table of Contents Markdown Syntax"),a(c)]),s(", the TOC component that provided by this plugin could be used in your markdown content directly:")]),v,n("p",null,[s("This plugin could work together with "),a(o,{to:"/plugins/active-header-links.html"},{default:p(()=>[s("@vuepress/plugin-active-header-links")]),_:1}),s(" by setting the "),a(o,{to:"/plugins/active-header-links.html#headerlinkselector"},{default:p(()=>[s("headerLinkSelector")]),_:1}),s(" to match the "),C,s(" option. When the page scroll to a certain header anchor, this corresponding link will be added "),h,s(" class name.")]),g])}const x=i(y,[["render",E],["__file","toc.html.vue"]]),F=JSON.parse('{"path":"/plugins/toc.html","title":"toc","lang":"en-US","frontmatter":{"head":[["link",{"rel":"alternate","hreflang":"zh-cn","href":"https://ecosystem.vuejs.press/ecosystem/zh/plugins/toc.html"}],["meta",{"property":"og:url","content":"https://ecosystem.vuejs.press/ecosystem/plugins/toc.html"}],["meta",{"property":"og:site_name","content":"VuePress Ecosystem"}],["meta",{"property":"og:title","content":"toc"}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:locale:alternate","content":"zh-CN"}],["meta",{"property":"og:updated_time","content":"2024-02-21T05:33:46.000Z"}],["meta",{"property":"article:modified_time","content":"2024-02-21T05:33:46.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"toc\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2024-02-21T05:33:46.000Z\\",\\"author\\":[]}"],["link",{"rel":"alternate","type":"application/atom+xml","href":"https://ecosystem.vuejs.press/ecosystem/atom.xml","title":"VuePress Ecosystem Atom Feed"}],["link",{"rel":"alternate","type":"application/json","href":"https://ecosystem.vuejs.press/ecosystem/feed.json","title":"VuePress Ecosystem JSON Feed"}],["link",{"rel":"alternate","type":"application/rss+xml","href":"https://ecosystem.vuejs.press/ecosystem/rss.xml","title":"VuePress Ecosystem RSS Feed"}]]},"headers":[{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Differences with Markdown TOC Syntax","slug":"differences-with-markdown-toc-syntax","link":"#differences-with-markdown-toc-syntax","children":[]},{"level":2,"title":"Options","slug":"options","link":"#options","children":[{"level":3,"title":"componentName","slug":"componentname","link":"#componentname","children":[]},{"level":3,"title":"defaultPropsOptions","slug":"defaultpropsoptions","link":"#defaultpropsoptions","children":[]}]},{"level":2,"title":"Component Props","slug":"component-props","link":"#component-props","children":[{"level":3,"title":"headers","slug":"headers","link":"#headers","children":[]},{"level":3,"title":"options","slug":"options-1","link":"#options-1","children":[]}]}],"git":{"updatedTime":1708493626000,"contributors":[{"name":"Mr.Hope","email":"mister-hope@outlook.com","commits":5}]},"filePathRelative":"plugins/toc.md"}');export{x as comp,F as data};
diff --git a/assets/toc.html-DWGvp7l1.js b/assets/toc.html-DWGvp7l1.js
new file mode 100644
index 0000000000..c49e5fa5a6
--- /dev/null
+++ b/assets/toc.html-DWGvp7l1.js
@@ -0,0 +1,74 @@
+import{_ as r,r as l,o as i,c as d,a,b as n,d as s,w as o,e}from"./app-3y2wReKQ.js";const D={},y=n("h1",{id:"toc",tabindex:"-1"},[n("a",{class:"header-anchor",href:"#toc"},[n("span",null,"toc")])],-1),u=e(`
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:
+
+
A NavbarItem object should have a text field and a link field, could have an optional activeMatch field.
+
A NavbarGroup object should have a text field and a children field. The children field should be a navbar array, too.
+
A string should be the path to the target page file. It will be converted to a NavbarItem object, using the page title as text, and the page route path as link.
If not specified, defaults to be the same as the site title.
+
+
+
repo
+
+
+
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',
+ }),
+}
+
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:
+
+
A 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.
+
A string should be the path to the target page file. It will be converted to a 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:
+
+
The key should be the path prefix.
+
The value should be a sidebar array or set to 'heading' to automatically generate the sidebar from the page headers for just the corresponding path.
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
+
+
Set to 0 to disable all levels of headers.
+
Set to 1 to include <h2> headers.
+
Set to 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.
+
+
+
editLink
+
+
+
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.
+
+
+
editLinkPattern
+
+
+
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 |
+|
+
+
+]]>
+
+
+ Extending
+ https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html
+
+ 2024-01-30T14:33:01.000Z
+ VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
+
Layout Slots
+
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
+
]]>
+ VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
+
Layout Slots
+
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:
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):
+
+
Components Replacement
+
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:
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',
+ ),
+ },
+ }
+}
+
If your site is served in a different language besides English, you should set these options per locale to provide translations.
+
repoLabel
+
+
+
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.
+
+
]]>
+ 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.
+
repoLabel
+
+
+
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.
+
+
+
selectLanguageText
+
+
+
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.
+
+
+
selectLanguageAriaLabel
+
+
+
Type: string
+
+
+
Details:
+
Specify the aria-label attribute of the select language menu.
+
This is mainly for a11y purpose.
+
+
+
selectLanguageName
+
+
+
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.
+]]>
+
+
+ Markdown
+ https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html
+
+ 2024-01-30T09:08:43.000Z
+
+
+
+
+ Plugins Config
+ https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html
+
+ 2024-02-21T05:33:46.000Z
+ 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.
]]>
+ 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.
Page filter, determine whether the plugin should generate excerpt for it.
+
TIP
+
You should use this to skip pages that you don't need to generate excerpt for. E.g.: If users set excerpt or description in frontmatter, you may want to use them directly.
This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.
+
+
+
metaScope
+
+
+
Type: string
+
+
+
Default: "_blog"
+
+
+
Details:
+
Key used when injecting info to route meta.
+
TIP
+
Setting to an empty key will inject to route meta directly instead of a field.
+
+
+
+
hotReload
+
+
+
Type: boolean
+
+
+
Default: Whether using --debug flag
+
+
+
Details:
+
Whether enable hotReload in devServer.
+
To theme developers
+
It's disabled by default because it does have performance impact in sites with a lot of categories and types. And it can slow down hotReload speed when editing Markdown.
+
If users are adding or organizing your categories or tags, you may tell them to enable this, for the rest it's better to keep it disabled.
+
Also, you can try to detect number of pages in users project and decide whether to enable it.
+
+
+
+
Blog Category Config
+
Blog category config should be an array, while each item is controlling a "category" rule.
+
interface BlogCategoryOptions {
+ /**
+ * Unique category name
+ */
+ key: string
+
+ /**
+ * Function getting category from page
+ */
+ getter: (page: Page) => string[]
+
+ /**
+ * A custom function to sort the pages
+ */
+ sorter?: (pageA: Page, pageB: Page) => number
+
+ /**
+ * Path pattern of page to be registered
+ *
+ * @description `:key` will be replaced by the "slugify" result of the original key
+ *
+ * @default `/:key/`
+ */
+ path?: string
+
+ /**
+ * Page layout name
+ *
+ * @default 'Layout'
+ */
+ layout?: string
+
+ /**
+ * Frontmatter
+ */
+ frontmatter?: (localePath: string) => Record<string, string>
+
+ /**
+ * Item page path pattern or custom function to be registered
+ *
+ * @description When filling in a string, `:key` and `:name` will be replaced by the "slugify" result of the original key and name
+ *
+ * @default `/:key/:name/`
+ */
+ itemPath?: string | ((name: string) => string)
+
+ /**
+ * Item page layout name
+ *
+ * @default 'Layout'
+ */
+ itemLayout?: string
+
+ /**
+ * Items Frontmatter
+ */
+ itemFrontmatter?: (name: string, localePath: string) => Record<string, string>
+}
+
Blog Type Config
+
Blog type config should be an array, while each item is controlling a "type" rule.
+
interface BlogTypeOptions {
+ /**
+ * Unique type name
+ */
+ key: string
+
+ /**
+ * A filter function to determine whether a page should be the type
+ */
+ filter: (page: Page) => boolean
+
+ /**
+ * A custom function to sort the pages
+ */
+ sorter?: (pageA: Page, pageB: Page) => number
+
+ /**
+ * Page path to be registered
+ *
+ * @default '/:key/'
+ */
+ path?: string
+
+ /**
+ * Layout name
+ *
+ * @default 'Layout'
+ */
+ layout?: string
+
+ /**
+ * Frontmatter
+ */
+ frontmatter?: (localePath: string) => Record<string, string>
+}
+
Composition API
+
You can import the following API from @vuepress/plugin-blog/client.
If no key is passed, the plugin will try to use the key in current path.
+
+
+
Returning values are:
+
interface Article<T extends Record<string, unknown> = Record<string, unknown>> {
+ /** Article path */
+ path: string
+ /** Article info */
+ info: T
+}
+
+interface BlogCategoryData<
+ T extends Record<string, unknown> = Record<string, unknown>,
+> {
+ /** Category path */
+ path: string
+
+ /**
+ * Only available when current route matches an item path
+ */
+ currentItems?: Article<T>[]
+
+ /** Category map */
+ map: {
+ /** Unique key under current category */
+ [key: string]: {
+ /** Category path of the key */
+ path: string
+ /** Category items of the key */
+ items: Article<T>[]
+ }
+ }
+}
+
+interface BlogTypeData<
+ T extends Record<string, unknown> = Record<string, unknown>,
+> {
+ /** Type path */
+ path: string
+
+ /** Items under current type */
+ items: Article<T>[]
+}
+
]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html
+
+ 2024-02-19T18:01:19.000Z
+ With @vuepress/plugin-blog, you can easily bring blog feature into your theme.
+
Collecting Articles
+
The plugin filters all pages using filter option to drop pages you don't want.
+
By default, all pages generating from Markdown files but not homepage are considered as articles.
+
+
You can fully customize pages to collect through option filter, which accepts a function (page: Page) => boolean.
+
Gathering Info
+
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
+
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
+Demo
+
import { blogPlugin } from '@vuepress/plugin-blog'
+
+export default {
+ name: 'vuepress-theme-xxx',
+ plugins: [
+ blogPlugin({
+ filter: ({ filePathRelative, frontmatter }) => {
+ // drop those pages which is NOT generated from file
+ if (!filePathRelative) return false
+
+ // drop those pages in `archives` directory
+ if (filePathRelative.startsWith('archives/')) return false
+
+ // drop those pages which do not use default layout
+ if (frontmatter.home || frontmatter.layout) return false
+
+ return true
+ },
+
+ getInfo: ({ frontmatter, git = {}, data = {} }) => {
+ // getting page info
+ const info: Record<string, any> = {
+ author: frontmatter.author || '',
+ categories: frontmatter.categories || [],
+ date: frontmatter.date || git.createdTime || null,
+ tags: frontmatter.tags || [],
+ excerpt: data.excerpt || '',
+ }
+
+ return info
+ },
+ }),
+ // other plugins ...
+ ],
+}
+
+
Customizing Categories and Types
+
Basically, you would want 2 types of collection in your blog:
+
+
+
Category:
+
"Category" means grouping articles with their labels.
+
For example, each article may have their "categories" and "tags".
+
+
+
Type:
+
"Type" means identifying articles with conditions.
+
For example, you may want to describe some of your articles as diary.
+
+
+
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
+
Let's start with 2 examples here.
+
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
+
interface BlogFrontmatterOptions {
+ /** Current type of the page */
+ type: 'category' | 'type'
+ /** Unique key under current category or tag */
+ key: string
+ /**
+ * Current category name
+ *
+ * @description Only available in category item page
+ */
+ name?: string
+}
+
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
+
Also, you can pass key you want as argument, then you will get information bind to that key.
+
So with node side settings above, you can get information about "tag" and "star" in client side:
Then /zh/star/ and /star/ will both be available, and only articles under the correct locale will appear.
+
Generating Excerpt
+
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
+
Excerpt introduction
+
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
+
+
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
+
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
+
+
+
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default `
+]]>
+ With @vuepress/plugin-blog, you can easily bring blog feature into your theme.
+
Collecting Articles
+
The plugin filters all pages using filter option to drop pages you don't want.
+
By default, all pages generating from Markdown files but not homepage are considered as articles.
+
+
You can fully customize pages to collect through option filter, which accepts a function (page: Page) => boolean.
+
Gathering Info
+
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
+
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
+Demo
+
import { blogPlugin } from '@vuepress/plugin-blog'
+
+export default {
+ name: 'vuepress-theme-xxx',
+ plugins: [
+ blogPlugin({
+ filter: ({ filePathRelative, frontmatter }) => {
+ // drop those pages which is NOT generated from file
+ if (!filePathRelative) return false
+
+ // drop those pages in `archives` directory
+ if (filePathRelative.startsWith('archives/')) return false
+
+ // drop those pages which do not use default layout
+ if (frontmatter.home || frontmatter.layout) return false
+
+ return true
+ },
+
+ getInfo: ({ frontmatter, git = {}, data = {} }) => {
+ // getting page info
+ const info: Record<string, any> = {
+ author: frontmatter.author || '',
+ categories: frontmatter.categories || [],
+ date: frontmatter.date || git.createdTime || null,
+ tags: frontmatter.tags || [],
+ excerpt: data.excerpt || '',
+ }
+
+ return info
+ },
+ }),
+ // other plugins ...
+ ],
+}
+
+
Customizing Categories and Types
+
Basically, you would want 2 types of collection in your blog:
+
+
+
Category:
+
"Category" means grouping articles with their labels.
+
For example, each article may have their "categories" and "tags".
+
+
+
Type:
+
"Type" means identifying articles with conditions.
+
For example, you may want to describe some of your articles as diary.
+
+
+
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
+
Let's start with 2 examples here.
+
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
+
interface BlogFrontmatterOptions {
+ /** Current type of the page */
+ type: 'category' | 'type'
+ /** Unique key under current category or tag */
+ key: string
+ /**
+ * Current category name
+ *
+ * @description Only available in category item page
+ */
+ name?: string
+}
+
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
+
Also, you can pass key you want as argument, then you will get information bind to that key.
+
So with node side settings above, you can get information about "tag" and "star" in client side:
Then /zh/star/ and /star/ will both be available, and only articles under the correct locale will appear.
+
Generating Excerpt
+
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
+
Excerpt introduction
+
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
+
+
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
+
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
+
+
+
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default <!-- more -->, and you can customize it by setting excerptSeparator option.
+
If it cannot find a valid separator, it will parse content from the beginning of markdown file, and stop till its length reaches a preset value. The value is default 300, and you can customize it by setting excerptLength option.
+
To choose which page should generate excerpt, you can use excerptFilter option.
+
Example
+
Normally you may want to use frontmatter.description if users set them, so you can let filter function return false if frontmatter.description is not empty.
But here are some limitations you should remember:
+
+
+
provider, locales and other resource related option must be set in plugin options.
+
To ensure tree-shaking works, we must optimize entries at node so that bundler can understand which resource should be included in the final bundle.
+
These options will be marked with
+
+
+
Options which can not be serialized to JSON must be set in client config.
+
Options that receives function values can not be set in plugin options, as plugins are running under Node.js environment, so we can not pass these values and their contexts to browser.
+
These options will be marked with
+
+
+
Adding Comment
+
This plugin globally registers a component <CommentService />.
+
+
If you are a user, you should use alias and layout slots to insert the component. We recommended you to insert the comment component (<CommentService />) after the <PageNav /> component, and the current page is a demo with default theme.
+
If you are a theme developer, you should insert this component in the layout of your theme.
+
+
By default, <CommentService /> component is enabled globally, and you can use comment option in both plugin options and page frontmatter to control it.
+
+
You can disable it locally by setting comment: false in page frontmatter.
+
To keep it globally disabled, please set comment to false in the plugin options. Then you can set comment: true in page frontmatter to enable it locally.
+
+
You can set commentID option in page frontmatter to customize comment ID, which is used to identify comment storage item to use for a page. By default it will be the path of the page, which means if you are deploying the site to multiple places, page with same content across sites will share the same comment data.
A custom filter function, used to filter feed items.
+
sorter
+
+
+
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.
The plugin has a built-in getter, only set this if you want full control of feed generation.
+
+
locales
+
+
Type: Record<string, BaseFeedOptions>
+
+
You can use it to specific options for each locale.
+
Any options above are supported except hostname.
+]]>
+
+
+ Frontmatter Config
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html
+
+ 2024-02-01T04:46:03.000Z
+ You can control each feed item generation by setting page frontmatter.
+
Additions and Removals
+
By default, all articles are added to the feed stream. Set feed: false in frontmatter to remove a page from feed.
+
Frontmatter Information
+
title
+
+
Type: string
+
]]>
+ You can control each feed item generation by setting page frontmatter.
+
Additions and Removals
+
By default, all articles are added to the feed stream. Set feed: false in frontmatter to remove a page from feed.
+
Frontmatter Information
+
title
+
+
Type: string
+
+
Automatically generated by VuePress, defaults to the h1 content of the page
+
description
+
+
Type: string
+
+
Description of the page
+
date
+
+
Type: Date
+
+
Date when the page was published
+
article
+
+
Type: boolean
+
+
Whether the page is an article
+
+
If this is set to false, the page will not be included in the final feed.
+
+
copyright
+
+
Type: string
+
+
Page copyright information
+
cover / image / banner
+
+
Type: string
+
+
Image used as page cover , should be full link or absolute link.
The identifier of feed item, used to identify the feed item.
+
You should ensure every feed has a unique guid.
+
+]]>
+
+
+ Feed Getter
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/getter.html
+
+ 2024-02-01T04:46:03.000Z
+ You can take full control of feed items generation by setting getter in the plugin options.
+
getter.title
+
+
Type: (page: Page) => string
+
+
Item title getter
+
getter.link
+
+
Type: (page: Page) => string
+
]]>
+ You can take full control of feed items generation by setting getter in the plugin options.
+
getter.title
+
+
Type: (page: Page) => string
+
+
Item title getter
+
getter.link
+
+
Type: (page: Page) => string
+
+
Item link getter
+
getter.description
+
+
Type: (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:.
+
+
getter.content
+
+
Type: (page: Page) => string
+
+
Item content getter
+
getter.author
+
+
Type: (page: Page) => FeedAuthor[]
+
+
Item author getter.
+
The getter should return an empty array when author information is missing.
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
+}
+
+
getter.enclosure
+
+
Type: (page: Page) => FeedEnclosure | undefined
+
+
Item enclosure getter.
+FeedEnclosure format
+
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
+}
+
+
getter.publishDate
+
+
Type: (page: Page) => Date | undefined
+
+
Item release date getter
+
getter.lastUpdateDate
+
+
Type: (page: Page) => Date
+
+
Item last update date getter
+
getter.image
+
+
Type: (page: Page) => string
+
+
Item Image Getter
+
Ensure it's returning a full URL
+
+
getter.contributor
+
+
Type: (page: Page) => FeedContributor[]
+
+
Item Contributor Getter
+
The getter should return an empty array when contributor information is missing.
The plugin can generate feed files in the following three formats for you:
+
+
Atom 1.0
+
JSON 1.1
+
RSS 2.0
+
+
Please set atom, json or rss to true in the plugin options according to the formats you want to generate.
]]>
+ Usage
+
The plugin can generate feed files in the following three formats for you:
+
+
Atom 1.0
+
JSON 1.1
+
RSS 2.0
+
+
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,
+
Readable Preview
+
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}.
+
Channel settings
+
You can customize the feed channel information by setting the channel option.
+
We recommend the following settings:
+
+
Convert the date of creating the feed to ISOString and write it into channel.pubDate
+
The update period of the content set in channel.ttl (unit: minutes)
+
Set copyright information via channel.copyright
+
Set the channel author via channel.author.
+
+
For detailed options and their default values, see Channel Config
+
Feed Generation
+
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.
+
I18n Config
+
The plugin generates separate feeds for each language.
+
You can provide different settings for different languages via locales in the plugin options.
Whether cache HTML files besides home page and 404 page.
+
+
+
cacheImage
+
+
+
Type: boolean
+
+
+
Default: false
+
+
+
Details:
+
Whether cache pictures
+
+
+
maxSize
+
+
+
Type: number
+
+
+
Default: 2048
+
+
+
Details:
+
Max size allowed to be cached, with KB unit
+
WARNING
+
This option has the highest priority, and any files exceeding this value will be excluded.
+
So if you generate very large HTML or JS files, please consider increasing this value, otherwise your PWA may not work normally in offline mode.
+
+
+
+
maxImageSize
+
+
+
Type: number
+
+
+
Default: 1024
+
+
+
Details:
+Max picture size allowed to be cached, with KB unit
+
The value must not be greater than maxSize option
+
+
+
+
update
+
+
+
Type: "disabled" | "available" | "hint" | "force"
+
+
+
Default: "available"
+
+
+
Details:
+Control logic when new content is found.
+
+
+
"disabled": Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
+
+
+
"available": Only display update popup when the new service worker is available
+
+
+
"hint": Display a hint to let user choose to refresh immediately
+
This is helpful when you want users to see new docs immediately.
+
TIP
+
If users choose to refresh, the current service worker will be unregister, and request will start coming to web. Later the new service worker will start installing and control current page after installed.
+
+
+
+
"force": unregister current service worker immediately then refresh to get new content
+
DANGER
+
Although this ensures users are viewing the latest content, it may affect viewing experiences.
+
+
+
+
TIP
+
How docs are updated is controlled by a previous version, so the current option only effect next update from this version.
+
+
+
+
apple
+
Special settings for better supporting Safari, ignoring these options are safe.
+
apple.icon
+
+
Type: string
+
Details: Icon link used by Safari.
+
+
apple.statusBarColor
+
+
Type: "black" | "white"
+
Default: "black"
+
Details: Status bar color for Safari
+
+
apple.maskIcon
+
+
Type: string
+
Details: Safari mask icon
+
+
msTile
+
Special settings for Microsoft tiles, ignoring these options are safe.
+
msTile.image
+
+
Type: string
+
Details: Tile image
+
+
msTile.color
+
+
Type: string
+
Default value: themeColor
+
Details: Tile color
+
+
foundComponent
+
+
Type: string
+
Default: "PwaFoundPopup"
+
Details: Path of custom hint popup component.
+
+
readyComponent
+
+
Type: string
+
Default: "PwaReadyPopup"
+
Details: Path of custom update popup component.
+
+
appendBase
+
+
Type: boolean
+
Default: false
+
Details: Whether append base to all absolute links in options.
To better control what the Service Worker can pre-cache, the plugin provides related options for cache control.
+
Default cache
+
By default, the plugin will pre-cache all jscss files, and only homepage and 404 html are cached. The plugin will also cache font files (woff, woff2, eot, ttf, otf) and SVG icons.
+
Image Cache
+
If your site has only a few important images, and want them displayed in offline mode, you can cache site images by setting cacheImage: true .
+
We recognize images by file extension. Any files ending with .png, .jpg, .jpeg, .gif, .bmp, .webp will be regarded as images.
+
HTML Cache
+
If you have small sites, and would like to make document fully offline available, you can set cacheHTML to true to cache all HTML files.
+
Why only home and 404 page been cached by default?
To prevent large files from being included in the pre-cache list, any files > 2 MB or images > 1 MB will be omitted. You can customize these limits with maxSize and maxImageSize options (in KB unit).
+
Update Control
+
We provide the update option to control how users receive updates.
+
The default value of the update option is "available", which means that when new content available, the new SW will be installed and its resources will be fetched silently in the background. A pop-up window appears once the new SW is ready, and users can choose whether to refresh immediately to view new content. This means users are reading old content before a new SW is ready.
+
If your project is still in building stage, and you want to alert the user that he may be reading outdated content, you can set this to "hint". This allows users to be notified that new content has been published within seconds after visiting docs. But the negative effect of this is that if the user chooses to update before the new SW is ready, he will need to get all the resources of the page from the internet before the new SW installs and controls the page.
+
If your docs are stable, or you're hosting a blog and don't care much about users receiving the latest version right away, you can set this to "disabled", which means that the new SW will be installed completely silently in the background and start waiting, when all pages controlled by old SW are all closed, the new SW will start to take control and provide users with new content during next visit. This setting can prevent users from being disturbed during the visit.
+
To speed up user access under weak or no network conditions through SW, but also want users to always access new content, you can set this option to "force". This means any old SW will be removed as soon as a new SW is detected, and all pages are refreshed to ensure the user is browsing the latest content. The biggest disadvantage is that all users will experience unexpected sudden refresh within seconds after reentering an updated site.
+
Popups
+
When new content is detected (new SW detected), a update found popup appears; and when the new content is ready, an update ready popup appears.
+
If you are not satisfied with the default popup content, you can use your own component. Import PwaFoundPopup or PwaReadyPopup from @vuepress/plugin-pwa/client and use its slot to customize the popup content, then pass the component path to foundComponent or readyComponent option:
The plugin also provides other PWA-related options, such as Microsoft tile icon and color settings, Apple icon and so on. If you are an advanced user, you can also set generateSwConfig to configure workbox-build. Check Plugin options for more details.
The Service Worker will get and cache all the files registered in it during the registration process.
+
+
+
After the registration complete, the Service Worker is activated, and starts to proxy and control all your requests.
+
+
+
Whenever you want to initiate an access request through the browser, the Service Worker will check whether it exists in its own cache list, if it exists, it will directly return the cached result, otherwise it will call its own fetch method to get it. You can use a custom fetch method to fully control the result of the request for resources in the web page, such as providing a fallback web page when offline.
+
+
+
Every time the user reopens the site, the Service Worker will request to the link when it was registered. If a new version of Service Worker is detected, it will update itself and start caching the list of resources registered in the new Service Worker . After the content update is successfully obtained, the Service Worker will trigger the update event. The user can be notified through this event, for example, a pop-up window will be displayed in the lower right corner, prompting the user that new content is available and allowing the user to trigger an update.
The manifest file uses the JSON format and is responsible for declaring various information of the PWA, such as name, description, icon, and shortcut actions.
+
In order for your site to be registered as a PWA, you need to meet the basic specifications of the manifest to make the browser consider the site as an installable PWA and allow users to install it.
To let the site be registered as a PWA, the site needs to successfully register a valid service worker by itself, and declare a valid manifest file with its link in meta tag.
+
The manifest file should contain at least name (or short_name) iconsstart_url.
+
On safari, the maximum cache size of the service worker is 50 MB. ↩︎↩︎
SPA: Single Page Application, most of them only have the homepage, and use history mode to handle routing instead of actually navigating between pages. ↩︎
You can use this options to edit JSON-LD properties.
+
+
+
customHead
+
+
+
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>.
+
+
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html
+
+ 2024-03-10T14:51:27.000Z
+ This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site.
+]]>
+ This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site.
+
+
Out of Box
+
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:
+
Default OGP Generation
+
The following are the <meta> tags and their value injected into <head> by default to satisfy OGP:
Page default update frequency. This will override changefreq in Plugin Options.
+
+
+
sitemap.priority
+
+
+
Type: number
+
+
+
Default: 0.5
+
+
+
Details:
+
Page priority, range from 0 to 1.
+
+
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html
+
+ 2024-01-31T17:59:51.000Z
+ 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.
]]>
+ 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.
+
Control Sitemap Link
+
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.
+
Output Location
+
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.
+
Change Frequency
+
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"
+
+
Priority
+
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.
+
Modify Time
+
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();
+})
+
Sitemap Intro
+
Sitemaps provide SEO (Search Engine Optimization):
+
+
Provide search engine spiders with links of the entire site;
+
Provide some links for search engine spiders to dynamic pages or pages that are difficult to reach by other methods;
+
If a visitor attempts to access a URL that does not exist within the site's domain, the visitor will be directed to a "file not found" error page, and the sitemap can be used as a navigation page.
+
+
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)
+]]>
+
+
+ Shared Methods
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html
+
+ 2024-02-03T11:34:35.000Z
+ The following functions are available on both Node.js and Client.
+
Data Related
+
Encode/decode and zip/unzip data.
+
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
+
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
]]>
+ The following functions are available on both Node.js and Client.
+
Data Related
+
Encode/decode and zip/unzip data.
+
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
+
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
+
So we provide encodeData and decodeData to zip and encode content.
getDate(x): Convert input x to a date. It can support Date, timestamp, and date string. The support degree of date string depends on the Date.parse support degree of the environment. Return null when it cannot be converted to a date.
+Example
+
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
+
+
+
dateSorter: Sort the values that can be converted to dates from new to old, and the values that cannot be converted to dates will be at the end.
isLinkWithProtocol(x): Check if x is a valid URL with protocol.
+
isLinkExternal(x): Check if x is a valid external URL.
+
isLinkAbsolute(x): Check if x is a valid absolute URL.
+
ensureEndingSlash(x): Ensure x ends with a slash.
+
ensureLeadingSlash(x): Ensure x starts with a slash.
+
removeEndingSlash(x): Ensure x does not end with a slash.
+
removeLeadingSlash(x): Ensure x does not start with a slash.
+
+]]>
+
+
+ Artalk
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/
+
+ 2024-03-11T08:20:01.000Z
+ Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page.
+
Come to your blog, or anywhere, place the Artalk comment box, so that the page has rich social functions.
+]]>
+ Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page.
+
Come to your blog, or anywhere, place the Artalk comment box, so that the page has rich social functions.
The plugin retains the el option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the pageTitle, pageKey and site options for you according to the VuePress information.
+
+
Darkmode
+
To let Artalk apply the correct theme, you need to pass a boolean value to <CommentService /> through darkmode prop, representing whether the dark mode is currently enabled.
]]>
+
+
+ Giscus
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/
+
+ 2024-03-11T08:20:01.000Z
+ Giscus is a commenting system based on GitHub Discussion that is easy to start.
+]]>
+ Giscus is a commenting system based on GitHub Discussion that is easy to start.
+
+
Preparation
+
+
+
Create a public repository and open discussion panel as a place to store comments.
+
+
+
Install the Giscus App to have permission to access the corresponding repository.
+
+
+
After completing the above steps, please go to the Giscus page to get your settings.
+
You just need to fill in the repository and Discussion categories, then scroll to the "Enable giscus" section at the bottom of the page and obtain four attributes: data-repo, data-repo-id, data-category and data-category-id.
+
+
+
Config
+
Please set provider: "Giscus" and pass data-repo, data-repo-id, data-category and data-category-id as plugin options as repo, repoId, categorycategoryId.
By default, the theme of Giscus is light or dark (based on darkmode status).
+
Darkmode
+
To let Giscus apply the correct theme, you need to pass a boolean value to <CommentService /> via darkmode property, indicating whether darkmode is currently enabled.
+
+
If you want to customize theme in lightmode and darkmode, you can set lightTheme and darkTheme option with a built-in theme keyword or a custom CSS link starting with https://.
]]>
+
+
+ Twikoo
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/twikoo/
+
+ 2024-03-11T08:20:01.000Z
+ A concise, safe and free static site commenting system, based on Tencent Cloud Development.
+]]>
+ A concise, safe and free static site commenting system, based on Tencent Cloud Development.
+
+
Create a free MongoDB database, the recommended region is AWS / N. Virginia (us-east-1)
+
+
+
Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses (Why?), create Database user, and record the database connection string, please change the <password> in the connection string to the database password
Click the button below to deploy Twikoo to Vercel in one click
+
+
+
+
Go to Settings - Environment Variables, add the environment variable MONGODB_URI, the value is the database connection string in step 3
+
+
+
Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt "Twikoo cloud function is running normally"
+
+
+
Vercel Domains (with https:// prefix, e.g. https://xxx.vercel.app) is your environment ID
+
+
+
Configuration
+
Please set provider: "Twikoo" and set envId in the plugin options.
]]>
+
+
+ Waline
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/
+
+ 2024-03-11T08:20:01.000Z
+ A safe comment system with backend.
+]]>
+ A safe comment system with backend.
+
+
Click Create app button to create a new app and enter a name you like:
+
+
+
+
Enter the app, then select Settings > App Keys at the left bottom corner. You will see APP ID, APP Key and Master Key of your app. We will use them later
+
+
+
+
Deploy to Vercel (Server)
+
+
+
+
Click the dark button above, it will redirect you to vercel to deploy with waline template.
+
TIP
+
If you haven't logged in, we recommend you to sign in with GitHub.
+
+
+
+
Input your Vercel project name then click Create.
+
+
+
+
Repo which named you input before will be created and initialized automatically base on waline example template by Vercel.
+
+
After one minute or two, vercel should finish the deployment. Click Go to Dashboard button to redirect to your application dashboard.
+
+
+
+
Click Settings menu on the top, and Environment Variables button on the side to go to environment variables setting page. Then set LEAN_ID, LEAN_KEY and LEAN_MASTER_KEY. The variables' value should be the ones you got in the previous step. APP ID is the value of LEAN_ID, and APP Key to LEAN_KEY, Master Key to LEAN_MASTER_KEY.
+
+
+
+
To let your environment variables setting active, you need redeploy your application. Click Deployments menu on the top and find the latest deployment at the top of list, click Redeploy button in the right dropdown menu.
+
+
+
+
If everything is ok, vercel will redirect to Overview page to start redeployment. Wait a moment the STATUS will change to Ready. Now you can click Visit to visit the site. This link is your server address.
+
+
+
+
Assign Domain (Optional)
+
+
+
Click Settings - Domains to go to domain setting page.
+
+
+
Input domain you want to assign and click Add button.
+
+
+
+
Add a new CNAME record in your domain service server.
Code highlighting, use hanabi by default. The function passes in original content of code block and language of the code block. You should return a string directly.
+
You can pass in a code highlighter of your own, or set to false to disable code highlighting.
+
+
+
texRenderer
+
+
+
Type: WalineTexRenderer | false
+
type WalineTexRenderer = (blockMode: boolean, tex: string) => string
+
Customize TeX rendering, the default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters, the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content, and return a HTML string as render result.
+
You can import TeX renderer to provide preview feature. We recommend you to use Katex or MathJax, or you can set to false to disable parsing TeX.
+
+
+
search
+
+
+
Type: WalineSearchOptions | false
+
interface WalineSearchImageData extends Record<string, unknown> {
+ /**
+ * Image link
+ */
+ src: string
+
+ /**
+ * Image title
+ *
+ * @description Used for alt attribute of image
+ */
+ title?: string
+
+ /**
+ * Image preview link
+ *
+ * @description For better loading performance, we will use this thumbnail first in the list
+ *
+ * @default src
+ */
+ preview?: string
+}
+
+type WalineSearchResult = WalineSearchImageData[]
+
+interface WalineSearchOptions {
+ /**
+ * Search action
+ */
+ search: (word: string) => Promise<WalineSearchResult>
+
+ /**
+ * Default result when opening list
+ *
+ * @default () => search('')
+ */
+ default?: () => Promise<WalineSearchResult>
+
+ /**
+ * Fetch more action
+ *
+ * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling
+ *
+ * @default (word) => search(word)
+ */
+ more?: (word: string, currentCount: number) => Promise<WalineSearchResult>
+}
+
+
+
Details: Customize search features, you can disable search function by setting it to false.
+
+
+
recaptchaV3Key
+
+
+
Type: string
+
+
+
Details:
+
reCAPTCHA V3 is a captcha service provided by Google. You can add reCAPTCHA V3 site key with recaptchaV3Key to enable it.
+
You should also set environment variable RECAPTCHA_V3_SECRET for server.
+
+
+
reaction
+
+
+
Type: boolean | string[]
+
+
+
Default: false
+
+
+
Details:
+
Add emoji interaction function to the article, set it to true to provide the default emoji, you can also customize the emoji image by setting the emoji url array, and supports a maximum of 8 emojis.
]]>
+
+
+ Bundler Related
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html
+
+ 2024-02-03T11:34:35.000Z
+ Bundler function is for appending or modifying bundler options in theme and plugins.
+
All functions should be called in extendsBundlerOptions lifecycle hook.
+
TIP
+
We are omitting that in examples. The actual code should be like this:
+
// import functions you need
+import { addCustomElement } from '@vuepress/helper'
+
+export const yourPlugin = {
+ // ...
+ extendsBundlerOptions: (bundlerOptions, app) => {
+ // add them here
+ addCustomElement(bundlerOptions, app, 'my-custom-element')
+ },
+}
+
]]>
+ Bundler function is for appending or modifying bundler options in theme and plugins.
+
All functions should be called in extendsBundlerOptions lifecycle hook.
+
TIP
+
We are omitting that in examples. The actual code should be like this:
+
// import functions you need
+import { addCustomElement } from '@vuepress/helper'
+
+export const yourPlugin = {
+ // ...
+ extendsBundlerOptions: (bundlerOptions, app) => {
+ // add them here
+ addCustomElement(bundlerOptions, app, 'my-custom-element')
+ },
+}
+
import { configWebpack } from '@vuepress/helper'
+
+configWebpack(bundlerOptions, app, (config, isServer, isBuild) => {
+ // do some customize here
+})
+
+
+
+]]>
+
+
+ Page Related
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html
+
+ 2024-02-03T11:34:35.000Z
+ These functions generate common information for your pages.
+
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:
\n
\n
A NavbarItem object should have a text field and a link field, could have an optional activeMatch field.
\n
A NavbarGroup object should have a text field and a children field. The children field should be a navbar array, too.
\n
A string should be the path to the target page file. It will be converted to a NavbarItem object, using the page title as text, and the page route path as link.
export default {\n theme: defaultTheme({\n navbar: [\n // nested group - max depth is 2\n {\n text: 'Group',\n children: [\n {\n text: 'SubGroup',\n children: ['/group/sub/foo.md', '/group/sub/bar.md'],\n },\n ],\n },\n // control when should the item be active\n {\n text: 'Group 2',\n children: [\n {\n text: 'Always active',\n link: '/',\n // this item will always be active\n activeMatch: '/',\n },\n {\n text: 'Active on /foo/',\n link: '/not-foo/',\n // this item will be active when current route path starts with /foo/\n // regular expression is supported\n activeMatch: '^/foo/',\n },\n ],\n },\n ],\n }),\n}\n
logo
\n
\n
\n
Type: null | string
\n
\n
\n
Details:
\n
Specify the url of logo image.
\n
The logo image will be displayed at the left end of the navbar.
If not specified, defaults to be the same as the site title.
\n
\n
\n
repo
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the repository url of your project.
\n
This will be used as the link of the repository link, which will be displayed as the last item of the navbar.
\n
\n
\n
export default {\n theme: defaultTheme({\n // If you set it in the form of `organization/repository`\n // we will take it as a GitHub repo\n repo: 'vuejs/vuepress',\n // You can also set it to a URL directly\n repo: 'https://gitlab.com/foo/bar',\n }),\n}\n
You can override this global option via sidebar frontmatter in your pages.
\n
Set to false to disable sidebar.
\n
If you set it to 'auto', the sidebar will be automatically generated from the page headers.
\n
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:
\n
\n
A 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.
\n
A string should be the path to the target page file. It will be converted to a SidebarItem object, whose text is the page title, link is the page route path, and children is automatically generated from the page headers.
\n
\n
If you want to set different sidebar for different sub paths, you can set this option to a sidebar object:
\n
\n
The key should be the path prefix.
\n
The value should be a sidebar array or set to 'heading' to automatically generate the sidebar from the page headers for just the corresponding path.
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
\n
\n
Set to 0 to disable all levels of headers.
\n
Set to 1 to include <h2> headers.
\n
Set to 2 to include <h2> and <h3> headers.
\n
...
\n
\n
The max value depends on which levels of headers you have extracted via markdown.headers.level.
\n
The default value of markdown.headers.level is [2, 3], so the default max value of sidebarDepth is 2.
\n
You can override this global option via sidebarDepth frontmatter in your pages.
\n
\n
\n
editLink
\n
\n
\n
Type: boolean
\n
\n
\n
Default: true
\n
\n
\n
Details:
\n
Enable the edit this page link or not.
\n
You can override this global option via editLink frontmatter in your pages.
\n
\n
\n
editLinkPattern
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the pattern of the edit this page link.
\n
This will be used for generating the edit this page link.
\n
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.
\n
\n
\n
Usage:
\n
| Pattern | Description |\n|
\n
\n
\n",
+ "date_modified": "2024-01-31T20:49:08.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Extending",
+ "url": "https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html",
+ "summary": "Extending VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease. Layout Slots Default them...",
+ "content_html": "\n
VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
\n
Layout Slots
\n
Default theme's Layout provides some slots:
\n
\n
navbar
\n
navbar-before
\n
navbar-after
\n
sidebar
\n
sidebar-top
\n
sidebar-bottom
\n
page
\n
page-top
\n
page-bottom
\n
page-content-top
\n
page-content-bottom
\n
\n
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.
\n
Firstly, create a client config file .vuepress/client.ts:
\n
import { defineClientConfig } from 'vuepress/client'\nimport Layout from './layouts/Layout.vue'\n\nexport default defineClientConfig({\n layouts: {\n Layout,\n },\n})\n
Next, create the .vuepress/layouts/Layout.vue, and make use of the slots that provided by the Layout of default theme:
\n
<script setup>\nimport ParentLayout from '@vuepress/theme-default/layouts/Layout.vue'\n</script>\n\n<template>\n <ParentLayout>\n <template #page-bottom>\n <div class=\"my-footer\">This is my custom page footer</div>\n </template>\n </ParentLayout>\n</template>\n\n<style lang=\"css\">\n.my-footer {\n text-align: center;\n}\n</style>\n
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):
\n\n
Components Replacement
\n
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.
\n
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.
\n
Then, if you want to replace the HomeFooter.vue component, just override the alias in your config file .vuepress/config.ts:
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:
\n
import { defaultTheme, type DefaultThemeOptions } from '@vuepress/theme-default'\nimport type { Theme } from 'vuepress/core'\nimport { getDirname, path } from 'vuepress/utils'\n\nconst __dirname = getDirname(import.meta.url)\n\nexport const childTheme = (options: DefaultThemeOptions): Theme => {\n return {\n name: 'vuepress-theme-child',\n extends: defaultTheme(options),\n\n // override layouts in child theme's client config file\n // notice that you would build ts to js before publishing to npm,\n // so this should be the path to the js file\n clientConfigFile: path.resolve(__dirname, './client.js'),\n\n // override component alias\n alias: {\n '@theme/HomeFooter.vue': path.resolve(\n __dirname,\n './components/MyHomeFooter.vue',\n ),\n },\n }\n}\n
",
+ "image": "https://ecosystem.vuejs.press/ecosystem/images/cookbook/extending-a-theme-01.png",
+ "date_modified": "2024-01-30T14:33:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Frontmatter",
+ "url": "https://ecosystem.vuejs.press/ecosystem/themes/default/frontmatter.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/themes/default/frontmatter.html",
+ "summary": "Frontmatter",
+ "content_html": "\n",
+ "date_modified": "2024-01-30T14:33:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Locale Config",
+ "url": "https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html",
+ "summary": "Locale Config 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 tr...",
+ "content_html": "\n
These options configure locale-related texts.
\n
If your site is served in a different language besides English, you should set these options per locale to provide translations.
\n
repoLabel
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the repository label of your project.
\n
This will be used as the text of the repository link, which will be displayed as the last item of the navbar.
\n
If you don't set this option explicitly, it will be automatically inferred from the repo option.
\n
\n
\n
selectLanguageText
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the text of the select language menu.
\n
The select language menu will appear next to the repository button in the navbar when you set multiple locales in your site config.
\n
\n
\n
selectLanguageAriaLabel
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the aria-label attribute of the select language menu.
\n
This is mainly for a11y purpose.
\n
\n
\n
selectLanguageName
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
Specify the name of the language of a locale.
\n
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.
\n",
+ "date_modified": "2024-03-25T11:54:39.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Markdown",
+ "url": "https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html",
+ "summary": "Markdown",
+ "content_html": "\n",
+ "date_modified": "2024-01-30T09:08:43.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Plugins Config",
+ "url": "https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html",
+ "summary": "Plugins Config 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...",
+ "content_html": "\n
You can configure the plugins that used by default theme with themePlugins.
\n
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.
Page filter, determine whether the plugin should generate excerpt for it.
\n
TIP
\n
You should use this to skip pages that you don't need to generate excerpt for. E.g.: If users set excerpt or description in frontmatter, you may want to use them directly.
This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.
\n
\n
\n
metaScope
\n
\n
\n
Type: string
\n
\n
\n
Default: \"_blog\"
\n
\n
\n
Details:
\n
Key used when injecting info to route meta.
\n
TIP
\n
Setting to an empty key will inject to route meta directly instead of a field.
\n
\n
\n
\n
hotReload
\n
\n
\n
Type: boolean
\n
\n
\n
Default: Whether using --debug flag
\n
\n
\n
Details:
\n
Whether enable hotReload in devServer.
\n
To theme developers
\n
It's disabled by default because it does have performance impact in sites with a lot of categories and types. And it can slow down hotReload speed when editing Markdown.
\n
If users are adding or organizing your categories or tags, you may tell them to enable this, for the rest it's better to keep it disabled.
\n
Also, you can try to detect number of pages in users project and decide whether to enable it.
\n
\n
\n
\n
Blog Category Config
\n
Blog category config should be an array, while each item is controlling a \"category\" rule.
\n
interface BlogCategoryOptions {\n /**\n * Unique category name\n */\n key: string\n\n /**\n * Function getting category from page\n */\n getter: (page: Page) => string[]\n\n /**\n * A custom function to sort the pages\n */\n sorter?: (pageA: Page, pageB: Page) => number\n\n /**\n * Path pattern of page to be registered\n *\n * @description `:key` will be replaced by the \"slugify\" result of the original key\n *\n * @default `/:key/`\n */\n path?: string\n\n /**\n * Page layout name\n *\n * @default 'Layout'\n */\n layout?: string\n\n /**\n * Frontmatter\n */\n frontmatter?: (localePath: string) => Record<string, string>\n\n /**\n * Item page path pattern or custom function to be registered\n *\n * @description When filling in a string, `:key` and `:name` will be replaced by the \"slugify\" result of the original key and name\n *\n * @default `/:key/:name/`\n */\n itemPath?: string | ((name: string) => string)\n\n /**\n * Item page layout name\n *\n * @default 'Layout'\n */\n itemLayout?: string\n\n /**\n * Items Frontmatter\n */\n itemFrontmatter?: (name: string, localePath: string) => Record<string, string>\n}\n
Blog Type Config
\n
Blog type config should be an array, while each item is controlling a \"type\" rule.
\n
interface BlogTypeOptions {\n /**\n * Unique type name\n */\n key: string\n\n /**\n * A filter function to determine whether a page should be the type\n */\n filter: (page: Page) => boolean\n\n /**\n * A custom function to sort the pages\n */\n sorter?: (pageA: Page, pageB: Page) => number\n\n /**\n * Page path to be registered\n *\n * @default '/:key/'\n */\n path?: string\n\n /**\n * Layout name\n *\n * @default 'Layout'\n */\n layout?: string\n\n /**\n * Frontmatter\n */\n frontmatter?: (localePath: string) => Record<string, string>\n}\n
Composition API
\n
You can import the following API from @vuepress/plugin-blog/client.
If no key is passed, the plugin will try to use the key in current path.
\n
\n
\n
Returning values are:
\n
interface Article<T extends Record<string, unknown> = Record<string, unknown>> {\n /** Article path */\n path: string\n /** Article info */\n info: T\n}\n\ninterface BlogCategoryData<\n T extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Category path */\n path: string\n\n /**\n * Only available when current route matches an item path\n */\n currentItems?: Article<T>[]\n\n /** Category map */\n map: {\n /** Unique key under current category */\n [key: string]: {\n /** Category path of the key */\n path: string\n /** Category items of the key */\n items: Article<T>[]\n }\n }\n}\n\ninterface BlogTypeData<\n T extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Type path */\n path: string\n\n /** Items under current type */\n items: Article<T>[]\n}\n
",
+ "date_modified": "2024-02-05T09:34:12.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Guide",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html",
+ "summary": "With @vuepress/plugin-blog, you can easily bring blog feature into your theme. Collecting Articles The plugin filters all pages using filter option to drop pages you don't want....",
+ "content_html": "
With @vuepress/plugin-blog, you can easily bring blog feature into your theme.
\n
Collecting Articles
\n
The plugin filters all pages using filter option to drop pages you don't want.
\n
By default, all pages generating from Markdown files but not homepage are considered as articles.
\n
\n
You can fully customize pages to collect through option filter, which accepts a function (page: Page) => boolean.
\n
Gathering Info
\n
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
\n
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
\nDemo\n
import { blogPlugin } from '@vuepress/plugin-blog'\n\nexport default {\n name: 'vuepress-theme-xxx',\n plugins: [\n blogPlugin({\n filter: ({ filePathRelative, frontmatter }) => {\n // drop those pages which is NOT generated from file\n if (!filePathRelative) return false\n\n // drop those pages in `archives` directory\n if (filePathRelative.startsWith('archives/')) return false\n\n // drop those pages which do not use default layout\n if (frontmatter.home || frontmatter.layout) return false\n\n return true\n },\n\n getInfo: ({ frontmatter, git = {}, data = {} }) => {\n // getting page info\n const info: Record<string, any> = {\n author: frontmatter.author || '',\n categories: frontmatter.categories || [],\n date: frontmatter.date || git.createdTime || null,\n tags: frontmatter.tags || [],\n excerpt: data.excerpt || '',\n }\n\n return info\n },\n }),\n // other plugins ...\n ],\n}\n
\n
Customizing Categories and Types
\n
Basically, you would want 2 types of collection in your blog:
\n
\n
\n
Category:
\n
\"Category\" means grouping articles with their labels.
\n
For example, each article may have their \"categories\" and \"tags\".
\n
\n
\n
Type:
\n
\"Type\" means identifying articles with conditions.
\n
For example, you may want to describe some of your articles as diary.
\n
\n
\n
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
\n
Let's start with 2 examples here.
\n
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
\n
interface BlogFrontmatterOptions {\n /** Current type of the page */\n type: 'category' | 'type'\n /** Unique key under current category or tag */\n key: string\n /**\n * Current category name\n *\n * @description Only available in category item page\n */\n name?: string\n}\n
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
\n
Also, you can pass key you want as argument, then you will get information bind to that key.
\n
So with node side settings above, you can get information about \"tag\" and \"star\" in client side:
Then /zh/star/ and /star/ will both be available, and only articles under the correct locale will appear.
\n
Generating Excerpt
\n
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
\n
Excerpt introduction
\n
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
\n
\n
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
\n
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
\n
\n
\n
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default <!-- more -->, and you can customize it by setting excerptSeparator option.
\n
If it cannot find a valid separator, it will parse content from the beginning of markdown file, and stop till its length reaches a preset value. The value is default 300, and you can customize it by setting excerptLength option.
\n
To choose which page should generate excerpt, you can use excerptFilter option.
\n
Example
\n
Normally you may want to use frontmatter.description if users set them, so you can let filter function return false if frontmatter.description is not empty.
\n
\n",
+ "date_modified": "2024-02-19T18:01:19.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "comment",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/",
+ "summary": "comment",
+ "content_html": "\n",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Guide",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/guide.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/guide.html",
+ "summary": "Guide Setting Options You can both set options with plugin options on Node side and set options in client config file on Browser side. With Plugin Options With Client Config Fil...",
+ "content_html": "\n
Setting Options
\n
You can both set options with plugin options on Node side and set options in client config file on Browser side.
But here are some limitations you should remember:
\n
\n
\n
provider, locales and other resource related option must be set in plugin options.
\n
To ensure tree-shaking works, we must optimize entries at node so that bundler can understand which resource should be included in the final bundle.
\n
These options will be marked with
\n
\n
\n
Options which can not be serialized to JSON must be set in client config.
\n
Options that receives function values can not be set in plugin options, as plugins are running under Node.js environment, so we can not pass these values and their contexts to browser.
\n
These options will be marked with
\n
\n
\n
Adding Comment
\n
This plugin globally registers a component <CommentService />.
\n
\n
If you are a user, you should use alias and layout slots to insert the component. We recommended you to insert the comment component (<CommentService />) after the <PageNav /> component, and the current page is a demo with default theme.
\n
If you are a theme developer, you should insert this component in the layout of your theme.
\n
\n
By default, <CommentService /> component is enabled globally, and you can use comment option in both plugin options and page frontmatter to control it.
\n
\n
You can disable it locally by setting comment: false in page frontmatter.
\n
To keep it globally disabled, please set comment to false in the plugin options. Then you can set comment: true in page frontmatter to enable it locally.
\n
\n
You can set commentID option in page frontmatter to customize comment ID, which is used to identify comment storage item to use for a page. By default it will be the path of the page, which means if you are deploying the site to multiple places, page with same content across sites will share the same comment data.
A custom filter function, used to filter feed items.
\n
sorter
\n
\n
\n
Type: (pageA: Page, pageB: Page)=> number
\n
\n
\n
Default:
\n
// dateSorter is from @vuepress/helper\n;(pageA: Page, pageB: Page): number =>\n dateSorter(\n pageA.data.git?.createdTime\n ? new Date(pageA.data.git?.createdTime)\n : pageA.frontmatter.date,\n pageB.data.git?.createdTime\n ? new Date(pageB.data.git?.createdTime)\n : pageB.frontmatter.date,\n )\n
\n
\n
Custom sorter function for feed items.
\n
The default sorting behavior is by file adding time coming from git (needs @vuepress/plugin-git).
\n
TIP
\n
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.
The plugin has a built-in getter, only set this if you want full control of feed generation.
\n
\n
locales
\n
\n
Type: Record<string, BaseFeedOptions>
\n
\n
You can use it to specific options for each locale.
\n
Any options above are supported except hostname.
\n",
+ "date_modified": "2024-02-02T06:14:30.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Frontmatter Config",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html",
+ "summary": "Frontmatter Config You can control each feed item generation by setting page frontmatter. Additions and Removals By default, all articles are added to the feed stream. Set feed:...",
+ "content_html": "\n
You can control each feed item generation by setting page frontmatter.
\n
Additions and Removals
\n
By default, all articles are added to the feed stream. Set feed: false in frontmatter to remove a page from feed.
\n
Frontmatter Information
\n
title
\n
\n
Type: string
\n
\n
Automatically generated by VuePress, defaults to the h1 content of the page
\n
description
\n
\n
Type: string
\n
\n
Description of the page
\n
date
\n
\n
Type: Date
\n
\n
Date when the page was published
\n
article
\n
\n
Type: boolean
\n
\n
Whether the page is an article
\n
\n
If this is set to false, the page will not be included in the final feed.
\n
\n
copyright
\n
\n
Type: string
\n
\n
Page copyright information
\n
cover / image / banner
\n
\n
Type: string
\n
\n
Image used as page cover , should be full link or absolute link.
interface FeedCategory {\n /**\n * Category Name\n */\n name: string\n\n /**\n * A string that identifies a categorization taxonomy\n *\n * @description rss format only\n */\n domain?: string\n\n /**\n * the categorization scheme via a URI\n *\n * @description atom format only\n */\n scheme?: string\n}\n
\n
getter.enclosure
\n
\n
Type: (page: Page) => FeedEnclosure | undefined
\n
\n
Item enclosure getter.
\nFeedEnclosure format\n
interface FeedEnclosure {\n /**\n * Enclosure link\n */\n url: string\n\n /**\n * what its type is\n *\n * @description should be a standard MIME Type, rss format only\n */\n Type: string\n\n /**\n * Size in bytes\n *\n * @description rss format only\n */\n length?: number\n}\n
\n
getter.publishDate
\n
\n
Type: (page: Page) => Date | undefined
\n
\n
Item release date getter
\n
getter.lastUpdateDate
\n
\n
Type: (page: Page) => Date
\n
\n
Item last update date getter
\n
getter.image
\n
\n
Type: (page: Page) => string
\n
\n
Item Image Getter
\n
Ensure it's returning a full URL
\n
\n
getter.contributor
\n
\n
Type: (page: Page) => FeedContributor[]
\n
\n
Item Contributor Getter
\n
The getter should return an empty array when contributor information is missing.
\n",
+ "date_modified": "2024-02-01T04:46:03.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Guide",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/feed/guide.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/feed/guide.html",
+ "summary": "Guide Usage The plugin can generate feed files in the following three formats for you: Atom 1.0 JSON 1.1 RSS 2.0 Please set atom, json or rss to true in the plugin options accor...",
+ "content_html": "\n
Usage
\n
The plugin can generate feed files in the following three formats for you:
\n
\n
Atom 1.0
\n
JSON 1.1
\n
RSS 2.0
\n
\n
Please set atom, json or rss to true in the plugin options according to the formats you want to generate.
\n
To correctly generate feed links, you need to set hostname in the plugin options,
\n
Readable Preview
\n
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!
\n
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}.
\n
Channel settings
\n
You can customize the feed channel information by setting the channel option.
\n
We recommend the following settings:
\n
\n
Convert the date of creating the feed to ISOString and write it into channel.pubDate
\n
The update period of the content set in channel.ttl (unit: minutes)
\n
Set copyright information via channel.copyright
\n
Set the channel author via channel.author.
\n
\n
For detailed options and their default values, see Channel Config
\n
Feed Generation
\n
By default, all articles are added to the feed stream.
\n
You can set feed and other options in page frontmatter to control contents of feed item. See Frontmatter Config for how they are converted.
\n
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.
\n
I18n Config
\n
The plugin generates separate feeds for each language.
\n
You can provide different settings for different languages via locales in the plugin options.
Details:\nControl logic when new content is found.
\n
\n
\n
\"disabled\": Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
\n
\n
\n
\"available\": Only display update popup when the new service worker is available
\n
\n
\n
\"hint\": Display a hint to let user choose to refresh immediately
\n
This is helpful when you want users to see new docs immediately.
\n
TIP
\n
If users choose to refresh, the current service worker will be unregister, and request will start coming to web. Later the new service worker will start installing and control current page after installed.
\n
\n
\n
\n
\"force\": unregister current service worker immediately then refresh to get new content
\n
DANGER
\n
Although this ensures users are viewing the latest content, it may affect viewing experiences.
\n
\n
\n
\n
TIP
\n
How docs are updated is controlled by a previous version, so the current option only effect next update from this version.
\n
\n
\n
\n
apple
\n
Special settings for better supporting Safari, ignoring these options are safe.
\n
apple.icon
\n
\n
Type: string
\n
Details: Icon link used by Safari.
\n
\n
apple.statusBarColor
\n
\n
Type: \"black\" | \"white\"
\n
Default: \"black\"
\n
Details: Status bar color for Safari
\n
\n
apple.maskIcon
\n
\n
Type: string
\n
Details: Safari mask icon
\n
\n
msTile
\n
Special settings for Microsoft tiles, ignoring these options are safe.
\n
msTile.image
\n
\n
Type: string
\n
Details: Tile image
\n
\n
msTile.color
\n
\n
Type: string
\n
Default value: themeColor
\n
Details: Tile color
\n
\n
foundComponent
\n
\n
Type: string
\n
Default: \"PwaFoundPopup\"
\n
Details: Path of custom hint popup component.
\n
\n
readyComponent
\n
\n
Type: string
\n
Default: \"PwaReadyPopup\"
\n
Details: Path of custom update popup component.
\n
\n
appendBase
\n
\n
Type: boolean
\n
Default: false
\n
Details: Whether append base to all absolute links in options.
To better control what the Service Worker can pre-cache, the plugin provides related options for cache control.
\n
Default cache
\n
By default, the plugin will pre-cache all jscss files, and only homepage and 404 html are cached. The plugin will also cache font files (woff, woff2, eot, ttf, otf) and SVG icons.
\n
Image Cache
\n
If your site has only a few important images, and want them displayed in offline mode, you can cache site images by setting cacheImage: true .
\n
We recognize images by file extension. Any files ending with .png, .jpg, .jpeg, .gif, .bmp, .webp will be regarded as images.
\n
HTML Cache
\n
If you have small sites, and would like to make document fully offline available, you can set cacheHTML to true to cache all HTML files.
\n
Why only home and 404 page been cached by default?
To prevent large files from being included in the pre-cache list, any files > 2 MB or images > 1 MB will be omitted. You can customize these limits with maxSize and maxImageSize options (in KB unit).
\n
Update Control
\n
We provide the update option to control how users receive updates.
\n
The default value of the update option is \"available\", which means that when new content available, the new SW will be installed and its resources will be fetched silently in the background. A pop-up window appears once the new SW is ready, and users can choose whether to refresh immediately to view new content. This means users are reading old content before a new SW is ready.
\n
If your project is still in building stage, and you want to alert the user that he may be reading outdated content, you can set this to \"hint\". This allows users to be notified that new content has been published within seconds after visiting docs. But the negative effect of this is that if the user chooses to update before the new SW is ready, he will need to get all the resources of the page from the internet before the new SW installs and controls the page.
\n
If your docs are stable, or you're hosting a blog and don't care much about users receiving the latest version right away, you can set this to \"disabled\", which means that the new SW will be installed completely silently in the background and start waiting, when all pages controlled by old SW are all closed, the new SW will start to take control and provide users with new content during next visit. This setting can prevent users from being disturbed during the visit.
\n
To speed up user access under weak or no network conditions through SW, but also want users to always access new content, you can set this option to \"force\". This means any old SW will be removed as soon as a new SW is detected, and all pages are refreshed to ensure the user is browsing the latest content. The biggest disadvantage is that all users will experience unexpected sudden refresh within seconds after reentering an updated site.
\n
Popups
\n
When new content is detected (new SW detected), a update found popup appears; and when the new content is ready, an update ready popup appears.
\n
If you are not satisfied with the default popup content, you can use your own component. Import PwaFoundPopup or PwaReadyPopup from @vuepress/plugin-pwa/client and use its slot to customize the popup content, then pass the component path to foundComponent or readyComponent option:
\n
<script setup lang=\"ts\">\nimport { PwaFoundPopup } from '@vuepress/plugin-pwa/client'\n</script>\n<template>\n <PwaFoundPopup v-slot=\"{ found, refresh }\">\n <div v-if=\"found\">\n New content is found.\n <button @click=\"refresh\">Refresh</button>\n </div>\n </PwaFoundPopup>\n</template>\n
<script setup lang=\"ts\">\nimport { PwaReadyPopup } from '@vuepress/plugin-pwa/client'\n</script>\n<template>\n <PwaReadyPopup v-slot=\"{ isReady, reload }\">\n <div v-if=\"isReady\">\n New content is ready.\n <button @click=\"reload\">Apply</button>\n </div>\n </PwaReadyPopup>\n</template>\n
Other Options
\n
The plugin also provides other PWA-related options, such as Microsoft tile icon and color settings, Apple icon and so on. If you are an advanced user, you can also set generateSwConfig to configure workbox-build. Check Plugin options for more details.
The Service Worker will get and cache all the files registered in it during the registration process.
\n
\n
\n
After the registration complete, the Service Worker is activated, and starts to proxy and control all your requests.
\n
\n
\n
Whenever you want to initiate an access request through the browser, the Service Worker will check whether it exists in its own cache list, if it exists, it will directly return the cached result, otherwise it will call its own fetch method to get it. You can use a custom fetch method to fully control the result of the request for resources in the web page, such as providing a fallback web page when offline.
\n
\n
\n
Every time the user reopens the site, the Service Worker will request to the link when it was registered. If a new version of Service Worker is detected, it will update itself and start caching the list of resources registered in the new Service Worker . After the content update is successfully obtained, the Service Worker will trigger the update event. The user can be notified through this event, for example, a pop-up window will be displayed in the lower right corner, prompting the user that new content is available and allowing the user to trigger an update.
The manifest file uses the JSON format and is responsible for declaring various information of the PWA, such as name, description, icon, and shortcut actions.
\n
In order for your site to be registered as a PWA, you need to meet the basic specifications of the manifest to make the browser consider the site as an installable PWA and allow users to install it.
To let the site be registered as a PWA, the site needs to successfully register a valid service worker by itself, and declare a valid manifest file with its link in meta tag.
\n
The manifest file should contain at least name (or short_name) iconsstart_url.
\n
On safari, the maximum cache size of the service worker is 50 MB. ↩︎↩︎
SPA: Single Page Application, most of them only have the homepage, and use history mode to handle routing instead of actually navigating between pages. ↩︎
You can use this options to edit JSON-LD properties.
\n
\n
\n
customHead
\n
\n
\n
Type:
\n
function customHead(\n /** Head tag config */\n head: HeadConfig[],\n /** Page Object */\n page: Page,\n /** VuePress App */\n app: App,\n): void\n
\n
\n
Required: No
\n
\n
\n
Details:
\n
You can use this options to edit tags injected to <head>.
\n
\n
\n",
+ "date_modified": "2024-02-01T04:46:03.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Guide",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html",
+ "summary": "Guide This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site. Out of Box The plugin works out of the box. Without...",
+ "content_html": "\n
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.
\n
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.
\n
The following are the <meta> tags and their values that will be injected into <head> by default:
\n
Default OGP Generation
\n
The following are the <meta> tags and their value injected into <head> by default to satisfy OGP:
\n
| Meta Name | Value |\n| :
\n",
+ "date_modified": "2024-03-10T14:51:27.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "sitemap",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/",
+ "summary": "sitemap",
+ "content_html": "\n",
+ "date_modified": "2024-02-01T04:46:03.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Config",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/config.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/config.html",
+ "summary": "Config hostname Type: string Required: Yes Details: The domain name where the current site is deployed, the plugin needs this option to work. extraUrls Type: string[] Details: E...",
+ "content_html": "\n
hostname
\n
\n
\n
Type: string
\n
\n
\n
Required: Yes
\n
\n
\n
Details:
\n
The domain name where the current site is deployed, the plugin needs this option to work.
\n
\n
\n
extraUrls
\n
\n
\n
Type: string[]
\n
\n
\n
Details:
\n
Extra link to be included.
\n
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.
\n
\n
\n
Example: ['/about.html', '/api/']
\n
\n
\n
excludePaths
\n
\n
\n
Type: string[]
\n
\n
\n
Default: ['/404.html']
\n
\n
\n
Details:
\n
Urls excluding from sitemap, starting with absolute path.
\n
By default, all the urls generated by VuePress (excluding 404 page) will be added into sitemap.
\n
\n
\n
devServer
\n
\n
\n
Type: boolean
\n
\n
\n
Default: false
\n
\n
\n
Details:
\n
Whether enabled in devServer.
\n
\n
\n
TIP
\n
For performance reasons, we do not provide hot reload. Reboot your devServer to sync your changes.
\n
\n
devHostname
\n
\n
\n
Type: string
\n
\n
\n
Default: \"http://localhost:${port}\"
\n
\n
\n
Details:
\n
Hostname to use in devServer
\n
\n
\n
sitemapFilename
\n
\n
\n
Type: string
\n
\n
\n
Default value: \"sitemap.xml\"
\n
\n
\n
Details:
\n
The output filename, relative to output directory.
Page default update frequency. This will override changefreq in Plugin Options.
\n
\n
\n
sitemap.priority
\n
\n
\n
Type: number
\n
\n
\n
Default: 0.5
\n
\n
\n
Details:
\n
Page priority, range from 0 to 1.
\n
\n
\n",
+ "date_modified": "2024-02-01T04:46:03.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Guide",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html",
+ "summary": "Guide 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. I...",
+ "content_html": "\n
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.
\n
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.
\n
Control Sitemap Link
\n
By default, all site links except 404 page will be added to the Sitemap.
\n
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.
\n
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.
\n
Output Location
\n
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.
\n
Change Frequency
\n
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.
\n
The legal frequencies are:
\n
\n
\"always\"
\n
\"hourly\"
\n
\"daily\"
\n
\"weekly\"
\n
\"monthly\"
\n
\"yearly\"
\n
\"never\"
\n
\n
Priority
\n
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.
\n
Modify Time
\n
You can use option modifyTimeGetter to return a time in ISO string format, which is generated by the Git plugin by default.
\n
The following is an example based on the last modification time of a file.
\n
// Based on file last modified time\n({\n modifyTimeGetter: (page, app) =>\n fs.statSync(app.dir.source(page.filePathRelative)).mtime.toISOString();\n})\n
Sitemap Intro
\n
Sitemaps provide SEO (Search Engine Optimization):
\n
\n
Provide search engine spiders with links of the entire site;
\n
Provide some links for search engine spiders to dynamic pages or pages that are difficult to reach by other methods;
\n
If a visitor attempts to access a URL that does not exist within the site's domain, the visitor will be directed to a \"file not found\" error page, and the sitemap can be used as a navigation page.
\n
\n
A sitemap enhances SEO by making all pages findable.
\n
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.
\n
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.
\n
Together with robots.txt
\n
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)
\n
User-agent: *\n\nAllow: /\n
\n",
+ "date_modified": "2024-01-31T17:59:51.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "@vuepress/helper",
+ "url": "https://ecosystem.vuejs.press/ecosystem/tools/helper/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/tools/helper/",
+ "summary": "@vuepress/helper",
+ "content_html": "\n",
+ "date_modified": "2024-02-03T11:34:35.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Client Related",
+ "url": "https://ecosystem.vuejs.press/ecosystem/tools/helper/client.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/tools/helper/client.html",
+ "summary": "Client Related Composables APIs hasGlobalComponent Check whether a component is registered globally. TIP Local import of the component does not affect the result. When calling o...",
+ "content_html": "\n
Composables APIs
\n
hasGlobalComponent
\n
Check whether a component is registered globally.
\n
TIP
\n\n
Local import of the component does not affect the result.
\n
When calling outside setup scope, you need to pass the app instance as the second parameter.
const localesCOnfig = {\n '/': 'Title',\n '/zh/': '标题',\n}\n\nconst locale = useLocaleConfig(localesConfig)\n\n// under `/page`\nlocale.value // 'Title'\n\n// under `/zh/page`\nlocale.value // '标题'\n
\n",
+ "date_modified": "2024-02-03T11:34:35.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Shared Methods",
+ "url": "https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html",
+ "summary": "Shared Methods The following functions are available on both Node.js and Client. Data Related Encode/decode and zip/unzip data. This is useful in markdown plugins when you want ...",
+ "content_html": "\n
The following functions are available on both Node.js and Client.
\n
Data Related
\n
Encode/decode and zip/unzip data.
\n
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
\n
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
\n
So we provide encodeData and decodeData to zip and encode content.
getDate(x): Convert input x to a date. It can support Date, timestamp, and date string. The support degree of date string depends on the Date.parse support degree of the environment. Return null when it cannot be converted to a date.
\nExample\n
getDate('2021-01-01') // a Date object represents 2021-01-01\ngetDate(1609459200000) // a Date object represents 2021-01-01\ngetDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01\ngetDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)\ngetDate('invalid date') // null\ngetDate(undefined) // null\ngetDate(-32) // null\n
\n
\n
\n
dateSorter: Sort the values that can be converted to dates from new to old, and the values that cannot be converted to dates will be at the end.
isLinkWithProtocol(x): Check if x is a valid URL with protocol.
\n
isLinkExternal(x): Check if x is a valid external URL.
\n
isLinkAbsolute(x): Check if x is a valid absolute URL.
\n
ensureEndingSlash(x): Ensure x ends with a slash.
\n
ensureLeadingSlash(x): Ensure x starts with a slash.
\n
removeEndingSlash(x): Ensure x does not end with a slash.
\n
removeLeadingSlash(x): Ensure x does not start with a slash.
\n
\n",
+ "date_modified": "2024-02-03T11:34:35.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Artalk",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/",
+ "summary": "Artalk Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page. Come to your blog, or anywhere, place the Artal...",
+ "content_html": "\n
Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page.
\n
Come to your blog, or anywhere, place the Artalk comment box, so that the page has rich social functions.
The plugin retains the el option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the pageTitle, pageKey and site options for you according to the VuePress information.
\n
\n
Darkmode
\n
To let Artalk apply the correct theme, you need to pass a boolean value to <CommentService /> through darkmode prop, representing whether the dark mode is currently enabled.
\n",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Artalk Options",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/config.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/config.html",
+ "summary": "Artalk Options Config See Artalk Configuration for details. The el pageTitle, pageKey and site options are reserved for plugins, they will be inferred from VuePress config. Two ...",
+ "content_html": "\n
The elpageTitle, pageKey and site options are reserved for plugins, they will be inferred from VuePress config.
\n
\n
\n
Two function options imgUploader and avatarURLBuilder can only be set on client side.
\n
\n
\n
Plugin Config
\n
You can directly configure serializable options in the plugin options:
\n
import { defineUserConfig } from 'vuepress'\nimport { commentPlugin } from 'vuepress-plugin-comment2'\n\nexport default defineUserConfig({\n plugins: [\n commentPlugin({\n provider: 'Artalk',\n // other options\n // ...\n }),\n ],\n})\n
Client Config
\n
You can use the defineArtalkConfig function to customize Artalk:
\n
import { defineClientConfig } from 'vuepress/client'\nimport { defineArtalkConfig } from 'vuepress-plugin-comment2/client'\n\ndefineArtalkConfig({\n // Artalk config\n})\n\nexport default defineClientConfig({\n // ...\n})\n
",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Giscus",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/",
+ "summary": "Giscus Giscus is a commenting system based on GitHub Discussion that is easy to start. Preparation Create a public repository and open discussion panel as a place to store comme...",
+ "content_html": "\n
Giscus is a commenting system based on GitHub Discussion that is easy to start.
\n\n
Preparation
\n\n
\n
Create a public repository and open discussion panel as a place to store comments.
\n
\n
\n
Install the Giscus App to have permission to access the corresponding repository.
\n
\n
\n
After completing the above steps, please go to the Giscus page to get your settings.
\n
You just need to fill in the repository and Discussion categories, then scroll to the \"Enable giscus\" section at the bottom of the page and obtain four attributes: data-repo, data-repo-id, data-category and data-category-id.
\n
\n\n
Config
\n
Please set provider: \"Giscus\" and pass data-repo, data-repo-id, data-category and data-category-id as plugin options as repo, repoId, categorycategoryId.
By default, the theme of Giscus is light or dark (based on darkmode status).
\n
Darkmode
\n
To let Giscus apply the correct theme, you need to pass a boolean value to <CommentService /> via darkmode property, indicating whether darkmode is currently enabled.
\n
\n
If you want to customize theme in lightmode and darkmode, you can set lightTheme and darkTheme option with a built-in theme keyword or a custom CSS link starting with https://.
\n",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Giscus Options",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/config.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/config.html",
+ "summary": "Giscus Options Config repo Type: string Details: The name of repository to store discussions. repoId Type: string Details: The ID of repository to store discussions. Generate th...",
+ "content_html": "\n
Config
\n
repo
\n
\n
Type: string
\n
Details: The name of repository to store discussions.
\n
\n
repoId
\n
\n
Type: string
\n
Details:\nThe ID of repository to store discussions. Generate through Giscus Page
\n
\n
category
\n
\n
Type: string
\n
Details:\nThe name of the discussion category.
\n
\n
categoryId
\n
\n
Type: string
\n
Details:\nThe ID of the discussion category. Generate through Giscus Page
\n
\n
mapping
\n
\n
Type: string
\n
Default: \"pathname\"
\n
Details:\nPage - Discussion mapping. For details see Giscus Page
Create a free MongoDB database, the recommended region is AWS / N. Virginia (us-east-1)
\n
\n
\n
Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses (Why?), create Database user, and record the database connection string, please change the <password> in the connection string to the database password
Click the button below to deploy Twikoo to Vercel in one click
\n
\n
\n
\n
Go to Settings - Environment Variables, add the environment variable MONGODB_URI, the value is the database connection string in step 3
\n
\n
\n
Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt \"Twikoo cloud function is running normally\"
\n
\n
\n
Vercel Domains (with https:// prefix, e.g. https://xxx.vercel.app) is your environment ID
\n
\n\n
Configuration
\n
Please set provider: \"Twikoo\" and set envId in the plugin options.
You can directly configure serializable options in the plugin options:
\n
import { defineUserConfig } from 'vuepress'\nimport { commentPlugin } from 'vuepress-plugin-comment2'\n\nexport default defineUserConfig({\n plugins: [\n commentPlugin({\n provider: 'Twikoo',\n // other options\n // ...\n }),\n ],\n})\n
Client Config
\n
You can use the defineTwikooConfig function to customize Twikoo:
\n
import { defineClientConfig } from 'vuepress/client'\nimport { defineTwikooConfig } from 'vuepress-plugin-comment2/client'\n\ndefineTwikooConfig({\n // Twikoo config\n})\n\nexport default defineClientConfig({\n // ...\n})\n
",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Waline",
+ "url": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/",
+ "id": "https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/",
+ "summary": "Waline A safe comment system with backend. Install LeanCloud Settings (Database) sign in or sign up LeanCloud and enter Console. Click Create app button to create a new app and ...",
+ "content_html": "\n
Click Create app button to create a new app and enter a name you like:
\n\n
\n
\n
Enter the app, then select Settings > App Keys at the left bottom corner. You will see APP ID, APP Key and Master Key of your app. We will use them later
\n\n
\n\n
Deploy to Vercel (Server)
\n
\n\n
\n
Click the dark button above, it will redirect you to vercel to deploy with waline template.
\n
TIP
\n
If you haven't logged in, we recommend you to sign in with GitHub.
\n
\n
\n
\n
Input your Vercel project name then click Create.
\n\n
\n
\n
Repo which named you input before will be created and initialized automatically base on waline example template by Vercel.
\n\n
After one minute or two, vercel should finish the deployment. Click Go to Dashboard button to redirect to your application dashboard.
\n\n
\n
\n
Click Settings menu on the top, and Environment Variables button on the side to go to environment variables setting page. Then set LEAN_ID, LEAN_KEY and LEAN_MASTER_KEY. The variables' value should be the ones you got in the previous step. APP ID is the value of LEAN_ID, and APP Key to LEAN_KEY, Master Key to LEAN_MASTER_KEY.
\n\n
\n
\n
To let your environment variables setting active, you need redeploy your application. Click Deployments menu on the top and find the latest deployment at the top of list, click Redeploy button in the right dropdown menu.
\n\n
\n
\n
If everything is ok, vercel will redirect to Overview page to start redeployment. Wait a moment the STATUS will change to Ready. Now you can click Visit to visit the site. This link is your server address.
\n\n
\n\n
Assign Domain (Optional)
\n\n
\n
Click Settings - Domains to go to domain setting page.
\n
\n
\n
Input domain you want to assign and click Add button.
\n\n
\n
\n
Add a new CNAME record in your domain service server.
type WalineEmojiPresets = `http://${string}` | `https://${string}`\n\ninterface WalineEmojiInfo {\n /**\n * Emoji name show on tab\n */\n name: string\n /**\n * Current folder link\n */\n folder?: string\n /**\n * Common prefix of Emoji icons\n */\n prefix?: string\n /**\n * Type of Emoji icons, will be regarded as file extension\n */\n type?: string\n /**\n * Emoji icon show on tab\n */\n icon: string\n /**\n * Emoji image list\n */\n items: string[]\n}\n
Code highlighting, use hanabi by default. The function passes in original content of code block and language of the code block. You should return a string directly.
\n
You can pass in a code highlighter of your own, or set to false to disable code highlighting.
\n
\n
\n
texRenderer
\n
\n
\n
Type: WalineTexRenderer | false
\n
type WalineTexRenderer = (blockMode: boolean, tex: string) => string\n
Customize TeX rendering, the default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters, the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content, and return a HTML string as render result.
\n
You can import TeX renderer to provide preview feature. We recommend you to use Katex or MathJax, or you can set to false to disable parsing TeX.
\n
\n
\n
search
\n
\n
\n
Type: WalineSearchOptions | false
\n
interface WalineSearchImageData extends Record<string, unknown> {\n /**\n * Image link\n */\n src: string\n\n /**\n * Image title\n *\n * @description Used for alt attribute of image\n */\n title?: string\n\n /**\n * Image preview link\n *\n * @description For better loading performance, we will use this thumbnail first in the list\n *\n * @default src\n */\n preview?: string\n}\n\ntype WalineSearchResult = WalineSearchImageData[]\n\ninterface WalineSearchOptions {\n /**\n * Search action\n */\n search: (word: string) => Promise<WalineSearchResult>\n\n /**\n * Default result when opening list\n *\n * @default () => search('')\n */\n default?: () => Promise<WalineSearchResult>\n\n /**\n * Fetch more action\n *\n * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling\n *\n * @default (word) => search(word)\n */\n more?: (word: string, currentCount: number) => Promise<WalineSearchResult>\n}\n
\n
\n
Details: Customize search features, you can disable search function by setting it to false.
\n
\n
\n
recaptchaV3Key
\n
\n
\n
Type: string
\n
\n
\n
Details:
\n
reCAPTCHA V3 is a captcha service provided by Google. You can add reCAPTCHA V3 site key with recaptchaV3Key to enable it.
\n
You should also set environment variable RECAPTCHA_V3_SECRET for server.
\n
\n
\n
reaction
\n
\n
\n
Type: boolean | string[]
\n
\n
\n
Default: false
\n
\n
\n
Details:
\n
Add emoji interaction function to the article, set it to true to provide the default emoji, you can also customize the emoji image by setting the emoji url array, and supports a maximum of 8 emojis.
You can directly configure serializable options in the plugin options:
\n
import { defineUserConfig } from 'vuepress'\nimport { commentPlugin } from 'vuepress-plugin-comment2'\n\nexport default defineUserConfig({\n plugins: [\n commentPlugin({\n provider: 'Waline',\n // other options\n // ...\n }),\n ],\n})\n
Client Config
\n
You can use the defineWalineConfig function to customize Waline:
\n
import { defineClientConfig } from 'vuepress/client'\nimport { defineWalineConfig } from 'vuepress-plugin-comment2/client'\n\ndefineWalineConfig({\n // Waline config\n})\n\nexport default defineClientConfig({\n // ...\n})\n
",
+ "date_modified": "2024-03-11T08:20:01.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Bundler Related",
+ "url": "https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html",
+ "summary": "Bundler Related Bundler function is for appending or modifying bundler options in theme and plugins. All functions should be called in extendsBundlerOptions lifecycle hook. TIP ...",
+ "content_html": "\n
Bundler function is for appending or modifying bundler options in theme and plugins.
\n
All functions should be called in extendsBundlerOptions lifecycle hook.
\n
TIP
\n
We are omitting that in examples. The actual code should be like this:
\n
// import functions you need\nimport { addCustomElement } from '@vuepress/helper'\n\nexport const yourPlugin = {\n // ...\n extendsBundlerOptions: (bundlerOptions, app) => {\n // add them here\n addCustomElement(bundlerOptions, app, 'my-custom-element')\n },\n}\n
import { configWebpack } from '@vuepress/helper'\n\nconfigWebpack(bundlerOptions, app, (config, isServer, isBuild) => {\n // do some customize here\n})\n
\n
\n
\n",
+ "date_modified": "2024-02-03T11:34:35.000Z",
+ "authors": [],
+ "tags": []
+ },
+ {
+ "title": "Page Related",
+ "url": "https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html",
+ "id": "https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html",
+ "summary": "Page Related These functions generate common information for your pages. getPageExcerpt Get the excerpt of the page. getPageText Get plain text of the page.",
+ "content_html": "\n
These functions generate common information for your pages.
\n
getPageExcerpt
\n
Get the excerpt of the page.
\n
export interface PageExcerptOptions {\n /**\n * Excerpt separator\n *\n * @default \"<!-- more -->\"\n */\n separator?: string\n\n /**\n * Length of excerpt\n *\n * @description Excerpt length will be the minimal possible length reaching this value\n *\n * @default 300\n */\n length?: number\n\n /**\n * Tags which is considered as custom elements\n *\n * @description This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.\n */\n isCustomElement?: (tagName: string) => boolean\n\n /**\n * Whether keep page title (first h1) in excerpt\n *\n * @default false\n */\n keepPageTitle?: boolean\n\n /**\n * Whether preserve tags like line numbers and highlight lines for code blocks\n *\n * @default false\n */\n keepFenceDom?: boolean\n}\n\nexport const getPageExcerpt: (\n app: App,\n page: Page,\n options?: PageExcerptOptions,\n) => string\n
getPageText
\n
Get plain text of the page.
\n
export interface PageTextOptions {\n /**\n * Whether convert text to single line content\n *\n * @default false\n */\n singleLine?: boolean\n\n /**\n * Length of text\n *\n * @description Text length will be the minimal possible length reaching this value\n *\n * @default 300\n */\n length?: number\n\n /**\n * Tags to be removed\n *\n * @description Table and code blocks are removed by default.\n *\n * @default ['table', 'pre']\n */\n removedTags?: string[]\n}\n\nexport const getPageText: (\n app: App,\n page: Page,\n options?: PageTextOptions,\n) => string\n
",
+ "date_modified": "2024-02-03T11:34:35.000Z",
+ "authors": [],
+ "tags": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/images/comment/vercel-1.png b/images/comment/vercel-1.png
new file mode 100644
index 0000000000..5cb34f3c0a
Binary files /dev/null and b/images/comment/vercel-1.png differ
diff --git a/images/comment/vercel-2.png b/images/comment/vercel-2.png
new file mode 100644
index 0000000000..447e587c0b
Binary files /dev/null and b/images/comment/vercel-2.png differ
diff --git a/images/comment/vercel-3.png b/images/comment/vercel-3.png
new file mode 100644
index 0000000000..2d29503234
Binary files /dev/null and b/images/comment/vercel-3.png differ
diff --git a/images/comment/vercel-4.png b/images/comment/vercel-4.png
new file mode 100644
index 0000000000..0298d1e8da
Binary files /dev/null and b/images/comment/vercel-4.png differ
diff --git a/images/comment/vercel-5.png b/images/comment/vercel-5.png
new file mode 100644
index 0000000000..811af4dee9
Binary files /dev/null and b/images/comment/vercel-5.png differ
diff --git a/images/comment/vercel-6.png b/images/comment/vercel-6.png
new file mode 100644
index 0000000000..d7367e15f4
Binary files /dev/null and b/images/comment/vercel-6.png differ
diff --git a/images/comment/vercel-7.png b/images/comment/vercel-7.png
new file mode 100644
index 0000000000..a8bb786970
Binary files /dev/null and b/images/comment/vercel-7.png differ
diff --git a/images/comment/vercel-8.png b/images/comment/vercel-8.png
new file mode 100644
index 0000000000..77ca69d69a
Binary files /dev/null and b/images/comment/vercel-8.png differ
diff --git a/images/comment/vercel-9.png b/images/comment/vercel-9.png
new file mode 100644
index 0000000000..259bfee7de
Binary files /dev/null and b/images/comment/vercel-9.png differ
diff --git a/images/cookbook/extending-a-theme-01.png b/images/cookbook/extending-a-theme-01.png
new file mode 100644
index 0000000000..9ba6d7e812
Binary files /dev/null and b/images/cookbook/extending-a-theme-01.png differ
diff --git a/images/hero.png b/images/hero.png
new file mode 100644
index 0000000000..ac6beaff06
Binary files /dev/null and b/images/hero.png differ
diff --git a/images/icons/android-chrome-192x192.png b/images/icons/android-chrome-192x192.png
new file mode 100644
index 0000000000..ddd043910e
Binary files /dev/null and b/images/icons/android-chrome-192x192.png differ
diff --git a/images/icons/android-chrome-384x384.png b/images/icons/android-chrome-384x384.png
new file mode 100644
index 0000000000..86e1fd58b3
Binary files /dev/null and b/images/icons/android-chrome-384x384.png differ
diff --git a/images/icons/apple-touch-icon.png b/images/icons/apple-touch-icon.png
new file mode 100644
index 0000000000..208915f1de
Binary files /dev/null and b/images/icons/apple-touch-icon.png differ
diff --git a/images/icons/favicon-16x16.png b/images/icons/favicon-16x16.png
new file mode 100644
index 0000000000..ca5047e7b8
Binary files /dev/null and b/images/icons/favicon-16x16.png differ
diff --git a/images/icons/favicon-32x32.png b/images/icons/favicon-32x32.png
new file mode 100644
index 0000000000..e275ce9ba1
Binary files /dev/null and b/images/icons/favicon-32x32.png differ
diff --git a/images/icons/mstile-150x150.png b/images/icons/mstile-150x150.png
new file mode 100644
index 0000000000..d0b1439483
Binary files /dev/null and b/images/icons/mstile-150x150.png differ
diff --git a/images/icons/safari-pinned-tab.svg b/images/icons/safari-pinned-tab.svg
new file mode 100644
index 0000000000..dc0b992c04
--- /dev/null
+++ b/images/icons/safari-pinned-tab.svg
@@ -0,0 +1,23 @@
+
+
+
diff --git a/images/logo.png b/images/logo.png
new file mode 100644
index 0000000000..60e17006ad
Binary files /dev/null and b/images/logo.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 0000000000..6955e0eca5
--- /dev/null
+++ b/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+ Home | VuePress Ecosystem
+
+
+
+
+
+
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.
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.
Page filter, determine whether the plugin should generate excerpt for it.
TIP
You should use this to skip pages that you don't need to generate excerpt for. E.g.: If users set excerpt or description in frontmatter, you may want to use them directly.
It's disabled by default because it does have performance impact in sites with a lot of categories and types. And it can slow down hotReload speed when editing Markdown.
If users are adding or organizing your categories or tags, you may tell them to enable this, for the rest it's better to keep it disabled.
Also, you can try to detect number of pages in users project and decide whether to enable it.
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
Demo
import { blogPlugin } from '@vuepress/plugin-blog'
+
+export default {
+ name: 'vuepress-theme-xxx',
+ plugins: [
+ blogPlugin({
+ filter: ({ filePathRelative, frontmatter }) => {
+ // drop those pages which is NOT generated from file
+ if (!filePathRelative) return false
+
+ // drop those pages in `archives` directory
+ if (filePathRelative.startsWith('archives/')) return false
+
+ // drop those pages which do not use default layout
+ if (frontmatter.home || frontmatter.layout) return false
+
+ return true
+ },
+
+ getInfo: ({ frontmatter, git = {}, data = {} }) => {
+ // getting page info
+ const info: Record<string, any> = {
+ author: frontmatter.author || '',
+ categories: frontmatter.categories || [],
+ date: frontmatter.date || git.createdTime || null,
+ tags: frontmatter.tags || [],
+ excerpt: data.excerpt || '',
+ }
+
+ return info
+ },
+ }),
+ // other plugins ...
+ ],
+}
+
Basically, you would want 2 types of collection in your blog:
Category:
"Category" means grouping articles with their labels.
For example, each article may have their "categories" and "tags".
Type:
"Type" means identifying articles with conditions.
For example, you may want to describe some of your articles as diary.
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
Let's start with 2 examples here.
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
interface BlogFrontmatterOptions {
+ /** Current type of the page */
+ type: 'category' | 'type'
+ /** Unique key under current category or tag */
+ key: string
+ /**
+ * Current category name
+ *
+ * @description Only available in category item page
+ */
+ name?: string
+}
+
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
Also, you can pass key you want as argument, then you will get information bind to that key.
So with node side settings above, you can get information about "tag" and "star" in client side:
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
Excerpt introduction
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default <!-- more -->, and you can customize it by setting excerptSeparator option.
If it cannot find a valid separator, it will parse content from the beginning of markdown file, and stop till its length reaches a preset value. The value is default 300, and you can customize it by setting excerptLength option.
To choose which page should generate excerpt, you can use excerptFilter option.
Example
Normally you may want to use frontmatter.description if users set them, so you can let filter function return false if frontmatter.description is not empty.
import { catalogPlugin } from '@vuepress/plugin-catalog'
+
+export default {
+ extendsPage: (page) => {
+ // set catalog info in routeMeta
+ page.routeMeta = {
+ // catalog title
+ title: page.title,
+ // ... other information
+ }
+ },
+}
+
You can then import defineCatalogInfoGetter from @vuepress/plugin-catalog/client and use it in client config fileopen in new window to extract catalog info from meta.
The plugin will sort pages by order in the following way:
// order positive numbers from small to large
+Project with order 1
+Project with order 2
+...
+Project with order 10
+...
+// Project without order
+Project without order
+Project without order
+...
+// order negative numbers from small to large
+Project with order -10
+// ...
+Project with order -2
+Project with order -1
+
The plugin retains the el option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the pageTitle, pageKey and site options for you according to the VuePress information.
To let Artalk apply the correct theme, you need to pass a boolean value to <CommentService /> through darkmode prop, representing whether the dark mode is currently enabled.
You just need to fill in the repository and Discussion categories, then scroll to the "Enable giscus" section at the bottom of the page and obtain four attributes: data-repo, data-repo-id, data-category and data-category-id.
Please set provider: "Giscus" and pass data-repo, data-repo-id, data-category and data-category-id as plugin options as repo, repoId, categorycategoryId.
By default, the theme of Giscus is light or dark (based on darkmode status).
Darkmode
To let Giscus apply the correct theme, you need to pass a boolean value to <CommentService /> via darkmode property, indicating whether darkmode is currently enabled.
If you want to customize theme in lightmode and darkmode, you can set lightTheme and darkTheme option with a built-in theme keyword or a custom CSS link starting with https://.
But here are some limitations you should remember:
provider, locales and other resource related option must be set in plugin options.
To ensure tree-shaking works, we must optimize entries at node so that bundler can understand which resource should be included in the final bundle.
These options will be marked with Plugin Option Only in config reference.
Options which can not be serialized to JSON must be set in client config.
Options that receives function values can not be set in plugin options, as plugins are running under Node.js environment, so we can not pass these values and their contexts to browser.
These options will be marked with Client Config Only in config reference.
This plugin globally registers a component <CommentService />.
If you are a user, you should use alias and layout slots to insert the component. We recommended you to insert the comment component (<CommentService />) after the <PageNav /> component, and the current page is a demo with default theme.
If you are a theme developer, you should insert this component in the layout of your theme.
By default, <CommentService /> component is enabled globally, and you can use comment option in both plugin options and page frontmatter to control it.
You can disable it locally by setting comment: false in page frontmatter.
To keep it globally disabled, please set comment to false in the plugin options. Then you can set comment: true in page frontmatter to enable it locally.
You can set commentID option in page frontmatter to customize comment ID, which is used to identify comment storage item to use for a page. By default it will be the path of the page, which means if you are deploying the site to multiple places, page with same content across sites will share the same comment data.
Create a free MongoDB database, the recommended region is AWS / N. Virginia (us-east-1)
Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses (Why?open in new window), create Database user, and record the database connection string, please change the <password> in the connection string to the database password
Go to Settings - Environment Variables, add the environment variable MONGODB_URI, the value is the database connection string in step 3
Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt "Twikoo cloud function is running normally"
Vercel Domains (with https:// prefix, e.g. https://xxx.vercel.app) is your environment ID
Code highlighting, use hanabi by default. The function passes in original content of code block and language of the code block. You should return a string directly.
You can pass in a code highlighter of your own, or set to false to disable code highlighting.
Customize TeX rendering, the default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters, the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content, and return a HTML string as render result.
You can import TeX renderer to provide preview feature. We recommend you to use Katex or MathJax, or you can set to false to disable parsing TeX.
Add emoji interaction function to the article, set it to true to provide the default emoji, you can also customize the emoji image by setting the emoji url array, and supports a maximum of 8 emojis.
Enter the app, then select Settings > App Keys at the left bottom corner. You will see APP ID, APP Key and Master Key of your app. We will use them later
Click the dark button above, it will redirect you to vercel to deploy with waline template.
TIP
If you haven't logged in, we recommend you to sign in with GitHub.
Input your Vercel project name then click Create.
Repo which named you input before will be created and initialized automatically base on waline example template by Vercel.
After one minute or two, vercel should finish the deployment. Click Go to Dashboard button to redirect to your application dashboard.
Click Settings menu on the top, and Environment Variables button on the side to go to environment variables setting page. Then set LEAN_ID, LEAN_KEY and LEAN_MASTER_KEY. The variables' value should be the ones you got in the previous step. APP ID is the value of LEAN_ID, and APP Key to LEAN_KEY, Master Key to LEAN_MASTER_KEY.
To let your environment variables setting active, you need redeploy your application. Click Deployments menu on the top and find the latest deployment at the top of list, click Redeploy button in the right dropdown menu.
If everything is ok, vercel will redirect to Overview page to start redeployment. Wait a moment the STATUS will change to Ready. Now you can click Visit to visit the site. This link is your server address.
Set provider: "Waline" in the plugin options, and set serverURL as the link obtained in the previous step.
Then, place the <CommentService> component at a suitable location in your site (usually at the bottom of the page), you will be able to see the comment box.
TIP
You can also pass in other options supported by Waline (except el). For details, see Waline Config
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.
This plugin is disabled globally by default, you can:
Manually enable it by setting copy: true in page frontmatter
Set global: 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.
If you don't want users to copy your entire site or specific page text, you can set disableCopy in plugin options or copy.disableCopy in page frontmatter, the latter has higher priority.
If you don't want users to select your entire site or specific page text, you can set disableSelection in plugin options or copy.disableSelection in page frontmatter. This option has higher priority.
You need to submit the URL of your siteopen in new window 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.
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 Crawleropen in new window, and edit your config with 'Editor' panel in project sidebar.
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 baseopen in new window of your deployments are different for different domains, you need to set the option to the baseopen in new window of your index domain, so that other deployments could reuse the search index correctly.
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.
// 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.
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
+}
+
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
+}
+
When you open the feed file in browser, we magically convert atom and rss feed xml to human readable html via xsl template. Check atomopen in new window and rssopen in new window 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}.
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.
This plugin requires your project to be inside a Git Repositoryopen in new window, 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 1open in new window 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.
The Measurement ID of Google Analytics 4, which should start with 'G-'.
You can follow the instructions hereopen in new window 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).
Returns the Zoom instance that used by this plugin, so that you can use the instance methodsopen in new window 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()
+ })
+ },
+}
+
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.
Swipe left and right to preview other pictures on the page in order
View the description of the picture
Zoom in and zoom out the picture
View pictures in full screen
Download pictures
Share pictures
TIP
Besides clicking "×" in the upper right corner to exit the preview mode, scrolling up and down more than a certain distance will also exit preview mode.
On mobile devices, or using the PC trackpad, you can use pan and zoom gestures to pan and zoom in the preview mode.
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.
By default, languages will be loaded on demand when parsing markdown files.
However, Prism.js has some potential issuesopen in new window about loading languages dynamically. To avoid them, you can preload languages via this option.
"disabled": Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
"available": Only display update popup when the new service worker is available
"hint": Display a hint to let user choose to refresh immediately
This is helpful when you want users to see new docs immediately.
TIP
If users choose to refresh, the current service worker will be unregister, and request will start coming to web. Later the new service worker will start installing and control current page after installed.
"force": unregister current service worker immediately then refresh to get new content
DANGER
Although this ensures users are viewing the latest content, it may affect viewing experiences.
TIP
How docs are updated is controlled by a previous version, so the current option only effect next update from this version.
To make your website fully compliant with PWA, a Web app manifests [3] file is needed, and your pwa should satisfy the installability [4] specification.
You can set manifest option to customize the manifest file, or provide a manifest.webmanifest or manifest.json in public folder. The former has higher priority.
The plugin will automatically generate manifest.webmanifest for you and add manifest link declaration in each page, while you should still at least set a valid icon through manifest.icons or other icon related options in the PWA plugin.
WARNING
The installability [4:1] specification requires at least one valid icon to be declared in the manifest.
So if you do not configure manifest.icons, visitors can only enjoy the offline accessibility brought by the Service Worker cache, while cannot install your site as a PWA.
Besides the plugin does not process anything in the manifest by default, but outputs them as-is. This means that if you plan to deploy to a subdirectory, you should append the URL prefix to manifest Urls yourself. If everything you need is all under base directory, you can set appendBase: true in plugin options to let the plugin append base to any links in manifest.
By default, the plugin will pre-cache all jscss files, and only homepage and 404 html are cached. The plugin will also cache font files (woff, woff2, eot, ttf, otf) and SVG icons.
If you have small sites, and would like to make document fully offline available, you can set cacheHTML to true to cache all HTML files.
Why only home and 404 page been cached by default?
Though VuePress generates HTML files through SSG[5] for all pages, these files are mainly used for SEO[6] and allow you to directly configure the backend without SPA[7] Visit any link.
VuePress is essentially an SPA. This means that you only need to cache the home page and enter from the home page to access all pages normally. Therefore, not caching other HTML by default can effectively reduce the cache size (40% smaller in size) and speed up the SW update speed.
But this also has the disadvantage. If the user enters the site directly from a non-home page, the HTML file for the first page still needs to be loaded from the internet. Also, in offline environment, users can only enter through the homepage and then navigate to the corresponding page by themselves. If they directly access a link, an inaccessible prompt will appear.
To prevent large files from being included in the pre-cache list, any files > 2 MB or images > 1 MB will be omitted. You can customize these limits with maxSize and maxImageSize options (in KB unit).
We provide the update option to control how users receive updates.
The default value of the update option is "available", which means that when new content available, the new SW will be installed and its resources will be fetched silently in the background. A pop-up window appears once the new SW is ready, and users can choose whether to refresh immediately to view new content. This means users are reading old content before a new SW is ready.
If your project is still in building stage, and you want to alert the user that he may be reading outdated content, you can set this to "hint". This allows users to be notified that new content has been published within seconds after visiting docs. But the negative effect of this is that if the user chooses to update before the new SW is ready, he will need to get all the resources of the page from the internet before the new SW installs and controls the page.
If your docs are stable, or you're hosting a blog and don't care much about users receiving the latest version right away, you can set this to "disabled", which means that the new SW will be installed completely silently in the background and start waiting, when all pages controlled by old SW are all closed, the new SW will start to take control and provide users with new content during next visit. This setting can prevent users from being disturbed during the visit.
To speed up user access under weak or no network conditions through SW, but also want users to always access new content, you can set this option to "force". This means any old SW will be removed as soon as a new SW is detected, and all pages are refreshed to ensure the user is browsing the latest content. The biggest disadvantage is that all users will experience unexpected sudden refresh within seconds after reentering an updated site.
When new content is detected (new SW detected), a update found popup appears; and when the new content is ready, an update ready popup appears.
If you are not satisfied with the default popup content, you can use your own component. Import PwaFoundPopup or PwaReadyPopup from @vuepress/plugin-pwa/client and use its slot to customize the popup content, then pass the component path to foundComponent or readyComponent option:
The plugin also provides other PWA-related options, such as Microsoft tile icon and color settings, Apple icon and so on. If you are an advanced user, you can also set generateSwConfig to configure workbox-build. Check Plugin options for more details.
The Service Worker will get and cache all the files registered in it during the registration process.
After the registration complete, the Service Worker is activated, and starts to proxy and control all your requests.
Whenever you want to initiate an access request through the browser, the Service Worker will check whether it exists in its own cache list, if it exists, it will directly return the cached result, otherwise it will call its own fetch method to get it. You can use a custom fetch method to fully control the result of the request for resources in the web page, such as providing a fallback web page when offline.
Every time the user reopens the site, the Service Worker will request to the link when it was registered. If a new version of Service Worker is detected, it will update itself and start caching the list of resources registered in the new Service Worker . After the content update is successfully obtained, the Service Worker will trigger the update event. The user can be notified through this event, for example, a pop-up window will be displayed in the lower right corner, prompting the user that new content is available and allowing the user to trigger an update.
The manifest file uses the JSON format and is responsible for declaring various information of the PWA, such as name, description, icon, and shortcut actions.
In order for your site to be registered as a PWA, you need to meet the basic specifications of the manifest to make the browser consider the site as an installable PWA and allow users to install it.
To let the site be registered as a PWA, the site needs to successfully register a valid service worker by itself, and declare a valid manifest file with its link in meta tag.
The manifest file should contain at least name (or short_name) iconsstart_url.
On safari, the maximum cache size of the service worker is 50 MB. ↩︎↩︎
SPA: Single Page Application, most of them only have the homepage, and use history mode to handle routing instead of actually navigating between pages. ↩︎
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:
interface ReadingTime {
+ /** Expect reading time in minute unit */
+ minutes: number
+ /** Words count of content */
+ words: number
+}
+
+const useReadingTimeData: () => ComputedRef<ReadingTime | null>
+
When you register a plugin multiple times, vuepress will gives you warning about that telling you only the first one takes effect. The useReadingTimePlugin automatically detects if the plugin is registered and avoid registering multiple times.
If you access reading time data in 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
+ }
+}
+
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:
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 asking
modal: When the user's language preference is different from the current page language, show a modal asking whether to switch language
By 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:
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.
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:
A new service worker with empty contents shall be generated in the original place.
The new service worker shall attempt to remove contents that old service worker cached, then it should unregister itself.
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.
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;
+}
+
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:
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.
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:
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.
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.
This plugin will enable syntax highlighting for markdown code fence with Shikiopen in new window.
TIP
Shikiopen in new window is the syntax highlighter being used by VSCode. It has higher fidelity, but it could be slower than Prism.jsopen in new window, especially when you have a lot of code blocks.
You could consider disabling this plugin in dev mode to get better development experience.
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.
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):
Provide search engine spiders with links of the entire site;
Provide some links for search engine spiders to dynamic pages or pages that are difficult to reach by other methods;
If a visitor attempts to access a URL that does not exist within the site's domain, the visitor will be directed to a "file not found" error page, and the sitemap can be used as a navigation page.
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)
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.
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.
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.
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:
+
+
A NavbarItem object should have a text field and a link field, could have an optional activeMatch field.
+
A NavbarGroup object should have a text field and a children field. The children field should be a navbar array, too.
+
A string should be the path to the target page file. It will be converted to a NavbarItem object, using the page title as text, and the page route path as link.
If not specified, defaults to be the same as the site title.
+
+
+
repo
+
+
+
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',
+ }),
+}
+
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:
+
+
A 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.
+
A string should be the path to the target page file. It will be converted to a 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:
+
+
The key should be the path prefix.
+
The value should be a sidebar array or set to 'heading' to automatically generate the sidebar from the page headers for just the corresponding path.
Set the maximum depth of the sidebar children which are automatically generated from the page headers.
+
+
Set to 0 to disable all levels of headers.
+
Set to 1 to include <h2> headers.
+
Set to 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.
+
+
+
editLink
+
+
+
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.
+
+
+
editLinkPattern
+
+
+
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 |
+|
+
+
+]]>
+
+
+ Extending
+ https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html
+ https://ecosystem.vuejs.press/ecosystem/themes/default/extending.html
+
+ Extending VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease. Layout Slots Default them...
+ VuePress default theme is widely used by users, so it is designed to be extendable, allowing users to make their own customization with ease.
+
Layout Slots
+
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:
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):
+
+
Components Replacement
+
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:
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
+ https://ecosystem.vuejs.press/ecosystem/themes/default/frontmatter.html
+ https://ecosystem.vuejs.press/ecosystem/themes/default/frontmatter.html
+
+ Frontmatter
+
+
+
+ Locale Config
+ https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html
+ https://ecosystem.vuejs.press/ecosystem/themes/default/locale.html
+
+ Locale Config 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 tr...
+ 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.
+
repoLabel
+
+
+
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.
+
+
+
selectLanguageText
+
+
+
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.
+
+
+
selectLanguageAriaLabel
+
+
+
Type: string
+
+
+
Details:
+
Specify the aria-label attribute of the select language menu.
+
This is mainly for a11y purpose.
+
+
+
selectLanguageName
+
+
+
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.
+]]>
+
+
+ Markdown
+ https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html
+ https://ecosystem.vuejs.press/ecosystem/themes/default/markdown.html
+
+ Markdown
+
+
+
+ Plugins Config
+ https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html
+ https://ecosystem.vuejs.press/ecosystem/themes/default/plugin.html
+
+ Plugins Config 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...
+ 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.
Page filter, determine whether the plugin should generate excerpt for it.
+
TIP
+
You should use this to skip pages that you don't need to generate excerpt for. E.g.: If users set excerpt or description in frontmatter, you may want to use them directly.
This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.
+
+
+
metaScope
+
+
+
Type: string
+
+
+
Default: "_blog"
+
+
+
Details:
+
Key used when injecting info to route meta.
+
TIP
+
Setting to an empty key will inject to route meta directly instead of a field.
+
+
+
+
hotReload
+
+
+
Type: boolean
+
+
+
Default: Whether using --debug flag
+
+
+
Details:
+
Whether enable hotReload in devServer.
+
To theme developers
+
It's disabled by default because it does have performance impact in sites with a lot of categories and types. And it can slow down hotReload speed when editing Markdown.
+
If users are adding or organizing your categories or tags, you may tell them to enable this, for the rest it's better to keep it disabled.
+
Also, you can try to detect number of pages in users project and decide whether to enable it.
+
+
+
+
Blog Category Config
+
Blog category config should be an array, while each item is controlling a "category" rule.
+
interface BlogCategoryOptions {
+ /**
+ * Unique category name
+ */
+ key: string
+
+ /**
+ * Function getting category from page
+ */
+ getter: (page: Page) => string[]
+
+ /**
+ * A custom function to sort the pages
+ */
+ sorter?: (pageA: Page, pageB: Page) => number
+
+ /**
+ * Path pattern of page to be registered
+ *
+ * @description `:key` will be replaced by the "slugify" result of the original key
+ *
+ * @default `/:key/`
+ */
+ path?: string
+
+ /**
+ * Page layout name
+ *
+ * @default 'Layout'
+ */
+ layout?: string
+
+ /**
+ * Frontmatter
+ */
+ frontmatter?: (localePath: string) => Record<string, string>
+
+ /**
+ * Item page path pattern or custom function to be registered
+ *
+ * @description When filling in a string, `:key` and `:name` will be replaced by the "slugify" result of the original key and name
+ *
+ * @default `/:key/:name/`
+ */
+ itemPath?: string | ((name: string) => string)
+
+ /**
+ * Item page layout name
+ *
+ * @default 'Layout'
+ */
+ itemLayout?: string
+
+ /**
+ * Items Frontmatter
+ */
+ itemFrontmatter?: (name: string, localePath: string) => Record<string, string>
+}
+
Blog Type Config
+
Blog type config should be an array, while each item is controlling a "type" rule.
+
interface BlogTypeOptions {
+ /**
+ * Unique type name
+ */
+ key: string
+
+ /**
+ * A filter function to determine whether a page should be the type
+ */
+ filter: (page: Page) => boolean
+
+ /**
+ * A custom function to sort the pages
+ */
+ sorter?: (pageA: Page, pageB: Page) => number
+
+ /**
+ * Page path to be registered
+ *
+ * @default '/:key/'
+ */
+ path?: string
+
+ /**
+ * Layout name
+ *
+ * @default 'Layout'
+ */
+ layout?: string
+
+ /**
+ * Frontmatter
+ */
+ frontmatter?: (localePath: string) => Record<string, string>
+}
+
Composition API
+
You can import the following API from @vuepress/plugin-blog/client.
If no key is passed, the plugin will try to use the key in current path.
+
+
+
Returning values are:
+
interface Article<T extends Record<string, unknown> = Record<string, unknown>> {
+ /** Article path */
+ path: string
+ /** Article info */
+ info: T
+}
+
+interface BlogCategoryData<
+ T extends Record<string, unknown> = Record<string, unknown>,
+> {
+ /** Category path */
+ path: string
+
+ /**
+ * Only available when current route matches an item path
+ */
+ currentItems?: Article<T>[]
+
+ /** Category map */
+ map: {
+ /** Unique key under current category */
+ [key: string]: {
+ /** Category path of the key */
+ path: string
+ /** Category items of the key */
+ items: Article<T>[]
+ }
+ }
+}
+
+interface BlogTypeData<
+ T extends Record<string, unknown> = Record<string, unknown>,
+> {
+ /** Type path */
+ path: string
+
+ /** Items under current type */
+ items: Article<T>[]
+}
+
]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/blog/guide.html
+
+ With @vuepress/plugin-blog, you can easily bring blog feature into your theme. Collecting Articles The plugin filters all pages using filter option to drop pages you don't want....
+ With @vuepress/plugin-blog, you can easily bring blog feature into your theme.
+
Collecting Articles
+
The plugin filters all pages using filter option to drop pages you don't want.
+
By default, all pages generating from Markdown files but not homepage are considered as articles.
+
+
You can fully customize pages to collect through option filter, which accepts a function (page: Page) => boolean.
+
Gathering Info
+
You should set getInfo option with a function accepting Page as argument and returning an object containing the info you want.
+
The plugin will collect all the info you want and write them to routeMeta field of each page, so you will be able to get this information through Composition API later.
+Demo
+
import { blogPlugin } from '@vuepress/plugin-blog'
+
+export default {
+ name: 'vuepress-theme-xxx',
+ plugins: [
+ blogPlugin({
+ filter: ({ filePathRelative, frontmatter }) => {
+ // drop those pages which is NOT generated from file
+ if (!filePathRelative) return false
+
+ // drop those pages in `archives` directory
+ if (filePathRelative.startsWith('archives/')) return false
+
+ // drop those pages which do not use default layout
+ if (frontmatter.home || frontmatter.layout) return false
+
+ return true
+ },
+
+ getInfo: ({ frontmatter, git = {}, data = {} }) => {
+ // getting page info
+ const info: Record<string, any> = {
+ author: frontmatter.author || '',
+ categories: frontmatter.categories || [],
+ date: frontmatter.date || git.createdTime || null,
+ tags: frontmatter.tags || [],
+ excerpt: data.excerpt || '',
+ }
+
+ return info
+ },
+ }),
+ // other plugins ...
+ ],
+}
+
+
Customizing Categories and Types
+
Basically, you would want 2 types of collection in your blog:
+
+
+
Category:
+
"Category" means grouping articles with their labels.
+
For example, each article may have their "categories" and "tags".
+
+
+
Type:
+
"Type" means identifying articles with conditions.
+
For example, you may want to describe some of your articles as diary.
+
+
+
After understanding description of these 2 types, you can set category and type options, each accepts an array, and each element represents a configuration.
+
Let's start with 2 examples here.
+
Imagine you are setting tags for each articles with tag field in page frontmatter. You want a tag mapping page in /tag/ with TagMap layout, and group each tag list with tagName in /tag/tagName with TagList layout, you probably need a configuration like this:
Also, you may want to star some of your articles, and display them to visitors. When you are setting star: true in frontmatter to mark them, you probably need a configuration like this to display them in /star/ path with StarList layout:
When generating each page, the plugin will set following information under frontmatter.blog:
+
interface BlogFrontmatterOptions {
+ /** Current type of the page */
+ type: 'category' | 'type'
+ /** Unique key under current category or tag */
+ key: string
+ /**
+ * Current category name
+ *
+ * @description Only available in category item page
+ */
+ name?: string
+}
+
So you can invoke useBlogCategory() and useBlogType() directly, and the result will be the category or type bind to current route.
+
Also, you can pass key you want as argument, then you will get information bind to that key.
+
So with node side settings above, you can get information about "tag" and "star" in client side:
Then /zh/star/ and /star/ will both be available, and only articles under the correct locale will appear.
+
Generating Excerpt
+
This plugin provides a built-in excerpt generator, which can be enabled by setting excerpt option to true.
+
Excerpt introduction
+
An excerpt is an HTML fragment that is used to display a short description of an article in the blog list, so the excerpt has the following restrictions:
+
+
It doesn't support any unknown tags (including all Vue components) and Vue syntax, so these contents will be removed when generating. If you have custom components (non-Vue components), set isCustomElement option.
+
Since the snippet is an HTML fragment, you will not be able to import any images via relative paths or aliases, they will be removed directly. If you want to keep images, please use absolute path based on .vuepress/public or full URL to ensure they can be accessed in other places.
+
+
+
The excerpt generator will try to find a valid excerpt separator from markdown contents, if it finds one, it will use content before the separator. The separator is default <!-- more -->, and you can customize it by setting excerptSeparator option.
+
If it cannot find a valid separator, it will parse content from the beginning of markdown file, and stop till its length reaches a preset value. The value is default 300, and you can customize it by setting excerptLength option.
+
To choose which page should generate excerpt, you can use excerptFilter option.
+
Example
+
Normally you may want to use frontmatter.description if users set them, so you can let filter function return false if frontmatter.description is not empty.
+
+]]>
+
+
+ comment
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/
+
+ comment
+
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/guide.html
+
+ Guide Setting Options You can both set options with plugin options on Node side and set options in client config file on Browser side. With Plugin Options With Client Config Fil...
+ Setting Options
+
You can both set options with plugin options on Node side and set options in client config file on Browser side.
But here are some limitations you should remember:
+
+
+
provider, locales and other resource related option must be set in plugin options.
+
To ensure tree-shaking works, we must optimize entries at node so that bundler can understand which resource should be included in the final bundle.
+
These options will be marked with
+
+
+
Options which can not be serialized to JSON must be set in client config.
+
Options that receives function values can not be set in plugin options, as plugins are running under Node.js environment, so we can not pass these values and their contexts to browser.
+
These options will be marked with
+
+
+
Adding Comment
+
This plugin globally registers a component <CommentService />.
+
+
If you are a user, you should use alias and layout slots to insert the component. We recommended you to insert the comment component (<CommentService />) after the <PageNav /> component, and the current page is a demo with default theme.
+
If you are a theme developer, you should insert this component in the layout of your theme.
+
+
By default, <CommentService /> component is enabled globally, and you can use comment option in both plugin options and page frontmatter to control it.
+
+
You can disable it locally by setting comment: false in page frontmatter.
+
To keep it globally disabled, please set comment to false in the plugin options. Then you can set comment: true in page frontmatter to enable it locally.
+
+
You can set commentID option in page frontmatter to customize comment ID, which is used to identify comment storage item to use for a page. By default it will be the path of the page, which means if you are deploying the site to multiple places, page with same content across sites will share the same comment data.
A custom filter function, used to filter feed items.
+
sorter
+
+
+
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.
The plugin has a built-in getter, only set this if you want full control of feed generation.
+
+
locales
+
+
Type: Record<string, BaseFeedOptions>
+
+
You can use it to specific options for each locale.
+
Any options above are supported except hostname.
+]]>
+
+
+ Frontmatter Config
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/frontmatter.html
+
+ Frontmatter Config You can control each feed item generation by setting page frontmatter. Additions and Removals By default, all articles are added to the feed stream. Set feed:...
+ You can control each feed item generation by setting page frontmatter.
+
Additions and Removals
+
By default, all articles are added to the feed stream. Set feed: false in frontmatter to remove a page from feed.
+
Frontmatter Information
+
title
+
+
Type: string
+
+
Automatically generated by VuePress, defaults to the h1 content of the page
+
description
+
+
Type: string
+
+
Description of the page
+
date
+
+
Type: Date
+
+
Date when the page was published
+
article
+
+
Type: boolean
+
+
Whether the page is an article
+
+
If this is set to false, the page will not be included in the final feed.
+
+
copyright
+
+
Type: string
+
+
Page copyright information
+
cover / image / banner
+
+
Type: string
+
+
Image used as page cover , should be full link or absolute link.
The identifier of feed item, used to identify the feed item.
+
You should ensure every feed has a unique guid.
+
+]]>
+
+
+ Feed Getter
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/getter.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/getter.html
+
+ Feed Getter You can take full control of feed items generation by setting getter in the plugin options. getter.title Type: (page: Page) => string Item title getter getter.link T...
+ You can take full control of feed items generation by setting getter in the plugin options.
+
getter.title
+
+
Type: (page: Page) => string
+
+
Item title getter
+
getter.link
+
+
Type: (page: Page) => string
+
+
Item link getter
+
getter.description
+
+
Type: (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:.
+
+
getter.content
+
+
Type: (page: Page) => string
+
+
Item content getter
+
getter.author
+
+
Type: (page: Page) => FeedAuthor[]
+
+
Item author getter.
+
The getter should return an empty array when author information is missing.
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
+}
+
+
getter.enclosure
+
+
Type: (page: Page) => FeedEnclosure | undefined
+
+
Item enclosure getter.
+FeedEnclosure format
+
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
+}
+
+
getter.publishDate
+
+
Type: (page: Page) => Date | undefined
+
+
Item release date getter
+
getter.lastUpdateDate
+
+
Type: (page: Page) => Date
+
+
Item last update date getter
+
getter.image
+
+
Type: (page: Page) => string
+
+
Item Image Getter
+
Ensure it's returning a full URL
+
+
getter.contributor
+
+
Type: (page: Page) => FeedContributor[]
+
+
Item Contributor Getter
+
The getter should return an empty array when contributor information is missing.
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/feed/guide.html
+
+ Guide Usage The plugin can generate feed files in the following three formats for you: Atom 1.0 JSON 1.1 RSS 2.0 Please set atom, json or rss to true in the plugin options accor...
+ Usage
+
The plugin can generate feed files in the following three formats for you:
+
+
Atom 1.0
+
JSON 1.1
+
RSS 2.0
+
+
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,
+
Readable Preview
+
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}.
+
Channel settings
+
You can customize the feed channel information by setting the channel option.
+
We recommend the following settings:
+
+
Convert the date of creating the feed to ISOString and write it into channel.pubDate
+
The update period of the content set in channel.ttl (unit: minutes)
+
Set copyright information via channel.copyright
+
Set the channel author via channel.author.
+
+
For detailed options and their default values, see Channel Config
+
Feed Generation
+
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.
+
I18n Config
+
The plugin generates separate feeds for each language.
+
You can provide different settings for different languages via locales in the plugin options.
Whether cache HTML files besides home page and 404 page.
+
+
+
cacheImage
+
+
+
Type: boolean
+
+
+
Default: false
+
+
+
Details:
+
Whether cache pictures
+
+
+
maxSize
+
+
+
Type: number
+
+
+
Default: 2048
+
+
+
Details:
+
Max size allowed to be cached, with KB unit
+
WARNING
+
This option has the highest priority, and any files exceeding this value will be excluded.
+
So if you generate very large HTML or JS files, please consider increasing this value, otherwise your PWA may not work normally in offline mode.
+
+
+
+
maxImageSize
+
+
+
Type: number
+
+
+
Default: 1024
+
+
+
Details:
+Max picture size allowed to be cached, with KB unit
+
The value must not be greater than maxSize option
+
+
+
+
update
+
+
+
Type: "disabled" | "available" | "hint" | "force"
+
+
+
Default: "available"
+
+
+
Details:
+Control logic when new content is found.
+
+
+
"disabled": Do nothing even when new service worker is available. After new service work succeeds installing and starts waiting, it will control page and provide new content in next visit.
+
+
+
"available": Only display update popup when the new service worker is available
+
+
+
"hint": Display a hint to let user choose to refresh immediately
+
This is helpful when you want users to see new docs immediately.
+
TIP
+
If users choose to refresh, the current service worker will be unregister, and request will start coming to web. Later the new service worker will start installing and control current page after installed.
+
+
+
+
"force": unregister current service worker immediately then refresh to get new content
+
DANGER
+
Although this ensures users are viewing the latest content, it may affect viewing experiences.
+
+
+
+
TIP
+
How docs are updated is controlled by a previous version, so the current option only effect next update from this version.
+
+
+
+
apple
+
Special settings for better supporting Safari, ignoring these options are safe.
+
apple.icon
+
+
Type: string
+
Details: Icon link used by Safari.
+
+
apple.statusBarColor
+
+
Type: "black" | "white"
+
Default: "black"
+
Details: Status bar color for Safari
+
+
apple.maskIcon
+
+
Type: string
+
Details: Safari mask icon
+
+
msTile
+
Special settings for Microsoft tiles, ignoring these options are safe.
+
msTile.image
+
+
Type: string
+
Details: Tile image
+
+
msTile.color
+
+
Type: string
+
Default value: themeColor
+
Details: Tile color
+
+
foundComponent
+
+
Type: string
+
Default: "PwaFoundPopup"
+
Details: Path of custom hint popup component.
+
+
readyComponent
+
+
Type: string
+
Default: "PwaReadyPopup"
+
Details: Path of custom update popup component.
+
+
appendBase
+
+
Type: boolean
+
Default: false
+
Details: Whether append base to all absolute links in options.
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/pwa/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/pwa/guide.html
+
+ Guide Intro Make your VuePress site a Progressive Web Application (PWA)[1]. This plugin uses workbox-build to generate service worker file, and uses register-service-worker to r...
+ Intro
+
Make your VuePress site a Progressive Web Application (PWA)[1].
To better control what the Service Worker can pre-cache, the plugin provides related options for cache control.
+
Default cache
+
By default, the plugin will pre-cache all jscss files, and only homepage and 404 html are cached. The plugin will also cache font files (woff, woff2, eot, ttf, otf) and SVG icons.
+
Image Cache
+
If your site has only a few important images, and want them displayed in offline mode, you can cache site images by setting cacheImage: true .
+
We recognize images by file extension. Any files ending with .png, .jpg, .jpeg, .gif, .bmp, .webp will be regarded as images.
+
HTML Cache
+
If you have small sites, and would like to make document fully offline available, you can set cacheHTML to true to cache all HTML files.
+
Why only home and 404 page been cached by default?
To prevent large files from being included in the pre-cache list, any files > 2 MB or images > 1 MB will be omitted. You can customize these limits with maxSize and maxImageSize options (in KB unit).
+
Update Control
+
We provide the update option to control how users receive updates.
+
The default value of the update option is "available", which means that when new content available, the new SW will be installed and its resources will be fetched silently in the background. A pop-up window appears once the new SW is ready, and users can choose whether to refresh immediately to view new content. This means users are reading old content before a new SW is ready.
+
If your project is still in building stage, and you want to alert the user that he may be reading outdated content, you can set this to "hint". This allows users to be notified that new content has been published within seconds after visiting docs. But the negative effect of this is that if the user chooses to update before the new SW is ready, he will need to get all the resources of the page from the internet before the new SW installs and controls the page.
+
If your docs are stable, or you're hosting a blog and don't care much about users receiving the latest version right away, you can set this to "disabled", which means that the new SW will be installed completely silently in the background and start waiting, when all pages controlled by old SW are all closed, the new SW will start to take control and provide users with new content during next visit. This setting can prevent users from being disturbed during the visit.
+
To speed up user access under weak or no network conditions through SW, but also want users to always access new content, you can set this option to "force". This means any old SW will be removed as soon as a new SW is detected, and all pages are refreshed to ensure the user is browsing the latest content. The biggest disadvantage is that all users will experience unexpected sudden refresh within seconds after reentering an updated site.
+
Popups
+
When new content is detected (new SW detected), a update found popup appears; and when the new content is ready, an update ready popup appears.
+
If you are not satisfied with the default popup content, you can use your own component. Import PwaFoundPopup or PwaReadyPopup from @vuepress/plugin-pwa/client and use its slot to customize the popup content, then pass the component path to foundComponent or readyComponent option:
The plugin also provides other PWA-related options, such as Microsoft tile icon and color settings, Apple icon and so on. If you are an advanced user, you can also set generateSwConfig to configure workbox-build. Check Plugin options for more details.
The Service Worker will get and cache all the files registered in it during the registration process.
+
+
+
After the registration complete, the Service Worker is activated, and starts to proxy and control all your requests.
+
+
+
Whenever you want to initiate an access request through the browser, the Service Worker will check whether it exists in its own cache list, if it exists, it will directly return the cached result, otherwise it will call its own fetch method to get it. You can use a custom fetch method to fully control the result of the request for resources in the web page, such as providing a fallback web page when offline.
+
+
+
Every time the user reopens the site, the Service Worker will request to the link when it was registered. If a new version of Service Worker is detected, it will update itself and start caching the list of resources registered in the new Service Worker . After the content update is successfully obtained, the Service Worker will trigger the update event. The user can be notified through this event, for example, a pop-up window will be displayed in the lower right corner, prompting the user that new content is available and allowing the user to trigger an update.
The manifest file uses the JSON format and is responsible for declaring various information of the PWA, such as name, description, icon, and shortcut actions.
+
In order for your site to be registered as a PWA, you need to meet the basic specifications of the manifest to make the browser consider the site as an installable PWA and allow users to install it.
To let the site be registered as a PWA, the site needs to successfully register a valid service worker by itself, and declare a valid manifest file with its link in meta tag.
+
The manifest file should contain at least name (or short_name) iconsstart_url.
+
On safari, the maximum cache size of the service worker is 50 MB. ↩︎↩︎
SPA: Single Page Application, most of them only have the homepage, and use history mode to handle routing instead of actually navigating between pages. ↩︎
You can use this options to edit JSON-LD properties.
+
+
+
customHead
+
+
+
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>.
+
+
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/seo/guide.html
+
+ Guide This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site. Out of Box The plugin works out of the box. Without...
+ This plugin will make your site fully support Open Content Protocol OGP and JSON-LD 1.1 to enhance the SEO of the site.
+
+
Out of Box
+
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:
+
Default OGP Generation
+
The following are the <meta> tags and their value injected into <head> by default to satisfy OGP:
+
| Meta Name | Value |
+| :
+]]>
+
+
+ sitemap
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/
+
+ sitemap
+
+
+
+ Config
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/config.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/config.html
+
+ Config hostname Type: string Required: Yes Details: The domain name where the current site is deployed, the plugin needs this option to work. extraUrls Type: string[] Details: E...
+ hostname
+
+
+
Type: string
+
+
+
Required: Yes
+
+
+
Details:
+
The domain name where the current site is deployed, the plugin needs this option to work.
+
+
+
extraUrls
+
+
+
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/']
+
+
+
excludePaths
+
+
+
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.
+
+
+
devServer
+
+
+
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.
+
+
devHostname
+
+
+
Type: string
+
+
+
Default: "http://localhost:${port}"
+
+
+
Details:
+
Hostname to use in devServer
+
+
+
sitemapFilename
+
+
+
Type: string
+
+
+
Default value: "sitemap.xml"
+
+
+
Details:
+
The output filename, relative to output directory.
Page default update frequency. This will override changefreq in Plugin Options.
+
+
+
sitemap.priority
+
+
+
Type: number
+
+
+
Default: 0.5
+
+
+
Details:
+
Page priority, range from 0 to 1.
+
+
+]]>
+
+
+ Guide
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/sitemap/guide.html
+
+ Guide 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. I...
+ 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.
+
Control Sitemap Link
+
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.
+
Output Location
+
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.
+
Change Frequency
+
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"
+
+
Priority
+
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.
+
Modify Time
+
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();
+})
+
Sitemap Intro
+
Sitemaps provide SEO (Search Engine Optimization):
+
+
Provide search engine spiders with links of the entire site;
+
Provide some links for search engine spiders to dynamic pages or pages that are difficult to reach by other methods;
+
If a visitor attempts to access a URL that does not exist within the site's domain, the visitor will be directed to a "file not found" error page, and the sitemap can be used as a navigation page.
+
+
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: /
+
+]]>
+
+
+ @vuepress/helper
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/
+
+ @vuepress/helper
+
+
+
+ Client Related
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/client.html
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/client.html
+
+ Client Related Composables APIs hasGlobalComponent Check whether a component is registered globally. TIP Local import of the component does not affect the result. When calling o...
+ Composables APIs
+
hasGlobalComponent
+
Check whether a component is registered globally.
+
TIP
+
+
Local import of the component does not affect the result.
+
When calling outside setup scope, you need to pass the app instance as the second parameter.
+]]>
+
+
+ Shared Methods
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/shared.html
+
+ Shared Methods The following functions are available on both Node.js and Client. Data Related Encode/decode and zip/unzip data. This is useful in markdown plugins when you want ...
+ The following functions are available on both Node.js and Client.
+
Data Related
+
Encode/decode and zip/unzip data.
+
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
+
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
+
So we provide encodeData and decodeData to zip and encode content.
getDate(x): Convert input x to a date. It can support Date, timestamp, and date string. The support degree of date string depends on the Date.parse support degree of the environment. Return null when it cannot be converted to a date.
+Example
+
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
+
+
+
dateSorter: Sort the values that can be converted to dates from new to old, and the values that cannot be converted to dates will be at the end.
isLinkWithProtocol(x): Check if x is a valid URL with protocol.
+
isLinkExternal(x): Check if x is a valid external URL.
+
isLinkAbsolute(x): Check if x is a valid absolute URL.
+
ensureEndingSlash(x): Ensure x ends with a slash.
+
ensureLeadingSlash(x): Ensure x starts with a slash.
+
removeEndingSlash(x): Ensure x does not end with a slash.
+
removeLeadingSlash(x): Ensure x does not start with a slash.
+
+]]>
+
+
+ Artalk
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/
+
+ Artalk Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page. Come to your blog, or anywhere, place the Artal...
+ Artalk is a neat self-hosted commenting system that you can easily deploy on your server and put into your front-end page.
+
Come to your blog, or anywhere, place the Artalk comment box, so that the page has rich social functions.
The plugin retains the el option and inserts Artalk itself on the page. At the same time, the plugin will automatically set the pageTitle, pageKey and site options for you according to the VuePress information.
+
+
Darkmode
+
To let Artalk apply the correct theme, you need to pass a boolean value to <CommentService /> through darkmode prop, representing whether the dark mode is currently enabled.
+]]>
+
+
+ Artalk Options
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/config.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/artalk/config.html
+
+ Artalk Options Config See Artalk Configuration for details. The el pageTitle, pageKey and site options are reserved for plugins, they will be inferred from VuePress config. Two ...
+ Config
+
]]>
+
+
+ Giscus
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/
+
+ Giscus Giscus is a commenting system based on GitHub Discussion that is easy to start. Preparation Create a public repository and open discussion panel as a place to store comme...
+ Giscus is a commenting system based on GitHub Discussion that is easy to start.
+
+
Preparation
+
+
+
Create a public repository and open discussion panel as a place to store comments.
+
+
+
Install the Giscus App to have permission to access the corresponding repository.
+
+
+
After completing the above steps, please go to the Giscus page to get your settings.
+
You just need to fill in the repository and Discussion categories, then scroll to the "Enable giscus" section at the bottom of the page and obtain four attributes: data-repo, data-repo-id, data-category and data-category-id.
+
+
+
Config
+
Please set provider: "Giscus" and pass data-repo, data-repo-id, data-category and data-category-id as plugin options as repo, repoId, categorycategoryId.
By default, the theme of Giscus is light or dark (based on darkmode status).
+
Darkmode
+
To let Giscus apply the correct theme, you need to pass a boolean value to <CommentService /> via darkmode property, indicating whether darkmode is currently enabled.
+
+
If you want to customize theme in lightmode and darkmode, you can set lightTheme and darkTheme option with a built-in theme keyword or a custom CSS link starting with https://.
+]]>
+
+
+ Giscus Options
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/config.html
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/giscus/config.html
+
+ Giscus Options Config repo Type: string Details: The name of repository to store discussions. repoId Type: string Details: The ID of repository to store discussions. Generate th...
+ Config
+
repo
+
+
Type: string
+
Details: The name of repository to store discussions.
+
+
repoId
+
+
Type: string
+
Details:
+The ID of repository to store discussions. Generate through Giscus Page
+
+
category
+
+
Type: string
+
Details:
+The name of the discussion category.
+
+
categoryId
+
+
Type: string
+
Details:
+The ID of the discussion category. Generate through Giscus Page
+
+
mapping
+
+
Type: string
+
Default: "pathname"
+
Details:
+Page - Discussion mapping. For details see Giscus Page
]]>
+
+
+ Twikoo
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/twikoo/
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/twikoo/
+
+ Twikoo A concise, safe and free static site commenting system, based on Tencent Cloud Development. Install Getting started Apply for MongoDB account Create a free MongoDB databa...
+ A concise, safe and free static site commenting system, based on Tencent Cloud Development.
+
+
Create a free MongoDB database, the recommended region is AWS / N. Virginia (us-east-1)
+
+
+
Click CONNECT on the Clusters page, follow the steps to allow connections from all IP addresses (Why?), create Database user, and record the database connection string, please change the <password> in the connection string to the database password
Click the button below to deploy Twikoo to Vercel in one click
+
+
+
+
Go to Settings - Environment Variables, add the environment variable MONGODB_URI, the value is the database connection string in step 3
+
+
+
Go to Overview, click the link under Domains, if the environment configuration is correct, you can see the prompt "Twikoo cloud function is running normally"
+
+
+
Vercel Domains (with https:// prefix, e.g. https://xxx.vercel.app) is your environment ID
+
+
+
Configuration
+
Please set provider: "Twikoo" and set envId in the plugin options.
]]>
+
+
+ Waline
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/
+ https://ecosystem.vuejs.press/ecosystem/plugins/comment/waline/
+
+ Waline A safe comment system with backend. Install LeanCloud Settings (Database) sign in or sign up LeanCloud and enter Console. Click Create app button to create a new app and ...
+ A safe comment system with backend.
+
+
Click Create app button to create a new app and enter a name you like:
+
+
+
+
Enter the app, then select Settings > App Keys at the left bottom corner. You will see APP ID, APP Key and Master Key of your app. We will use them later
+
+
+
+
Deploy to Vercel (Server)
+
+
+
+
Click the dark button above, it will redirect you to vercel to deploy with waline template.
+
TIP
+
If you haven't logged in, we recommend you to sign in with GitHub.
+
+
+
+
Input your Vercel project name then click Create.
+
+
+
+
Repo which named you input before will be created and initialized automatically base on waline example template by Vercel.
+
+
After one minute or two, vercel should finish the deployment. Click Go to Dashboard button to redirect to your application dashboard.
+
+
+
+
Click Settings menu on the top, and Environment Variables button on the side to go to environment variables setting page. Then set LEAN_ID, LEAN_KEY and LEAN_MASTER_KEY. The variables' value should be the ones you got in the previous step. APP ID is the value of LEAN_ID, and APP Key to LEAN_KEY, Master Key to LEAN_MASTER_KEY.
+
+
+
+
To let your environment variables setting active, you need redeploy your application. Click Deployments menu on the top and find the latest deployment at the top of list, click Redeploy button in the right dropdown menu.
+
+
+
+
If everything is ok, vercel will redirect to Overview page to start redeployment. Wait a moment the STATUS will change to Ready. Now you can click Visit to visit the site. This link is your server address.
+
+
+
+
Assign Domain (Optional)
+
+
+
Click Settings - Domains to go to domain setting page.
+
+
+
Input domain you want to assign and click Add button.
+
+
+
+
Add a new CNAME record in your domain service server.
Code highlighting, use hanabi by default. The function passes in original content of code block and language of the code block. You should return a string directly.
+
You can pass in a code highlighter of your own, or set to false to disable code highlighting.
+
+
+
texRenderer
+
+
+
Type: WalineTexRenderer | false
+
type WalineTexRenderer = (blockMode: boolean, tex: string) => string
+
Customize TeX rendering, the default behavior is to prompt that the preview mode does not support TeX. The function provides two parameters, the first parameter indicates whether it should be rendered in block level, and the second parameter is the string of the TeX content, and return a HTML string as render result.
+
You can import TeX renderer to provide preview feature. We recommend you to use Katex or MathJax, or you can set to false to disable parsing TeX.
+
+
+
search
+
+
+
Type: WalineSearchOptions | false
+
interface WalineSearchImageData extends Record<string, unknown> {
+ /**
+ * Image link
+ */
+ src: string
+
+ /**
+ * Image title
+ *
+ * @description Used for alt attribute of image
+ */
+ title?: string
+
+ /**
+ * Image preview link
+ *
+ * @description For better loading performance, we will use this thumbnail first in the list
+ *
+ * @default src
+ */
+ preview?: string
+}
+
+type WalineSearchResult = WalineSearchImageData[]
+
+interface WalineSearchOptions {
+ /**
+ * Search action
+ */
+ search: (word: string) => Promise<WalineSearchResult>
+
+ /**
+ * Default result when opening list
+ *
+ * @default () => search('')
+ */
+ default?: () => Promise<WalineSearchResult>
+
+ /**
+ * Fetch more action
+ *
+ * @description It will be triggered when the list scrolls to the bottom. If your search service supports paging, you should set this to achieve infinite scrolling
+ *
+ * @default (word) => search(word)
+ */
+ more?: (word: string, currentCount: number) => Promise<WalineSearchResult>
+}
+
+
+
Details: Customize search features, you can disable search function by setting it to false.
+
+
+
recaptchaV3Key
+
+
+
Type: string
+
+
+
Details:
+
reCAPTCHA V3 is a captcha service provided by Google. You can add reCAPTCHA V3 site key with recaptchaV3Key to enable it.
+
You should also set environment variable RECAPTCHA_V3_SECRET for server.
+
+
+
reaction
+
+
+
Type: boolean | string[]
+
+
+
Default: false
+
+
+
Details:
+
Add emoji interaction function to the article, set it to true to provide the default emoji, you can also customize the emoji image by setting the emoji url array, and supports a maximum of 8 emojis.
]]>
+
+
+ Bundler Related
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/bundler.html
+
+ Bundler Related Bundler function is for appending or modifying bundler options in theme and plugins. All functions should be called in extendsBundlerOptions lifecycle hook. TIP ...
+ Bundler function is for appending or modifying bundler options in theme and plugins.
+
All functions should be called in extendsBundlerOptions lifecycle hook.
+
TIP
+
We are omitting that in examples. The actual code should be like this:
+
// import functions you need
+import { addCustomElement } from '@vuepress/helper'
+
+export const yourPlugin = {
+ // ...
+ extendsBundlerOptions: (bundlerOptions, app) => {
+ // add them here
+ addCustomElement(bundlerOptions, app, 'my-custom-element')
+ },
+}
+
import { configWebpack } from '@vuepress/helper'
+
+configWebpack(bundlerOptions, app, (config, isServer, isBuild) => {
+ // do some customize here
+})
+
+
+
+]]>
+
+
+ Page Related
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html
+ https://ecosystem.vuejs.press/ecosystem/tools/helper/node/page.html
+
+ Page Related These functions generate common information for your pages. getPageExcerpt Get the excerpt of the page. getPageText Get plain text of the page.
+ These functions generate common information for your pages.
+
getPageExcerpt
+
Get the excerpt of the page.
+
export interface PageExcerptOptions {
+ /**
+ * Excerpt separator
+ *
+ * @default "<!-- more -->"
+ */
+ separator?: string
+
+ /**
+ * Length of excerpt
+ *
+ * @description Excerpt length will be the minimal possible length reaching this value
+ *
+ * @default 300
+ */
+ length?: number
+
+ /**
+ * Tags which is considered as custom elements
+ *
+ * @description This is used to determine whether a tag is a custom element since all unknown tags are removed in excerpt.
+ */
+ isCustomElement?: (tagName: string) => boolean
+
+ /**
+ * Whether keep page title (first h1) in excerpt
+ *
+ * @default false
+ */
+ keepPageTitle?: boolean
+
+ /**
+ * Whether preserve tags like line numbers and highlight lines for code blocks
+ *
+ * @default false
+ */
+ keepFenceDom?: boolean
+}
+
+export const getPageExcerpt: (
+ app: App,
+ page: Page,
+ options?: PageExcerptOptions,
+) => string
+
getPageText
+
Get plain text of the page.
+
export interface PageTextOptions {
+ /**
+ * Whether convert text to single line content
+ *
+ * @default false
+ */
+ singleLine?: boolean
+
+ /**
+ * Length of text
+ *
+ * @description Text length will be the minimal possible length reaching this value
+ *
+ * @default 300
+ */
+ length?: number
+
+ /**
+ * Tags to be removed
+ *
+ * @description Table and code blocks are removed by default.
+ *
+ * @default ['table', 'pre']
+ */
+ removedTags?: string[]
+}
+
+export const getPageText: (
+ app: App,
+ page: Page,
+ options?: PageTextOptions,
+) => string
+
]]>
+
+
+
\ No newline at end of file
diff --git a/rss.xsl b/rss.xsl
new file mode 100644
index 0000000000..972565991d
--- /dev/null
+++ b/rss.xsl
@@ -0,0 +1,506 @@
+
+
+
+
+
+
+ RSS Feed
+
+
+
+
+
+
+
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.
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:
A NavbarItem object should have a text field and a link field, could have an optional activeMatch field.
A NavbarGroup object should have a text field and a children field. The children field should be a navbar array, too.
A string should be the path to the target page file. It will be converted to a NavbarItem object, using the page title as text, and the page route path as link.
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',
+ }),
+}
+
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:
A 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.
A string should be the path to the target page file. It will be converted to a 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:
The key should be the path prefix.
The value should be a sidebar array or set to 'heading' to automatically generate the sidebar from the page headers for just the corresponding path.
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.
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.
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.
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.
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.
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',
+ ),
+ },
+ }
+}
+
---
+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.
+---
+
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:
A NavLink object should have a text field and a link field.
A string should be the path to the target page file. It will be converted to a NavLink object, whose text is the page title, and link is the page route path.
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.
::: 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
Example 2 (custom title):
Input
::: danger STOP
+Danger zone, do not proceed
+:::
+
+::: details Click me to view the code
+
+```ts
+console.log('Hello, VuePress!')
+```
+
+:::
+
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.
This is useful in markdown plugins when you want to encode string content and pass it to the component through props.
You may simply achieve this with encodeURIComponent and decodeURIComponent, but it can be very large if the content contains lots of special characters.
So we provide encodeData and decodeData to zip and encode content.
getDate(x): Convert input x to a date. It can support Date, timestamp, and date string. The support degree of date string depends on the Date.parse support degree of the environment. Return null when it cannot be converted to a date.
Example
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
dateSorter: Sort the values that can be converted to dates from new to old, and the values that cannot be converted to dates will be at the end.
getDate(x): 将输入 x 转换为日期,可以支持 Date,时间戳,日期字符串。日期字符串的支持度以环境的 Date.parse 支持度为准。当不能转换为日期时返回 null
+示例
+
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
getDate(x): 将输入 x 转换为日期,可以支持 Date,时间戳,日期字符串。日期字符串的支持度以环境的 Date.parse 支持度为准。当不能转换为日期时返回 null
\n示例\n
getDate('2021-01-01') // a Date object represents 2021-01-01\ngetDate(1609459200000) // a Date object represents 2021-01-01\ngetDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01\ngetDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)\ngetDate('invalid date') // null\ngetDate(undefined) // null\ngetDate(-32) // null\n
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;
+}
+
getDate(x): 将输入 x 转换为日期,可以支持 Date,时间戳,日期字符串。日期字符串的支持度以环境的 Date.parse 支持度为准。当不能转换为日期时返回 null
+示例
+
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+
getDate(x): 将输入 x 转换为日期,可以支持 Date,时间戳,日期字符串。日期字符串的支持度以环境的 Date.parse 支持度为准。当不能转换为日期时返回 null
示例
getDate('2021-01-01') // a Date object represents 2021-01-01
+getDate(1609459200000) // a Date object represents 2021-01-01
+getDate('2021-01-01T00:00:00.000Z') // a Date object represents 2021-01-01
+getDate('2021/01/01') // a Date object represents 2021-01-01 (might be null in some browsers)
+getDate('invalid date') // null
+getDate(undefined) // null
+getDate(-32) // null
+