diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..77ad0ec --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,48 @@ +# @vuepress/plugin-blog + +> VuePress 的官方博客插件。 + +## 特性 + +- [**分类器**](https://vuepress-plugin-blog.ulivz.com/zh/guide/getting-started.html#文档分类器): + 强大的分类系统可让你快速对帖子进行分类。 +- [**分页**](https://vuepress-plugin-blog.ulivz.com/zh/guide/getting-started.html#分页): + 分页贯穿整个插件,它从未如此简单。 +- [**客户端 API**](https://vuepress-plugin-blog.ulivz.com/zh/client-api/):简单的客户端 API 使你可以更轻松地编写博客主题。 + +## 安装 + +我们强烈建议你在使用此插件之前阅读 [Getting Started](https://vuepress-plugin-blog.ulivz.com/guide/getting-started.html) 部分。 + +```bash +yarn add -D @vuepress/plugin-blog +# OR npm install -D @vuepress/plugin-blog +``` + +## 使用 + +```javascript +module.exports = { + plugins: ['@vuepress/blog'] +}; +``` + +请转到 [文档](https://vuepress-theme-blog.ulivz.com/zh/) 查看所有可用选项。 + +## 正在使用 `@vuepress/plugin-blog` 的项目 + +- [70-lines-of-vuepress-blog-theme](https://github.com/ulivz/70-lines-of-vuepress-blog-theme): 大约 70 行实现的 VuePress 博客主题。 +- [@vuepress/theme-blog](https://github.com/ulivz/vuepress-theme-blog): VuePress 的默认博客主题。 +- [vuepress-theme-modern-blog](https://github.com/z3by/vuepress-theme-modern-blog): 一个使用 [Element.UI 设计系统](https://element.eleme.io/#/) 的现代主题 +- [vuepress-theme-reco](https://github.com/vuepress-reco/vuepress-theme-reco) - 一个简单美观的 vuepress 博客主题 +- [vuepress-theme-yuchanns](https://github.com/yuchanns/vuepress-theme-yuchanns): 一个 Github 风格的 vuepress 博客主题 +- [vuepress-theme-ic](https://github.com/IKangXu/vuepress-theme-ic) :tada::tada::tada: 笔记样式的vuepress博客主题,具有简单,清晰和实用的功能。最浅的墨水比最好的记忆好。 +- [vuepress-theme-hope](https://vuepress-theme.mrhope.site/): :zap: 一个轻量的 vuepress 主题 + +随时在这里添加你的主题... + +## 作者 + +**@vuepress/theme-blog** © [ULIVZ](https://github.com/ulivz), 在 [MIT](./LICENSE) 许可证下发布。
+ +> [github.com/ulivz](https://github.com/ulivz) · GitHub [@ULIVZ](https://github.com/ulivz) · Twitter [@\_ulivz](https://twitter.com/_ulivz) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 26b2198..5c59aee 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -1,5 +1,15 @@ module.exports = { title: '@vuepress/plugin-blog', + description: 'Offical blog plugin for VuePress', + locales: { + '/': { + lang: 'en-US', + }, + '/zh/': { + lang: 'zh-CN', + description: 'Vuepress 官方博客插件', + }, + }, description: 'Official blog plugin for VuePress', themeConfig: { repo: 'vuepressjs/vuepress-plugin-blog', @@ -12,7 +22,7 @@ module.exports = { { text: 'Pagination', link: '/pagination/' }, { text: 'Client API', link: '/client-api/' }, { text: 'Components', link: '/components/' }, - { text: 'FAQ', link: '/faq/' } + { text: 'FAQ', link: '/faq/' }, ], sidebarDepth: 3, sidebar: { @@ -21,14 +31,36 @@ module.exports = { title: 'Guide', collapsable: false, - children: [ - '', - 'getting-started', - ], + children: ['', 'getting-started'], }, ], }, + locales: { + '/': { + label: 'English', + }, + '/zh/': { + nav: [ + { text: '指南', link: '/zh/guide/' }, + { text: '配置', link: '/zh/config/' }, + { text: '分页', link: '/zh/pagination/' }, + { text: '客户端 API', link: '/zh/client-api/' }, + { text: '组件', link: '/zh/components/' }, + { text: 'FAQ', link: '/zh/faq/' }, + ], + sidebar: { + '/zh/guide/': [ + { + title: '指南', + collapsable: false, + children: ['', 'getting-started'], + }, + ], + }, + selectText: '选择语言', + label: '简体中文', + }, + }, smoothScroll: true, }, } - diff --git a/docs/zh/README.md b/docs/zh/README.md new file mode 100644 index 0000000..6b0b2ad --- /dev/null +++ b/docs/zh/README.md @@ -0,0 +1,38 @@ +--- +home: true +heroImage: +actionText: 快速上手 → +actionLink: /zh/guide/ +features: + - title: 分类 + details: 强大的分类系统可让你快速对帖子进行分类。 + - title: 分页 + details: 分页贯穿整个插件,它从未如此简单。 + - title: 客户端 API + details: 简单的客户端 API 使你可以更轻松地编写博客主题。 + +footer: MIT Licensed | Copyright © 2019-present ULIVZ +--- + +## 安装 + +```bash +yarn add -D @vuepress/plugin-blog +# OR npm install -D @vuepress/plugin-blog +``` + +## 使用 + +```javascript +// .vuepress/config.js +module.exports = { + plugins: [ + '@vuepress/blog', + { + /* options */ + }, + ], +} +``` + +[这里](./config/README.md) 可以找到所有可用的选项. diff --git a/docs/zh/client-api/README.md b/docs/zh/client-api/README.md new file mode 100644 index 0000000..e2fe220 --- /dev/null +++ b/docs/zh/client-api/README.md @@ -0,0 +1,141 @@ +--- +sidebar: auto +--- + +# 客户端 API + +::: tip +我们强烈建议你在使用此插件之前阅读 [快速上手](../guide/getting-started.md) 部分。 +::: + +## $pagination + +::: warning +请注意,如果你在与任何分类都不匹配的路由上访问 `$pagination` , `$pagination` 的值将为 `null` 。 + +因此,当你开发布局组件时,你需要验证 `$pagination` 是否存在。 +::: + +### `$pagination.pages` + +当前路由的匹配页面。例如: + +```json +[ + { "relativePath": "b.md", "path": "/b.html" ... }, + { "relativePath": "a.md", "path": "/a.html" ... }, +] +``` + +### `$pagination.length` + +当前分页的长度。 + +### `$pagination.hasPrev` + +是否存在上一个分页。 + +### `$pagination.prevLink` + +上一个分页的链接。 + +### `$pagination.hasNext` + +是否存在下一个分页。 + +### `$pagination.nextLink` + +下一个分页的链接。 + +### `$pagination.getSpecificPageLink` + +通过页码获取特定的分页页面。 + +::: tip +你可以使用此功能将分页组件自定义为内部 [``](../components/#pagination) 组件。 +::: + +## $frontmatterKey + +如果你按照以下方式创建 [Frontmatter 分类器](../guide/getting-started.md#frontmatter-分类器): + +```js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + frontmatters: [ + { + // 当前分类的唯一 ID + id: 'tag', + // 决定将 frontmatter 键值归到该类别下 + keys: ['tag'], + // `entry page` (或者 `list page`) 的路径 + path: '/tag/', + // `entry page` 的布局 + layout: 'Tag', + }, + ], + }, + ], + ], +} +``` + +那么此插件将向 Vue 原型注入 `$frontmatterKey` 对象, ,因此你可以在自己的布局组件 (``) 上直接使用它。 + +### `$frontmatterKey.list` + +获取一个含有匹配的 frontmatter 分类器类型的列表。 + +接口如下: + +```typescript +type FrontmatterKeyList = Array<{ + name: string + path: string + pages: Array +}> +``` + +你可以重新阅读 [Frontmatter 分类器](../guide/getting-started.md#frontmatter-分类器) 来观看 `tag` 的真实示例。 + +::: tip 多个 Frontmatter 分类器 + +如果你创建两个 Frontmatter 分类器,例如 `tag` 和 `category`,那么在 `/tag/` 路由中,`$frontmatterKey` 自动指向 `tag` ,而在 `/category/` 中,它将指向 `category`。 + +此变量本质上是设计用于概括 frontmatter 键的列表页面。 +::: + +## $service + +### $service.comment + +#### `$ service.comment.enabled` + +是否启用评论。 + +#### `$ service.comment.service` + +获取评论服务 + +### $service.email + +#### `$service.email.enabled` + +是否启用电子邮件(新闻通讯)服务。 + +### $service.feed + +#### `$service.feed.rss` + +是否启用 RSS feed。 + +#### `$service.feed.atom` + +是否启用了 Atom feed。 + +#### `$service.feed.json` + +是否启用 JSON feed。 diff --git a/docs/zh/components/README.md b/docs/zh/components/README.md new file mode 100644 index 0000000..e4ab89e --- /dev/null +++ b/docs/zh/components/README.md @@ -0,0 +1,110 @@ +--- +sidebar: auto +--- + +# 组件 + +为了更好地享受此插件的便利,该插件提供了一些现成的组件。 + +## `` + +- 源代码: [SimplePagination.vue](https://github.com/ulivz/vuepress-plugin-blog/blob/master/src/client/components/SimplePagination.vue) +- 使用: + +```vue + + + +``` + +- 输出: + + + +::: tip +你可以在 [palette.styl](https://v1.vuepress.vuejs.org/config/#palette-styl) 使用 `$accentColor` 来调整该组件的默认颜色。 +::: + +## `` + +- 源代码: [Pagination.vue](https://github.com/ulivz/vuepress-plugin-blog/blob/master/src/client/components/Pagination.vue) +- 使用: + +```vue + + + +``` + +- 输出: + + + +::: tip +你可以在 [palette.styl](https://v1.vuepress.vuejs.org/config/#palette-styl) 使用 `$accentColor` 来调整该组件的默认颜色。 +::: + +## `` + +该组件将自动渲染你选择的评论服务内容。如果未启用评论,则不会渲染任何内容。 + +- 源代码:[Comment.vue](ttps://github.com/ulivz/vuepress-plugin-blog/blob/master/src/client/components/Comment.vue) + +- 用法: + +```vue + + + +``` + +- 输出: + + - Disqus: + + - Vssue: + +## `` + +由 [vuepress-plugin-mailchimp](https://github.com/newsbielt703/vuepress-plugin-mailchimp) 实现 + +- 源代码: [SimpleNewsletter.vue](https://github.com/newsbielt703/vuepress-plugin-mailchimp/blob/master/src/components/SimpleNewsletter.vue) + +- 用法: + +```vue + +``` + +- 输出: + + diff --git a/docs/zh/config/README.md b/docs/zh/config/README.md new file mode 100644 index 0000000..dfdc81c --- /dev/null +++ b/docs/zh/config/README.md @@ -0,0 +1,260 @@ +--- +sidebar: auto +--- + +# 配置 + +::: tip +我们强烈建议你在使用此插件之前阅读 [快速入门](../guide/getting-started.md) 部分。 +::: + +## directories + +- 类型: `DirectoryClassifier[]` +- 默认值: `[]` + +创建一个或多个 [目录分类器](../guide/getting-started.md#目录分类器),所有位于 `DirectoryClassifier` 可用选项如下。 + +### id + +- 类型: `string` +- 默认值: `undefined` +- 必填: 是 + +当前分类器的唯一 ID,例如 `post`. + +### dirname + +- 类型: `string` +- 默认值: `undefined` +- 必填: 是 + +匹配的目录名称,例如 `_post`. + +### path + +- 类型: `string` +- 默认值: `` `/${id}/` `` +- 必填: 否 + +当前分类器的输入页面,例如 `/` 或者 `/post/`. + +如果你将 `DirectoryClassifier.path` 设置为 `/`, 则意味着你要访问在 `/` 列出的处的匹配页面列表。设置到 `/post/` 也是一样的。 + +### title + +- 类型: `string` +- 默认值: `id` +- 必填: 否 + +当前分类器的条目和分页页面标题。 + +### layout + +- 类型: `string` +- 默认值: `'IndexPost' || 'Layout'` +- 必填: 否 + +入口页面的布局组件名称。 + +### frontmatter + +- 类型: `Record` +- 默认值: `{}` +- 必填: 否 + +整个页面的 [Frontmatter](https://v1.vuepress.vuejs.org/zh/guide/frontmatter.html)。 + +### itemLayout + +- 类型: `string` +- 默认值: `'Post'` +- 必填: 否 + +匹配页面的布局。 + +### itemPermalink + +- 类型: `string` +- 默认值: `'/:year/:month/:day/:slug'` +- 必填: 否 + +匹配页面的永久链接。 + +例如,如果你设置的目录分类器的目录名为 `_post` ,并且具有以下页面: + +``` +. +└── _posts + ├── 2018-4-4-intro-to-vuepress.md + └── 2019-6-8-intro-to-vuepress-next.md +``` + +保持默认的 `itemPermalink`, 你将获得以下输出路径: + +``` +/2018/04/04/intro-to-vuepress/ +/2019/06/08/intro-to-vuepress-next/ +``` + +有关 **永久链接** 的更多详细信息,请转到 VuePress 文档中的 [永久链接](https://v1.vuepress.vuejs.org/zh/guide/permalinks.html) 部分 + +### pagination + +- 类型: `Pagination` +- 默认值: `{ lengthPerPage: 10 }` +- 必填: 否 + +请转到 [分页配置](../pagination/README.md) 部分以获取所有可用选项。 + +## frontmatters + +### id + +- 类型: `string` +- 默认值: `undefined` +- 必填: 是 + +当前分类器的唯一 ID,例如 `tag`。 + +### keys + +- 类型: `string` +- 默认值: `undefined` +- 必填: 是 + +用于对页面进行分类的 Frontmatter 键值。 + +你还可以合并具有相同含义的多个标签,例如: + +```js +module.exports = { + plugins: [ + ['@vuepress/plugin-blog',{ + frontmatters: [ + { + id: 'tag', + keys: ['tag', 'tags'], + }, + ], + }], + ], +} +``` + +### path + +- 类型: `string` +- 默认值: `` `/${id}/` `` +- 必填: 否 + +当前分类的入口页面,例如 `/` 或 `/post/`。 + +### title + +- 类型: `string` +- 默认值: `id` +- 必填: 否 + +当前分类器的条目和分页页面标题。 + +### layout + +- 类型: `string` +- 默认值: `'IndexPost' || 'Layout'` +- 必填: 否 + +入口页面的布局组件名称。 + +### frontmatter + +- 类型: `Record` +- 默认值: `{}` +- 必填: 否 + +整个页面的 [Frontmatter](https://v1.vuepress.vuejs.org/guide/frontmatter.html)。 + +### pagination + +- 类型: `Pagination` +- 默认值: `{ lengthPerPage: 10 }` +- 必填: 否 + +它可以覆盖 [globalPagination](./#globalpagination). + +请转到 [分页配置](../pagination/README.md#config) 章节以获取所有可用选项。 + +## globalPagination + +所有目录和前题的分页配置。 + +- 类型: `Pagination` +- 默认值: `{}` +- 必填: 否 + +请转到 [分页配置](../pagination/README.md#config) 章节以获取所有可用选项。 + +## sitemap + +- 类型: `object` +- 默认值: `{}` +- 必填: 否 + +当提供 `hostname` 时,它将被启用。 例如 + +```js +{ + hostname: 'https://yourdomain' +} +``` + +默认情况下不包括 404 页。 更多选项,请前往 [vuepress-plugin-sitemap](https://github.com/ekoeryanto/vuepress-plugin-sitemap#options)。 + +## 评论 + +### service + +评论服务提供: + +- 类型: `'vssue' | 'disqus'` +- 默认值: `undefined` +- 必填: 否 + +### 其他选项 + +其他选项取决于你选择的服务,因为此功能由以下插件完成。 除了 `service` 之外的所有选项都将直接传递给插件,因此请查看其文档以获取更多详细信息: + +- [vuepress-plugin-disqus](https://github.com/lorisleiva/vuepress-plugin-disqus) +- [vuepress-plugin-vssue](https://vssue.js.org/guide/vuepress.html#usage) + +## newsletter + +- 类型: `object` +- 默认值: `{}` +- 必填: 否 + +当提供 `endpoint` 时,它将被启用。 例如: + +```js +{ + endpoint: 'https://billyyyyy3320.us4.list-manage.com/subscribe/post?u=4905113ee00d8210c2004e038&id=bd18d40138' +} +``` + +[vuepress-plugin-mailchimp](https://vuepress-plugin-mailchimp.billyyyyy3320.com/) 是我们实现此功能的方式。 此配置将直接传递给它,因此请访问[vuepress-plugin-mailchimp](https://vuepress-plugin-mailchimp.billyyyyy3320.com/#config) 以获取更多详细信息。 + +## feed + +- 类型: `object` +- 默认值: `{}` +- 必填: 否 + +当提供 `canonical_base` 时将启用它。 例如 + +```js +{ + canonical_base: 'https://yoursite' +} +``` + +所有生成的文件将放置在你的输出目录下。 如果你希望进行进一步的配置,请查看 [vuepress-plugin-feed](https://github.com/webmasterish/vuepress-plugin-feed) diff --git a/docs/zh/faq/README.md b/docs/zh/faq/README.md new file mode 100644 index 0000000..d9f7b03 --- /dev/null +++ b/docs/zh/faq/README.md @@ -0,0 +1,23 @@ +--- +sidebar: auto +--- + +# 常见问题 + +## `@vuepress/plugin-blog` 和 `@vuepress/theme-blog` 有什么区别? + +VuePress 的默认主题侧重于文档站点,因此提供适当的博客支持应当在另一个单独的主题中。 + +我们希望为开发人员提供默认的博客主题,并且鼓励社区主题的开发。该插件系统是在 VuePress 1.x 发布时引入的。其目的是去耦和可重用。因此,我们尝试在插件中实现所有常见和必要的博客功能,并更加关注主题中的交互体验。 + +使用博客主题,你可以在几分钟之内完成博客设置,并专注于内容。使用博客插件,你可以通过专注于用户界面来开发自己的主题,而无需了解幕后逻辑。 + +> 这是不可见的,用户不感兴趣。 + +## 为什么此插件中有几个插件? + +这是一个多合一的插件,所有通用和必要的功能都在一个插件中实现。我们不希望你花费大量时间寻找可用的插件,也不想重新造轮子。 + +你只需要安装此插件,而不用安装 `yarn add -D @vuepress/plugin-blog vuepress-plugin-sitemap vuepress-plugin-mailchimp vuepress-plugin-disqus` 之类的插件。当然,你可能不需要某些插件。不用担心,如果你不启用它们,它们将永远不会被使用。 + +此外,我们将一些功能提取到插件中,因为它们不仅可以被博客使用,还可以有其他用途。 diff --git a/docs/zh/guide/README.md b/docs/zh/guide/README.md new file mode 100644 index 0000000..2e93cb3 --- /dev/null +++ b/docs/zh/guide/README.md @@ -0,0 +1,14 @@ +# 介绍 + +[VuePress](https://v1.vuepress.vuejs.org/zh/) 是由 Vue 驱动的可扩展静态网站生成器,其创建目的是为了满足 Vue 子项目的文档需求。 + +后来,引入 [插件系统](https://v1.vuepress.vuejs.org/zh/plugin/)的 VuePress 1.x 大幅度地增強了 VuePress 的可扩展性。本项目是一個 VuePress 插件,由 VuePress 1.x 的作者创建,其目的是盡可能地降低 VuePress 博客主题的开发成本。 + +请注意,本插件已深入集成到 [@vuepress/theme-blog](https://github.com/ulivz/vuepress-theme-blog). + +为了了解本插件的用法,我们建议你先对于 VuePress 有些认识 ,而使用过 VuePress 的话更好。你可以通过以下方式了解 VuePress 1.x: + +- [VuePress 1.x 的文档](https://v1.vuepress.vuejs.org/zh/) +- [medium - VuePress 1.x 的介绍](https://medium.com/@_ulivz/intro-to-vuepress-1-x-7e2b7885f95f) + +如果你准备好了,就让我们一起 [快速上手](./getting-started.md) 吧。 diff --git a/docs/zh/guide/getting-started.md b/docs/zh/guide/getting-started.md new file mode 100644 index 0000000..00d4d5d --- /dev/null +++ b/docs/zh/guide/getting-started.md @@ -0,0 +1,500 @@ +# 快速入门 + +::: tip +本部分是包含一些概念的分步教程,并且我们建议你在使用前这个插件前完整阅读它。 +::: + +## 文档分类器 (`Document classifier`) + +`Document classifier` 是一组功能,可以对具有相同特征的页面进行分类。对于博客开发人员,不同页面之间可能存在相同的特征,如下所示: + +- 放在目录中的页面 (例如 `_post`) +- 包含相同的特定 frontmatter 值的页面 (例如 `tag: js`). + +当然,它们都可能与另一个通用要求 “分页”(`pagination`) 有关。 + +那么,如何巧妙地将它们组合在一起?接下来,让我们看一下该插件如何解决这些问题。 + +## 目录分类器 + +目录分类器,会对用于对放置在同一目录中的源页面进行分类。 + +假设你具有以下文件结构: + +``` +. +└── _posts + ├── 2018-4-4-intro-to-vuepress.md + └── 2019-6-8-intro-to-vuepress-next.md +``` + +在传统的 VuePress 网站中,转换后的页面 URL 为: + +- `_posts/2018-4-4-intro-to-vuepress.html` +- `_posts/2019-6-8-intro-to-vuepress-next.html` + +似乎没有按照博客组织,因此是时候使用此插件了: + +```js +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + directories: [ + { + // 当前分类的唯一 ID + id: 'post', + // 目标文件夹 + dirname: '_posts', + // `entry page` (或者 `list page`) 的路径 + path: '/', + }, + ], + }, + ], + ], +} +``` + +然后,该插件将帮助你生成以下页面,并自动利用相应的页面布局: + +| 页面地址 | 布局 | +| ------------------------------------- | ---------------------------------------------------- | +| `/` | `IndexPost` (回退到 `Layout` 如果不存在 `IndexPost`) | +| `/2018/04/04/intro-to-vuepress/` | `Post` | +| `/2019/06/08/intro-to-vuepress-next/` | `Post` | + +这意味着你需要创建两个布局组件 (`IndexPost` and `Post`) 来处理 `index` 和 `post` 页面的布局。 + +你还可以自定义布局组件: + +```diff +// .vuepress/config.js +module.exports = { + plugins: [ + ['@vuepress/blog', { + directories: [ + { + id: 'post', + dirname: '_posts', + path: '/', ++ layout: 'MyIndexPost', ++ itemLayout: 'MyPost', + }, + ], + }] + ] +} +``` + +并自定义入口页面的路径和帖子的永久链接: + +```diff +// .vuepress/config.js +module.exports = { + plugins: [ + ['@vuepress/blog', { + directories: [ + { + id: 'post', + dirname: '_posts', +- path: '/', ++ path: '/post/', ++ itemPermalink: '/post/:year/:month/:day/:slug', + }, + ], + }] + ] +} +``` + +::: warning +值得注意的是,`path` 和 `itemPermalink` 必须统一修改,并且 `itemPermalink` 必须带有前缀 `path`。 + +`itemPermalink` 的默认值为 `'/:year/:month/:day/:slug'`。 +::: + +**也可以详见**: + +- [配置 > 目录](../config/README.md#directories) + +## 分页 + +随着你的博客文章越来越多,你开始需要分页。默认情况下,此插件集成了一个非常强大的分页系统,使你可以通过简单的配置访问分页功能。 + +默认情况下,插件假定每页的最大页面数为 `10` 。你也可以像这样修改它: + +```diff +// .vuepress/config.js +module.exports = { + plugins: [ + ['@vuepress/blog', { + directories: [ + { + id: 'post', + dirname: '_posts', + path: '/', ++ pagination: { ++ lengthPerPage: 2, ++ }, + }, + ], + }] + ] +} +``` + +假设你在 `_posts` 目录中有 3 个页面: + +- `_posts/2018-6-8-a.md` +- `_posts/2019-6-8-b.md` +- `_posts/2019-6-8-c.md` + +当 `lengthPerPage` 选项被设置为 `2`,此插件将帮助你生成以下页面: + +| url | layout | +| ---------------- | --------------------------------------------------------- | +| `/` | `IndexPost` (fallback to `Layout` if not exist) | +| `/page/2/` (New) | `DirectoryPagination` (fallback to `Layout` if not exist) | +| `/2019/06/08/a/` | `Post` | +| `/2019/06/08/b/` | `Post` | +| `/2018/06/08/c/` | `Post` | + +那么如何在布局组件中获取匹配的页面呢?实际上,它将比你想象的简单得多。 + +如果你访问 `/`,则当前页面会使用布局 `IndexPost`。在此布局组件中,你只需要使用 `this.$pagination.pages` 即可获取匹配的页面。在上面的示例中,`this.$pagination.pages` 的实际值将为: + +```json +[ + { "relativePath": "_posts/2019-6-8-a.md", "path": "/2019/06/08/a/" ... }, + { "relativePath": "_posts/2019-6-8-b.md", "path": "/2019/06/08/b/" ... }, +] +``` + +如果你访问`/`,则当前页面会使用布局 `DirectoryPagination` ,你也可以使用 `this。$pagination.pages` 来访问它: + +```json +[ + { "relativePath": "_posts/2019-6-8-c.md", "path": "/2019/06/08/c/" ... }, +] +``` + +这难道不是很自然的体验吗?你只需要关心布局组件的样式,而不是它背后复杂而乏味的逻辑。 + +::: tip +为了节省文档的长度,我们省略了 `$page` 对象的数据结构。你可以在 [官方文档](https://v1.vuepress.vuejs.org/zh/guide/global-computed.html#page) 获得有关 `$page` 数据结构的更多信息。 +::: + +**也可详见**: + +- [分页配置](../pagination/README.md) + +## Frontmatter 分类器 + +Frontmatter 分类器,用于对具有相同 frontmatter 键值的页面进行分类。 + +假设你有三个页面: + +- `a.md`: + +```md +--- +tag: vue +--- +``` + +- `b.md`: + +```md +--- +tag: vue +--- +``` + +- `c.md`: + +```md +--- +tag: js +--- +``` + +如果你想轻松地对它们进行分类,则可以这样配置: + +```js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + frontmatters: [ + { + // 当前分类的唯一ID + id: 'tag', + // 决定将 frontmatter 键值归到该类别下 + keys: ['tag'], + // `entry page` (或者 `list page`) 的路径 + path: '/tag/', + // `entry page` 的布局 + layout: 'Tag', + }, + ], + }, + ], + ], +} +``` + +然后,该插件将帮助你生成以下额外页面,并自动利用相应的布局: + +| 地址 | 布局 | +| ----------- | ----------------------------------------------------------- | +| `/tag/` | `Tag` (fallback to `FrontmatterKey` if not exist) | +| `/tag/vue/` | `FrontmatterPagination` (fallback to `Layout` if not exist) | +| `/tag/js/` | `FrontmatterPagination` (fallback to `Layout` if not exist) | + +在 `` 组件中,你可以使用 [this.\$frontmatterKey.list](../client-api/README.md#frontmatterkey) 来获取标签列表。值将会像这样: + +```json +[ + { + "name": "vue", + "path": "/tag/vue/", + "pages": [ + { "relativePath": "b.md", "path": "/b.html" ... }, + { "relativePath": "a.md", "path": "/a.html" ... }, + ] + }, + { + "name": "js", + "path": "/tag/js/", + "pages": [ + { "relativePath": "c.md", "path": "/c.html" ... }, + ] + } +] +``` + +在 `FrontmatterPagination` 组件中,你可以使用 [this.\$pagination.pages](../client-api/README.md#pagination) 获取当前标签中匹配的页面分类: + +- 如果你访问了 `/tag/vue/`,`this.$pagination.pages` 将是: + +```json +[ + { "relativePath": "b.md", "path": "/b.html" ... }, + { "relativePath": "a.md", "path": "/a.html" ... }, +] +``` + +- 如果你访问了 `/tag/js/`,`this.$pagination.pages` 将是: + +```json +[ + { "relativePath": "c.md", "path": "/c.html" ... }, +] +``` + +**也可详见**: + +- [配置 > frontmatters](../config/README.md#frontmatters) + +## Sitemap + +我无法找到你不想要 Sitemap 的原因。 Sitemap 是一个 XML 文件,可帮助搜索引擎更好地索引你的博客。 + +通过简单地传递你的主机名即可生成文件,如下所示。 + +```js +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + sitemap: { + hostname: 'https://yourdomain', + }, + }, + ], + ], +} +``` + +## 评论 + +评论是使你的博客更加生动活泼的好方法。 我们在此插件中集成了客户端评论服务:[Vssue](https://vssue.js.org/) 和 [Disqus](https://disqus.com/)。 前者是一个基于 vue 的基于问题的开源项目,可以为你的静态页面启用评论,而后者是一个网络平台,可提供成千上万个网站使用的评论服务。 + +我们为你提供了一个现成的组件 ``。 你可以从 `'@vuepress/plugin-blog/lib/client/components'` 中导入它。 当你创建布局组件 `Post` 来处理帖子页面的所有布局时,这可能会很有用: + +```vue +// layouts/Post.vue + + + +``` + +你必须告诉插件你将要使用哪个服务。 + +由于注释是由其他插件实现的,因此请确保你已阅读[vuepress-plugin-vssue](https://vssue.js.org/) 或[vuepress-plugin-disqus](https://github.com/lorisleiva/vuepress-plugin-disqus) ,然后再使用它们: + +```js +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + comment: { + // 你想使用的服务 + service: 'vssue', + // 存储 issue 和评论的库的所有者名称。 + owner: 'You', + // 用于存储 issue 和评论的存储库的名称。 + repo: 'Your repo', + // 从 OAuth2 规范中引入的 clientId 和 clientSecret。 + clientId: 'Your clientId', + clientSecret: 'Your clientSecret', + }, + }, + ], + ], +} +``` + +```js +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + comment: { + // 你想使用的服务 + service: 'disqus', + // 用于存储 issue 和评论的存储库的所有者名称。 + shortname: 'vuepress-plugin-blog', + }, + }, + ], + ], +} +``` + +::: tip +当然,你可以使用任何喜欢的服务,也可以使用自己的评论系统。 你可以根据需要简单地忽略此配置,这样就不会启用此内置注释功能。 +::: + +## 订阅 (Newsletter) + +一个博客订阅 Newsletter 是一封电子邮件,用于通知订阅者你已经发布了新的博客文章。电子邮件是建立关系并与读者互动的好方法。 + +就像 [评论](#评论) 一样,我们集成了一项服务来帮助你轻松完成它。 [MailChimp](https://mailchimp.com/) 可能是最著名的电子邮件营销工具。唯一需要的配置选项是 `endpoint`,请转到[vuepress-plugin-mailchimp](https://vuepress-plugin-mailchimp.billyyyyy3320.com/#install) 以了解如何获取自己的 `endpoint`。 + +```js +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + newsletter: { + // 放置你的 endpoint,而不是我的 + endpoint: + 'https://billyyyyy3320.us4.list-manage.com/subscribe/post?u=4905113ee00d8210c2004e038&id=bd18d40138', + }, + }, + ], + ], +} +``` + +`vuepress-plugin-mailchimp` 已经注册了一个全局组件 `SimpleNewsletter`。 这是一个简单的用法: + +```vue +// layouts/Post.vue + +``` + +在你的主题中,你可能会为用户提供是否启用的选项。 你可以使用 `this.$service.email.enabled` 来访问它: + +```vue +// layouts/Post.vue + +``` + +如果你不喜欢默认的 UI,请转到 [自定义 UI](https://vuepress-plugin-mailchimp.billyyyyy3320.com/#ui-customization)。 + +## 提要 (Feed) + +Feed 是允许你的用户获取最新内容的另一种方法。 RSS,Atom 甚至 JSON 提要都是完成这项工作的正确工具。让我们来看一个例子: + +```JavaScript +// .vuepress/config.js +module.exports = { + plugins: [ + [ + '@vuepress/blog', + { + feed: { + canonical_base: 'http://yoursite', + }, + }, + ], + ], +} +``` + +构建后,你将可以在输出目录(`dist`)中找到它们 (`rss.xml`, `feed.atom`, `feed.json`)。 + +## 案例 + +此项目下有一些 [案例](https://github.com/vuepressjs/vuepress-plugin-blog/tree/master/examples) 帮助我们测试此插件。 在阅读了以上所有概念之后,它们对于你来说也是最简单的示例。 + +克隆[此仓库](https://github.com/vuepressjs/vuepress-plugin-blog) 并启动案例查看输出: + +```shell +yarn dev:example # 启动 example 开发服务器 +yarn build:example # 构建 example 输出 +``` + +::: tip +值得一提的是 [`zh` 文件夹](https://github.com/vuepressjs/vuepress-plugin-blog/tree/master/examples/zh) 是使用你的母语构建博客的示例。以繁体中文为例。 +::: + +## 撰写博客主题 + +如果一切正常,你就可以开始编写博客主题。实际上,创建博客主题只有 2 个必要的布局组件: + +- Layout +- Post +- FrontmatterKey (仅在设置 frontmatter 分类时才需要) + +这是为你提供的两个官方示例 (简单 和 复杂 ) : + +- [70 行的 vuepress 博客主题](https://github.com/ulivz/70-lines-of-vuepress-blog-theme): 一个大约 70 行中实现的 VuePress 博客主题。 +- [@vuepress/theme-blog](https://github.com/ulivz/vuepress-theme-blog): VuePress 的默认博客主题。 diff --git a/docs/zh/pagination/README.md b/docs/zh/pagination/README.md new file mode 100644 index 0000000..d118a76 --- /dev/null +++ b/docs/zh/pagination/README.md @@ -0,0 +1,103 @@ +--- +sidebar: auto +--- + +# 分页配置 + +::: tip +我们强烈建议你在使用此插件之前阅读 [快速上手](../guide/getting-started.md) 部分。 +::: + +## sorter + +- 类型: `Function` +- 默认值: + +```js +sorter: (prev, next) => { + const dayjs = require('dayjs') + const prevTime = dayjs(prev.frontmatter.date) + const nextTime = dayjs(next.frontmatter.date) + return prevTime - nextTime > 0 ? -1 : 1 +} +``` + +匹配页面的排序器。 + +该函数将是 [Array.sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 的一个参数。 + +::: warning +因为只有前两位用两位数字写的日期才会被转换,所以其他以一位数字写的日期(例如 `2020-1-1`)将被视为字符串。 +`dayjs` 接受这两种不同的结果,而 `new Date` 在某些浏览器(例如 Safari)中无法正常工作。 +::: + +## prevText + +- 类型: `string` +- 默认: `'Prev'` + +先前链接的文本。 + +## nextText + +- 类型: `string` +- 默认值: `'Next'` + +下一个链接的文字。 + +## lengthPerPage + +- 类型: `number` +- 默认值: `10` + +每页的最大帖子数。 + +## layout + +- 类型: `string` +- 默认值: `DirectoryPagination || Layout` + +分页页面的布局(主页除外)。 + +## getPaginationPageUrl + +- 类型: `Function` +- 默认值: + +```js +function getPaginationPageUrl(index) { + if (index === 0) { + return indexPath + } + return `${indexPath}page/${index + 1}/` +} +``` + +动态获取分页页面网址的函数。 + +- 对于 [目录分类器](../guide/getting-started.md#目录分类器), `indexPath` 默认为 `/${classifier.id}/` (例如 `/post/`) +- 对于 [frontmatter 分类器](../guide/getting-started.md#frontmatter-分类器), `indexPath` 默认为 `/${classifier.pid}/${classifier.id}` (例如 `/tag/js/`) + +## getPaginationPageTitle + +- 类型: `Function` +- 默认值: + +```js +// directories +function getPaginationPageTitle(pageNumber) { + return `Page ${pageNumber} | ${entryTitle}` +} + +// frontmatters +function getPaginationPageTitle(pageNumber, key) { + return `Page ${pageNumber} - ${key} | ${entryTitle}` +} +``` + +动态获取分页页面标题的功能。 + +有两个参数可以帮助你自定义标题: + +- `pageNumber` +- `key`: 配置 frontmatters 时的 [key](../config/#keys)