diff --git a/docs/developer-guide/form-schema.md b/docs/developer-guide/form-schema.md new file mode 100644 index 0000000..061798b --- /dev/null +++ b/docs/developer-guide/form-schema.md @@ -0,0 +1,271 @@ +--- +title: 表单定义 +--- + +在 Halo 2.0,在 Console 端的所有表单我们都使用了 [FormKit](https://github.com/formkit/formkit) 的方案。FormKit 不仅支持使用 Vue 组件的形式来构建表单,同时支持使用 Schema 的形式来构建。因此,我们的 [Setting](https://github.com/halo-dev/halo/blob/87ccd61ae5cd35a38324c30502d4e9c0ced41c6a/src/main/java/run/halo/app/core/extension/Setting.java#L20) 资源中的表单定义,都是使用 FormKit Schema 来定义的,最常用的场景即主题和插件的设置表单定义。当然,如果要在 Halo 2.0 的插件中使用,也可以参考 FormKit 的文档使用 Vue 组件的形式使用,但不需要在插件中引入 FormKit。 + +此文档将不会介绍 FormKit 的具体使用教程,因为我们已经很好的集成了 FormKit,并且使用方式基本无异。此文章将介绍 Halo 2.0 中表单定义的一些规范,以及额外的一些输入组件。 + +FormKit 相关文档: + +- Form Schema: + - + - +- FormKit Inputs: + +:::tip +目前不支持 FormKit Pro 中的输入组件,但 Halo 额外提供了部分输入组件,将在下面文档列出。 +::: + +## Setting 资源定义方式 + +```yaml title="settings.yaml" +apiVersion: v1alpha1 +kind: Setting +metadata: + name: foo-setting +spec: + forms: + - group: group_1 + label: 分组 1 + formSchema: + - $formkit: radio + name: color_scheme + label: 默认配色 + value: system + options: + - label: 跟随系统 + value: system + - label: 深色 + value: dark + - label: 浅色 + value: light + + - group: group_2 + label: 分组 2 + formSchema: + - $formkit: text + name: username + label: 用户名 + value: "" + - $formkit: password + name: password + label: 密码 + value: "" +``` + +:::tip +需要注意的是,FormKit Schema 本身应该是 JSON 格式的,但目前我们定义一个表单所使用的是 YAML,可能在参考 FormKit 写法时需要手动转换一下。 +::: + +字段说明: + +1. `metadata.name`:设置资源的名称,建议以 `-setting` 结尾。 +2. `spec.forms`:表单定义,可以定义多个表单,每个表单都有一个 `group` 字段,用于区分不同的表单。 +3. `spec.forms[].label`:表单的标题。 +4. `spec.forms[].formSchema`:表单的定义,使用 FormKit Schema 来定义。虽然我们使用的 YAML,但与 FormKit Schema 完全一致。 + +## 组件类型 + +除了 FormKit 官方提供的常用输入组件之外,Halo 还额外提供了一些输入组件,这些输入组件可以在 Form Schema 中使用。 + +### Repeater + +#### 描述 + +一组重复的输入组件,可以用于定义一组数据,最终得到的数据为一个对象的数组,可以方便地让使用者对其进行增加、移除、排序等操作。 + +#### 示例 + +```yaml +- $formkit: repeater + name: socials + label: 社交账号 + value: [] + children: + - $formkit: text + name: name + label: 名称 + value: "" + - $formkit: text + name: url + label: 地址 + value: "" +``` + +:::tip +使用 `repeater` 类型时,一定要设置默认值,如果不需要默认有任何元素,可以设置为 `[]`。 +::: + +其中 `name` 和 `url` 即数组对象的属性,最终保存表单之后得到的值为以下形式: + +```json +{ + "socials": [ + { + "name": "GitHub", + "url": "https://github.com/halo-dev" + } + ] +} +``` + +UI 效果: + + + +### Attachment + +#### 描述 + +附件类型的输入框,支持直接调用附件库弹框选择附件。 + +#### 示例 + +```yaml +- $formkit: attachment + name: logo + label: Logo + value: "" +``` + +### Code + +#### 描述 + +代码编辑器的输入组件,集成了 [Codemirror](https://codemirror.net/)。 + +#### 参数 + +- `language`:代码语言,目前支持 `yaml` `html` `javascript` `css` `json`。 +- `height`:代码编辑器的高度。 + +#### 示例 + +```yaml +- $formkit: code + name: footer_code + label: 页脚代码注入 + value: "" + language: yaml +``` + +### menuCheckbox + +#### 描述 + +菜单复选框,用于选择系统内的导航菜单。其中选择的值为菜单资源 `metadata.name` 的集合。 + +#### 示例 + +```yaml +- $formkit: menuCheckbox + name: menus + label: 菜单 + value: [] +``` + +### menuRadio + +#### 描述 + +菜单单选框,用于选择系统内的导航菜单。其中选择的值为菜单资源 `metadata.name`。 + +#### 示例 + +```yaml +- $formkit: menuRadio + name: menu + label: 菜单 + value: "" +``` + +### postSelect + +#### 描述 + +文章选择器,用于选择系统内的文章。其中选择的值为文章资源 `metadata.name`。 + +#### 示例 + +```yaml +- $formkit: postSelect + name: post + label: 文章 + value: "" +``` + +### singlePageSelect + +#### 描述 + +单页选择器,用于选择系统内的独立页面。其中选择的值为独立页面资源 `metadata.name`。 + +#### 示例 + +```yaml +- $formkit: singlePageSelect + name: singlePage + label: 单页 + value: "" +``` + +### categorySelect + +#### 描述 + +文章分类选择器,用于选择系统内的文章分类。其中选择的值为文章分类资源 `metadata.name`。 + +#### 示例 + +```yaml +- $formkit: categorySelect + name: category + label: 分类 + value: "" +``` + +### categoryCheckbox + +#### 描述 + +文章分类复选框,用于选择系统内的文章分类。其中选择的值为文章分类资源 `metadata.name` 的集合。 + +#### 示例 + +```yaml +- $formkit: categoryCheckbox + name: categories + label: 分类 + value: [] +``` + +### tagSelect + +#### 描述 + +文章标签选择器,用于选择系统内的文章标签。其中选择的值为文章标签资源 `metadata.name`。 + +#### 示例 + +```yaml +- $formkit: tagSelect + name: tag + label: 标签 + value: "" +``` + +### tagCheckbox + +#### 描述 + +文章标签复选框,用于选择系统内的文章标签。其中选择的值为文章标签资源 `metadata.name` 的集合。 + +#### 示例 + +```yaml +- $formkit: tagCheckbox + name: tags + label: 标签 + value: [] +``` diff --git a/docs/developer-guide/theme/code-snippets.md b/docs/developer-guide/theme/code-snippets.md new file mode 100644 index 0000000..632936c --- /dev/null +++ b/docs/developer-guide/theme/code-snippets.md @@ -0,0 +1,47 @@ +--- +title: 常用代码片段 +description: 本文档介绍了常用的代码片段,以便于开发者快速上手。 +--- + +## 布局模板 + +通常情况下,我们需要一个公共模板来定义页面的布局。 + +```html title="templates/layout.html" + + + + + + + + + + + + + + +
+ +
+ + +``` + +```html title="templates/index.html" + + + + +
    +
  • + +
  • +
+
+ +``` diff --git a/docs/developer-guide/theme/config-files.md b/docs/developer-guide/theme/config-files.md deleted file mode 100644 index 18f8ee4..0000000 --- a/docs/developer-guide/theme/config-files.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: 配置文件 -description: 主题配置文件的说明 ---- - -> Halo 的主题模块使用 yaml 来对主题进行配置,`theme.yaml` 里面主要描述主题的名称,开发者的信息,开源地址等等。`settings.yaml` 包含了主题所有的配置选项,需要注意的是,这些选项仅仅是用于构建配置表单,并不起到对主题的配置作用。 - -## theme.yaml - -```yaml -id: 主题id,唯一,不能与其他主题一样。我们建议设置为 `作者名_主题名称` -name: 主题名称 -author: - name: 作者名称 - website: 作者网址 -description: 主题描述 -logo: 主题 Logo 地址 -website: 主题地址,可填写为 git 仓库地址 -repo: 主题 git 仓库地址,如有填写,后台可在线更新 -version: 版本号 -require: 最低支持的 Halo 版本,如:1.3.0,那么如果用户的版本为 1.3.0 以下,则无法安装 - -postMetaField: 文章自定义 meta 变量 - - meta_key - -sheetMetaField: - - meta_key 页面自定义 meta 变量 -``` - -示例: - -```yaml -id: caicai_anatole -name: Anatole -author: - name: Caicai - website: https://www.caicai.me -description: A other Halo theme -logo: https://avatars1.githubusercontent.com/u/1811819?s=460&v=4 -website: https://github.com/halo-dev/halo-theme-anatole -repo: https://github.com/halo-dev/halo-theme-anatole -version: 1.0.0 -require: 1.3.0 -postMetaField: - - music_url # 假设在文章页面需要播放背景音乐,用户可以自己填写音乐地址。 - - download_url # 假设在文章页有一个下载按钮,那么用户也可以自己填写加载地址。 - -sheetMetaField: - - music_url - - download_url -``` - -### 自定义 meta - -这个为 1.2.0 引入的功能,用户可以在文章设置中设置自定义 meta,我们在 `theme.yaml` 中填写的 `postMetaField` 和 `sheetMetaField` 为预设项,当用户激活当前主题之后,在文章设置中即可看到预先设置好的项,然后填写对应的值即可。 - -关于这个 meta 变量如何调用的问题,会在后面的模板变量中阐述。 - -## settings.yaml - -```yaml -# Tab 节点 -group1: - label: 第一个 Tab 名称 - # 表单项 - items: - # 省略 -group2: - label: 第二个 Tab 名称 - # 表单项 - items: - # 省略 -``` - -## settings.yaml#items - -> settings.yaml 的 items 下即为所有表单元素,所支持的表单元素如下 - -```yaml -items: - - # 普通文本框 - item1: - name: item1 // 设置项的 name 值,在页面可通过 ${settings.item1!} 获取值。 - label: item1 // 表单项的 label - type: text // 表单项类型:普通文本框 - placeholder: '' // 表单项的 placeholder,一般给用户提示 - default: '' // 表单项的默认值 - description: '' // 描述,一般用于说明该设置的具体用途 - - # 颜色选择框 - item1: - name: item1 // 设置项的 name 值,在页面可通过 ${settings.item1!} 获取值。 - label: item1 // 表单项的 label - type: color // 表单项类型:颜色选择框 - placeholder: '' // 表单项的 placeholder,一般给用户提示 - default: '' // 表单项的默认值 - description: '' // 描述,一般用于说明该设置的具体用途 - - # 附件选择框 - item1: - name: item1 // 设置项的 name 值,在页面可通过 ${settings.item1!} 获取值。 - label: item1 // 表单项的 label - type: attachment // 表单项类型:颜色选择框 - placeholder: '' // 表单项的 placeholder,一般给用户提示 - default: '' // 表单项的默认值 - description: '' // 描述,一般用于说明该设置的具体用途 - - # 多行文本框 - item2: // 设置项的 name 值,在页面可通过 ${settings.item2!} 获取值。 - name: item2 - label: item2 // 同上 - type: textarea // 表单项类型:多行文本框 - placeholder: '' // 同上 - default: '' // 同上 - description: '' // 描述,一般用于说明该设置的具体用途 - - # 单选框 - item3: - name: item3 // 同上 - label: item3_label // 同上 - type: radio // 表单项类型:单选框 - data-type: bool // 数据类型:bool,string,long,double - default: value1 // 同上 - description: '' // 描述,一般用于说明该设置的具体用途 - options: // 选项 - - value: value1 // 值 - label: label1 // 说明 - - value: value2 - label: label2 - - # 下拉框 - item4: - name: item4 // 同上 - label: item4 // 同上 - type: select // 表单项类型:下拉框 - data-type: bool // 数据类型:bool,string,long,double - default: value1 // 同上 - description: '' // 描述,一般用于说明该设置的具体用途 - options: // 选项 - - value: value1 // 值 - label: label1 // 说明 - - value: value2 - label: label2 -``` - -### 一个例子 - -假设我们的配置文件如下: - -```yaml -general: - label: 基础设置 - items: - index_title: - name: index_title - label: 首页标题 - type: text - description: '注意:将覆盖博客标题' - background_cover: - name: background_cover - label: 首页背景图 - type: attachment - default: '/casper/assets/images/blog-cover.jpg' - description: '设置首页的背景图,你可以点击右边的选择按钮选择图片。' - background_color: - name: background_color - label: 首页背景颜色 - type: color - default: '#fff' - music_enabled: - name: music_enabled - label: 背景音乐 - type: radio - data-type: bool - default: false - description: '是否开启背景音乐,默认为 false' - options: - - value: true - label: 开启 - - value: false - label: 关闭 - code_pretty: - name: code_pretty - label: 文章代码高亮主题 - type: select - default: Default - options: - - value: Default - label: Default - - value: Coy - label: Coy - - value: Dark - label: Dark - - value: Okaidia - label: Okaidia - - value: Solarized Light - label: Solarized Light - - value: Tomorrow Night - label: Tomorrow Night - - value: Twilight - label: Twilight -``` - -页面取值: - -```html -// 获取首页标题 - -<#if settings.index_title?? && settings.index_title != ''> -

${settings.index_title!}

- -``` - -```html -// 获取背景图片 - -<#if settings.background_cover?? && settings.background_cover != ''> - - -``` - -```html -// 获取背景颜色 - - - -或者 - - - -``` - -```html -// 判断是否开启背景音乐 - -<#if settings.music_enabled!false> - do something... - -``` - -```html -// 获取代码高亮主题 - - - -``` - -更多实例可参考:。 diff --git a/docs/developer-guide/theme/config.md b/docs/developer-guide/theme/config.md new file mode 100644 index 0000000..fe92e8f --- /dev/null +++ b/docs/developer-guide/theme/config.md @@ -0,0 +1,83 @@ +--- +title: 配置文件 +description: 关于主题配置文件的文档。 +--- + +目前 Halo 2.0 的主题必须在根目录包含 `theme.yaml`,用于配置主题的基本信息,如主题名称、版本、作者等。 + +## 格式示例 + +```yaml title="theme.yaml" +apiVersion: theme.halo.run/v1alpha1 +kind: Theme +metadata: + name: theme-foo +spec: + displayName: 示例主题 + author: + name: halo-dev + website: https://halo.run + description: 一个示例主题 + logo: https://halo.run/logo + website: https://github.com/halo-sigs/theme-foo + repo: https://github.com/halo-sigs/theme-foo.git + settingName: "theme-foo-setting" + configMapName: "theme-foo-configMap" + customTemplates: + post: + - name: 文档 + description: 文档类型的文章 + screenshot: + file: post_documentation.html + category: + - name: 知识库 + description: 知识库类型的分类 + screenshot: + file: category_knowledge.html + page: + - name: 关于 + description: 关于页面 + screenshot: + file: page_about.html + version: 1.0.0 + require: 2.0.0 +``` + +## 字段详解 + +| 字段 | 描述 | 是否必填 | +| ------------------------------- | ----------------------------------------------------------------------------- | -------- | +| `metadata.name` | 主题的唯一标识 | 是 | +| `spec.displayName` | 显示名称 | 是 | +| `spec.author.name` | 作者名称 | 否 | +| `spec.author.website` | 作者网站 | 否 | +| `spec.description` | 主题描述 | 否 | +| `spec.logo` | 主题 Logo | 否 | +| `spec.website` | 主题网站 | 否 | +| `spec.repo` | 主题托管地址 | 否 | +| `spec.settingName` | 设置表单定义的名称,需要同时创建对应的 `settings.yaml` 文件 | 否 | +| `spec.configMapName` | 设置持久化配置的 ConfigMap 名称 | 否 | +| `spec.customTemplates.post` | 文章的自定义模板配置,详细文档可查阅 [模板路由](./template-route-mapping#custom-templates) | 否 | +| `spec.customTemplates.category` | 分类的自定义模板配置,详细文档可查阅 [模板路由](./template-route-mapping#custom-templates) | 否 | +| `spec.customTemplates.page` | 独立页面的自定义模板配置,详细文档可查阅 [模板路由](./template-route-mapping#custom-templates) | 否 | +| `spec.version` | 主题版本 | 是 | +| `spec.require` | 所需 Halo 的运行版本 | 是 | + +## 从 1.x 迁移 + +为了方便主题开发者从 1.x 迁移,我们提供了工具用于迁移配置文件。 + +工具仓库地址: + +```bash +# 1.x 版本主题 +cd path/to/theme + +npx @halo-dev/convert-theme-config-to-next theme +``` + +执行完成之后即可看到主题目录下生成了 `theme.2.0.yaml` 文件,重命名为 `theme.yaml` 即可。 + +:::tip +转换完成之后需要修改 `metadata.name`、`spec.settingName` 和 `spec.configMapName`。 +::: diff --git a/docs/developer-guide/theme/finder-apis.md b/docs/developer-guide/theme/finder-apis.md new file mode 100644 index 0000000..fc4522f --- /dev/null +++ b/docs/developer-guide/theme/finder-apis.md @@ -0,0 +1,10 @@ +--- +title: Finder API +description: 本文档介绍 Finder API 的使用方法。 +--- + +import DocCardList from '@theme/DocCardList'; + +目前在主题模板中获取数据可以使用对应路由提供的 [模板变量](./template-variables),但为了满足在任意位置获取数据的需求,我们提供了 Finder API。 + + diff --git a/docs/developer-guide/theme/finder-apis/category.md b/docs/developer-guide/theme/finder-apis/category.md new file mode 100644 index 0000000..1af6cb7 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/category.md @@ -0,0 +1,246 @@ +--- +title: 文章分类 +description: 文章分类 - CategoryFinder +--- + +## getByName(name) + +```js +categoryFinder.getByName(name) +``` + +### 描述 + +根据 `metadata.name` 获取文章分类。 + +### 参数 + +1. `name:string` - 分类的唯一标识 `metadata.name`。 + +### 返回值 + +[#CategoryVo](#categoryvo) + +### 示例 + +```html +
+ +
+``` + +## getByNames(names) + +```js +categoryFinder.getByNames(names) +``` + +### 描述 + +根据一组 `metadata.name` 获取文章分类。 + +### 参数 + +1. `names:List` - 分类的唯一标识 `metadata.name` 的集合。 + +### 返回值 + +List<[#CategoryVo](#categoryvo)> + +### 示例 + +```html +
+ +
+``` + +## list(page,size) + +```js +categoryFinder.list(page,size) +``` + +### 描述 + +根据分页参数获取分类列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresultcategoryvo) + +### 示例 + +```html +
    +
  • + +
  • +
+``` + +## listAll() + +```js +categoryFinder.listAll() +``` + +### 描述 + +获取所有文章分类。 + +### 参数 + +无 + +### 返回值 + +List<[#CategoryVo](#categoryvo)> + +### 示例 + +```html +
    +
  • + +
  • +
+``` + +## listAsTree() + +```js +categoryFinder.listAsTree() +``` + +### 描述 + +获取所有文章分类的多层级结构。 + +### 参数 + +无 + +### 返回值 + +List<[#CategoryTreeVo](#categorytreevo)> + +### 示例 + +```html +
+
    +
  • +
+
+``` + +```html title="/templates/category-tree.html" + +``` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#CategoryVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#CategoryVo](#categoryvo) + +### CategoryTreeVo + +```json title="CategoryTreeVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:18:49.230Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "children": "List<#CategoryTreeVo>", + "parentName": "string", + "postCount": 0 +} +``` + +- [#CategoryTreeVo](#categorytreevo) diff --git a/docs/developer-guide/theme/finder-apis/comment.md b/docs/developer-guide/theme/finder-apis/comment.md new file mode 100644 index 0000000..cf15914 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/comment.md @@ -0,0 +1,245 @@ +--- +title: 评论 +description: 评论 - CommentFinder +--- + +## getByName(name) + +```js +commentFinder.getByName(name) +``` + +### 描述 + +根据 `metadata.name` 获取评论。 + +### 参数 + +1. `name:string` - 评论的唯一标识 `metadata.name`。 + +### 返回值 + +[#CommentVo](#commentvo) + +### 示例 + +```html +
+ +
+
+``` + +## list(ref,page,size) + +```js +commentFinder.list(ref,page,size) +``` + +### 描述 + +根据评论的 `metadata.name` 和分页参数获取回复列表。 + +### 参数 + +1. `ref:#Ref` - 评论的唯一标识 `metadata.name`。 +2. `page:int` - 分页页码,从 1 开始 +3. `size:int` - 分页条数 + +- [#Ref](#ref) + +### 返回值 + +[#ListResult](#listresultcommentvo) + +### 示例 + +```html +
    +
  • + +
    +
  • +
+``` + +## listReply(commentName,page,size) + +```js +commentFinder.listReply(commentName,page,size) +``` + +### 描述 + +根据评论的 `metadata.name` 和分页参数获取回复列表。 + +### 参数 + +1. `commentName:string` - 评论的唯一标识 `metadata.name`。 +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresultreplyvo) + +### 示例 + +```html +
    +
  • + +
    +
  • +
+``` + +## 类型定义 + +### CommentVo + +```json title="CommentVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T12:16:19.788Z" + }, + "spec": { + "raw": "string", + "content": "string", + "owner": { + "kind": "string", + "name": "string", + "displayName": "string", + "annotations": { + "additionalProp1": "string" + } + }, + "userAgent": "string", + "ipAddress": "string", + "priority": 0, + "top": false, + "allowNotification": true, + "approved": false, + "hidden": false, + "subjectRef": { + "group": "string", + "version": "string", + "kind": "string", + "name": "string" + }, + "lastReadTime": "2022-11-20T12:16:19.788Z" + }, + "status": { + "lastReplyTime": "2022-11-20T12:16:19.788Z", + "replyCount": 0, + "unreadReplyCount": 0, + "hasNewReply": true + }, + "owner": { + "kind": "string", + "name": "string", + "displayName": "string", + "avatar": "string", + "email": "string" + } +} +``` + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#CommentVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#CommentVo](#commentvo) + +### ReplyVo + +```json title="ReplyVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T12:25:32.357Z" + }, + "spec": { + "raw": "string", + "content": "string", + "owner": { + "kind": "string", + "name": "string", + "displayName": "string", + "annotations": { + "additionalProp1": "string" + } + }, + "userAgent": "string", + "ipAddress": "string", + "priority": 0, + "top": false, + "allowNotification": true, + "approved": false, + "hidden": false, + "commentName": "string", + "quoteReply": "string" + }, + "owner": { + "kind": "string", + "name": "string", + "displayName": "string", + "avatar": "string", + "email": "string" + } +} +``` + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ReplyVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#ReplyVo](#replyvo) + +### Ref + +```json title="Ref" +{ + "group": "string", + "kind": "string", + "version": "string", + "name": "string" +} +``` diff --git a/docs/developer-guide/theme/finder-apis/contributor.md b/docs/developer-guide/theme/finder-apis/contributor.md new file mode 100644 index 0000000..517ece6 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/contributor.md @@ -0,0 +1,69 @@ +--- +title: 作者 +description: 作者 - ContributorFinder +--- + +## getContributor(name) + +```js +contributorFinder.getContributor(name) +``` + +### 描述 + +根据 `metadata.name` 获取作者。 + +### 参数 + +1. `name:string` - 作者的唯一标识 `metadata.name`。 + +### 返回值 + +[#Contributor](#contributor) + +### 示例 + +```html +
+

+
+``` + +## getContributors(names) + +```js +contributorFinder.getContributors(names) +``` + +### 描述 + +根据一组 `metadata.name` 获取作者。 + +### 参数 + +1. `names:List` - 作者的唯一标识 `metadata.name` 的集合。 + +### 返回值 + +List<[#Contributor](#contributor)> + +### 示例 + +```html +
+ +
+``` + +## 类型定义 + +### Contributor + +```json title="Contributor" +{ + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" +} +``` diff --git a/docs/developer-guide/theme/finder-apis/menu.md b/docs/developer-guide/theme/finder-apis/menu.md new file mode 100644 index 0000000..a77072d --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/menu.md @@ -0,0 +1,145 @@ +--- +title: 导航菜单 +description: 导航菜单 - MenuFinder +--- + +## getByName(name) + +```js +menuFinder.getByName(name) +``` + +### 描述 + +根据 `metadata.name` 获取菜单。 + +### 参数 + +1. `name:string` - 菜单的唯一标识 `metadata.name`。 + +### 返回值 + +[#MenuVo](#menuvo) + +### 示例 + +```html +
+
    +
  • + +
  • +
+
+``` + +## getPrimary() + +```js +menuFinder.getPrimary() +``` + +### 描述 + +获取主菜单。 + +### 参数 + +无 + +### 返回值 + +[#MenuVo](#menuvo) + +### 示例 + +```html +
+
    +
  • + +
  • +
+
+``` + +## 类型定义 + +### MenuVo + +```json title="MenuVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:44:58.984Z", + }, + "spec": { + "displayName": "string", + "menuItems": [ + "string" + ] + }, + "menuItems": "List<#MenuItemVo>" +} +``` + +### MenuItemVo + +```json title="MenuItemVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:44:58.984Z", + }, + "spec": { + "displayName": "string", + "href": "string", + "priority": 0, + "children": [ + "string" + ], + "categoryRef": { + "group": "string", + "version": "string", + "kind": "string", + "name": "string" + }, + "tagRef": { + "group": "string", + "version": "string", + "kind": "string", + "name": "string" + }, + "postRef": { + "group": "string", + "version": "string", + "kind": "string", + "name": "string" + }, + "singlePageRef": { + "group": "string", + "version": "string", + "kind": "string", + "name": "string" + } + }, + "status": { + "displayName": "string", + "href": "string" + }, + "children": "List<#MenuItemVo>", + "parentName": "string", +} +``` diff --git a/docs/developer-guide/theme/finder-apis/plugin.md b/docs/developer-guide/theme/finder-apis/plugin.md new file mode 100644 index 0000000..a77ec2d --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/plugin.md @@ -0,0 +1,33 @@ +--- +title: 插件 +description: 插件 - PluginFinder +--- + +## available(pluginName) + +```js +pluginFinder.available(pluginName) +``` + +### 描述 + +判断一个插件是否可用,会同时判断插件是否安装和启用。 + +### 参数 + +1. `pluginName:string` - 插件的唯一标识 `metadata.name`。 + +### 返回值 + +`boolean` - 插件是否可用 + +### 示例 + +```html + +
  • + + 搜索 + +
  • +``` diff --git a/docs/developer-guide/theme/finder-apis/post.md b/docs/developer-guide/theme/finder-apis/post.md new file mode 100644 index 0000000..70b91be --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/post.md @@ -0,0 +1,637 @@ +--- +title: 文章 +description: 文章 - PostFinder +--- + +## getByName(postName) + +```js +postFinder.getByName(postName) +``` + +### 描述 + +根据 `metadata.name` 获取文章。 + +### 参数 + +1. `postName:string` - 文章的唯一标识 `metadata.name`。 + +### 返回值 + +[#PostVo](#postvo) + +### 示例 + +```html +
    + +
    +``` + +## content(postName) + +```js +postFinder.content(postName) +``` + +### 描述 + +根据文章的 `metadata.name` 单独获取文章内容。 + +### 参数 + +1. `postName:string` - 文章的唯一标识 `metadata.name`。 + +### 返回值 + +[#ContentVo](#contentvo) + +### 示例 + +```html +
    +
    +
    +``` + +## cursor(postName) + +```js +postFinder.cursor(postName) +``` + +### 描述 + +根据文章的 `metadata.name` 获取相邻的文章(上一篇 / 下一篇)。 + +### 参数 + +1. `postName:string` - 文章的唯一标识 `metadata.name`。 + +### 返回值 + +[#NavigationPostVo](#navigationpostvo) + +### 示例 + +```html title="/templates/post.html" + +``` + +## listAll() + +```js +postFinder.listAll() +``` + +### 描述 + +获取所有文章。 + +### 参数 + +无 + +### 返回值 + +List<[#ListedPostVo](#listedpostvo)> + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## list(page,size) + +```js +postFinder.list(page,size) +``` + +### 描述 + +根据分页参数获取文章列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresultlistedpostvo) + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## listByCategory(page,size,categoryName) + +```js +postFinder.listByCategory(page,size,categoryName) +``` + +### 描述 + +根据分类标识和分页参数获取文章列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 +3. `categoryName:string` - 文章分类唯一标识 `metadata.name` + +### 返回值 + +[#ListResult](#listresultlistedpostvo) + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## listByTag(page,size,tag) + +```js +postFinder.listByTag(page,size,tag) +``` + +### 描述 + +根据标签标识和分页参数获取文章列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 +3. `tag:string` - 文章分类唯一标识 `metadata.name` + +### 返回值 + +[#ListResult](#listresultlistedpostvo) + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## archives(page,size) + +```js +postFinder.archives(page,size) +``` + +### 描述 + +根据分页参数获取文章归档列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresultpostarchivevo) + +### 示例 + +```html + + +

    +
      + +
    • + + +
    • +
      +
    +
    +
    +``` + +## archives(page,size,year) + +```js +postFinder.archives(page,size,year) +``` + +### 描述 + +根据年份和分页参数获取文章归档列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 +2. `year:string` - 年份 + +### 返回值 + +[#ListResult](#listresultpostarchivevo) + +### 示例 + +```html + + +

    +
      + +
    • + + +
    • +
      +
    +
    +
    +``` + +## archives(page,size,year,month) + +```js +postFinder.archives(page,size,year,month) +``` + +### 描述 + +根据年月和分页参数获取文章归档列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 +2. `year:string` - 年份 +2. `month:string` - 月份 + +### 返回值 + +[#ListResult](#listresultpostarchivevo) + +### 示例 + +```html + + +

    +
      + +
    • + + +
    • +
      +
    +
    +
    +``` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### PostVo + +```json title="PostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T12:45:43.888Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T12:45:43.888Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + }, + "content": { + "raw": "string", + "content": "string" + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### ContentVo + +```json title="ContentVo" +{ + "raw": "string", + "content": "string" +} +``` + +### NavigationPostVo + +```json title="NavigationPostVo" +{ + "previous": "#PostVo", + "current": "#PostVo", + "next": "#PostVo" +} +``` + +- [#PostVo](#postvo) + +### ListedPostVo + +```json title="ListedPostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.505Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T13:06:38.505Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ListedPostVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#ListedPostVo](#listedpostvo) + +### PostArchiveVo + +```json title="PostArchiveVo" +{ + "year": "string", + "months": [ + { + "month": "string", + "posts": "#ListedPostVo" + } + ] +} +``` + +- [#ListedPostVo](#listedpostvo) + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#PostArchiveVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#PostArchiveVo](#postarchivevo) diff --git a/docs/developer-guide/theme/finder-apis/single-page.md b/docs/developer-guide/theme/finder-apis/single-page.md new file mode 100644 index 0000000..0194f97 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/single-page.md @@ -0,0 +1,260 @@ +--- +title: 独立页面 +description: 独立页面 - SinglePageFinder +--- + +## getByName(pageName) + +```js +singlePageFinder.getByName(pageName) +``` + +### 描述 + +根据 `metadata.name` 获取独立页面。 + +### 参数 + +1. `pageName:string` - 独立页面的唯一标识 `metadata.name`。 + +### 返回值 + +[#SinglePageVo](#singlepagevo) + +### 示例 + +```html +
    + +
    +``` + +## content(pageName) + +```js +singlePageFinder.content(pageName) +``` + +### 描述 + +根据独立页面的 `metadata.name` 单独获取独立页面内容。 + +### 参数 + +1. `pageName:string` - 独立页面的唯一标识 `metadata.name`。 + +### 返回值 + +[#ContentVo](#contentvo) + +### 示例 + +```html +
    +
    +
    +``` + +## list(page,size) + +```js +singlePageFinder.list(page,size) +``` + +### 描述 + +根据分页参数获取独立页面列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresultlistedsinglepagevo) + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## 类型定义 + +### SinglePageVo + +```json title="SinglePageVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:29:44.601Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T14:29:44.601Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + }, + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "content": { + "raw": "string", + "content": "string" + } +} +``` + +### ListedSinglePageVo + +```json title="ListedSinglePageVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:31:00.876Z" + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T14:31:00.876Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + }, + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } +} +``` + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ListedSinglePageVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#ListedSinglePageVo](#listedsinglepagevo) + +### ContentVo + +```json title="ContentVo" +{ + "raw": "string", + "content": "string" +} +``` diff --git a/docs/developer-guide/theme/finder-apis/site-stats.md b/docs/developer-guide/theme/finder-apis/site-stats.md new file mode 100644 index 0000000..edb52e5 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/site-stats.md @@ -0,0 +1,45 @@ +--- +title: 站点统计 +description: 站点统计 - SiteStatsFinder +--- + +## getStats() + +```js +siteStatsFinder.getStats() +``` + +### 描述 + +获取站点的统计信息。 + +### 参数 + +无 + +### 返回值 + +[#SiteStatsVo](#sitestatsvo) + +### 示例 + +```html +
      +
    • +
    • +
    +``` + +## 类型定义 + +### SiteStatsVo + +```json title="SiteStatsVo" +{ + "visit": 0, + "upvote": 0, + "comment": 0, + "post": 0, + "category": 0 +} +``` diff --git a/docs/developer-guide/theme/finder-apis/tag.md b/docs/developer-guide/theme/finder-apis/tag.md new file mode 100644 index 0000000..bfa0559 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/tag.md @@ -0,0 +1,162 @@ +--- +title: 文章标签 +description: 文章标签 - TagFinder +--- + +## getByName(name) + +```js +tagFinder.getByName(name) +``` + +### 描述 + +根据 `metadata.name` 获取标签。 + +### 参数 + +1. `name:string` - 标签的唯一标识 `metadata.name`。 + +### 返回值 + +[#TagVo](#tagvo) + +### 示例 + +```html +
    + +
    +``` + +## getByNames(names) + +```js +tagFinder.getByNames(names) +``` + +### 描述 + +根据一组 `metadata.name` 获取标签。 + +### 参数 + +1. `names:List` - 标签的唯一标识 `metadata.name` 的集合。 + +### 返回值 + +List<[#TagVo](#tagvo)> + +### 示例 + +```html +
    + +
    +``` + +## list(page,size) + +```js +tagFinder.list(page,size) +``` + +### 描述 + +根据分页参数获取标签列表。 + +### 参数 + +1. `page:int` - 分页页码,从 1 开始 +2. `size:int` - 分页条数 + +### 返回值 + +[#ListResult](#listresulttagvo) + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## listAll() + +```js +tagFinder.listAll() +``` + +### 描述 + +获取所有文章标签。 + +### 参数 + +无 + +### 返回值 + +List<[#TagVo](#tagvo)> + +### 示例 + +```html +
      +
    • + +
    • +
    +``` + +## 类型定义 + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### ListResult + +```json title="ListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#TagVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0 +} +``` + +- [#TagVo](#tagvo) diff --git a/docs/developer-guide/theme/finder-apis/theme.md b/docs/developer-guide/theme/finder-apis/theme.md new file mode 100644 index 0000000..9fbb1a2 --- /dev/null +++ b/docs/developer-guide/theme/finder-apis/theme.md @@ -0,0 +1,119 @@ +--- +title: 主题 +description: 主题 - ThemeFinder +--- + +## activation() + +```js +themeFinder.activation() +``` + +### 描述 + +获取当前激活的主题。 + +### 参数 + +无 + +### 返回值 + +[#ThemeVo](#themevo) + +### 示例 + +```html +
    +

    +

    +
    +``` + +## getByName(themeName) + +```js +themeFinder.getByName(themeName) +``` + +### 描述 + +根据主题的唯一标识 `metadata.name` 获取主题。 + +### 参数 + +- `themeName:string` - 主题名称 + +### 返回值 + +[#ThemeVo](#themevo) + +### 示例 + +```html +
    +

    +

    +
    +``` + +## 类型定义 + +### ThemeVo + +```json title="ThemeVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T15:27:15.036Z", + }, + "spec": { + "displayName": "string", + "author": { + "name": "string", + "website": "string" + }, + "description": "string", + "logo": "string", + "website": "string", + "repo": "string", + "version": "string", + "require": "string", + "settingName": "string", + "configMapName": "string", + "customTemplates": { + "post": [ + { + "name": "string", + "description": "string", + "screenshot": "string", + "file": "string" + } + ], + "category": [ + { + "name": "string", + "description": "string", + "screenshot": "string", + "file": "string" + } + ], + "page": [ + { + "name": "string", + "description": "string", + "screenshot": "string", + "file": "string" + } + ] + } + }, + "config": {} +} +``` diff --git a/docs/developer-guide/theme/global-variable.md b/docs/developer-guide/theme/global-variable.md deleted file mode 100644 index c9785a7..0000000 --- a/docs/developer-guide/theme/global-variable.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: 全局变量 -description: 系统提供的一些全局变量 ---- - -## 博客地址 - -```html -${blog_url!} -``` - -此变量与后台博客设置中的 `博客地址` 相对应。 - -## 网站根路径 - -```html -${context!} -``` - -需要注意的是,此变量和 `blog_url` 不同的是,这个变量有两种值,一种为相对路径形式,一种为绝对路径形式。 - -那么,当在后台博客设置中将 `全局绝对路径` 的选项打开时,`context` 变量值为 `${blog_url}/`,关闭时,`context` 的变量值为 `/`。 - -假设,我设置的 `博客地址` 为 `https://halo.run`,那么: - -- 全局绝对路径为开启的状态下: -- 全局绝对路径为关闭的状态下:/ - -## 主题资源根路径 - -```html -${theme_base!} -``` - -假设你的主题在 `~/halo-dev/templates/themes/anatole` 这个目录,那么 `theme_base` 为 `https://yourdomain/themes/anatole` - -举个例子,你当前开发的主题为 `anatole`,当你要获取主题下 `css/style.css` 这个文件的路径,那么: - -```html -${theme_base!}/css/style.css -``` - -## 主题信息 - -主题名称: - -```html -${theme.name!} -``` - -主题 git 仓库地址: - -```html -${theme.repo!} -``` - -主题版本号: - -```html -${theme.version!} -``` - -## 博客标题 - -```html -${blog_title!} -``` - -此变量与后台博客设置中的 `博客标题` 相对应。 - -## 博客 Logo - -```html -${blog_logo!} -``` - -此变量与后台博客设置中的 `Logo` 相对应。 - -## Halo 版本 - -```html -${version!} -``` - -当前 Halo 的版本,如:1.3.0 - -## 博主信息 - -昵称: - -```html -${user.nickname!} -``` - -邮箱地址: - -```html -${user.email!} -``` - -描述: - -```html -${user.description!} -``` - -头像地址: - -```html -${user.avatar!} -``` - -上次登录时间: - -```html -${user.expireTime!} -``` - -## SEO 关键词 - -```html -${meta_keywords!} -``` - -需要注意的是,虽然这个变量在任何页面都可以使用,但是其值可能在不同的页面是不一样的。会根据用户的设置,生成对应的值。 - -假设在文章页面: - -- 如果用户为文章设置了标签,而没有设置 `自定义关键词`,系统会自动将标签设置为页面关键词。 -- 如果用户设置了 `自定义关键词`,那么则会取用户设置的值。 - -## SEO 描述 - -```html -${meta_description!} -``` - -需要注意的是,虽然这个变量在任何页面都可以使用,但是其值可能在不同的页面是不一样的。会根据用户的设置,生成对应的值。 - -## RSS 2.0 订阅地址 - -```html -${rss_url!} -``` - -如:`https://yourdomain/rss.xml` - -## Atom 格式的订阅地址 - -```html -${atom_url!} -``` - -如:`https://yourdomain/atom.xml` - -## XML 格式的网站地图地址 - -```html -${sitemap_xml_url!} -``` - -如:`https://yourdomain/sitemap.xml` - -## HTML 格式的网站地图地址 - -```html -${sitemap_html_url!} -``` - -如:`https://yourdomain/sitemap.html` - -## 友情链接页面地址 - -```html -${links_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{links_prefix}` -- **全局绝对路径为关闭的状态下**:`/{links_prefix}` - -`{links_prefix}` 是用户可设定的值,用户可以在后台修改 `友情链接` 的前缀,默认为 `links`。 - -## 图库页面地址 - -```html -${photos_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{photos_prefix}` -- **全局绝对路径为关闭的状态下**:`/{photos_prefix}` - -`{photos_prefix}` 是用户可设定的值,用户可以在后台修改 `图库页面` 的前缀,默认为 `photos`。 - -## 日志页面地址 - -```html -${journals_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{journals_prefix}` -- **全局绝对路径为关闭的状态下**:`/{journals_prefix}` - -`{journals_prefix}` 是用户可设定的值,用户可以在后台修改 `日志页面` 的前缀,默认为 `journals`。 - -## 文章归档页面地址 - -```html -${archives_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{archives_prefix}` -- **全局绝对路径为关闭的状态下**:`/{archives_prefix}` - -`{archives_prefix}` 是用户可设定的值,用户可以在后台修改 `归档` 的前缀,默认为 `archives`。 - -## 分类列表页面地址 - -```html -${categories_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{categories_prefix}` -- **全局绝对路径为关闭的状态下**:`/{categories_prefix}` - -`{categories_prefix}` 是用户可设定的值,用户可以在后台修改 `分类` 的前缀,默认为 `categories`。 - -## 标签列表页面地址 - -```html -${tags_url!} -``` - -- **全局绝对路径为开启的状态下**:`https://yourdomain.com/{tags_prefix}` -- **全局绝对路径为关闭的状态下**:`/{tags_prefix}` - -`{tags_prefix}` 是用户可设定的值,用户可以在后台修改 `标签` 的前缀,默认为 `tags`。 - -## 页面判断 - -判断当前页面是否是特定的页面。 - -- **is_index**:首页 -- **is_post**:文章页 -- **is_sheet**:自定义页面 -- **is_archives**:归档页面 -- **is_categories**:分类列表页面 -- **is_category**:单个分类页面 -- **is_tags**:标签列表页面 -- **is_tag**:单个标签页面 -- **is_search**:搜索结果页面 -- **is_journals**:日志页面 -- **is_photos**:图库页面 -- **is_links**:友情链接页面 - -用法: - -```html -<#if is_index??> - 当前页面是首页 - -``` diff --git a/docs/developer-guide/theme/page-variable.md b/docs/developer-guide/theme/page-variable.md deleted file mode 100644 index 555be22..0000000 --- a/docs/developer-guide/theme/page-variable.md +++ /dev/null @@ -1,1354 +0,0 @@ ---- -title: 页面变量 -description: 每个页面所返回的变量 ---- - -## 首页(index.ftl) - -访问路径:`http://yourdomain` - -### posts(List) - -#### 语法 - -```html -<#list posts.content as post> -// do something - -``` - -#### 参数 - -```json -[{ - "content": [{ - "categories": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-13T13:23:39.143Z", - "disallowComment": true, - "editTime": "2020-10-13T13:23:39.143Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-13T13:23:39.143Z", - "visits": 0, - "wordCount": 0 - }], - "empty": true, - "first": true, - "last": true, - "number": 0, - "numberOfElements": 0, - "pageable": { - "page": 0, - "size": 0, - "sort": [ - "string" - ] - }, - "size": 0, - "sort": { - "sort": [ - "string" - ] - }, - "totalElements": 0, - "totalPages": 0 -}] -``` - -#### 示例 - -遍历输出首页的文章: - -```html -<#list posts.content as post> - ${post.title!} - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -## 文章页面(post.ftl) - -访问路径不固定,视固定链接配置而定,目前可以配置的有: - -- `http://yourdomain/archives/{slug}`(默认) -- `http://yourdomain/1970/01/{slug}` -- `http://yourdomain/1970/01/01/{slug}` -- `http://yourdomain/?p={id}` -- `http://yourdomain/archives/{id}` - -### post(Object) - -#### 语法 - -```html -${post.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "categories": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "categoryIds": [ - 0 - ], - "commentCount": 0, - "createTime": "2021-02-25T13:15:58.589Z", - "disallowComment": true, - "editTime": "2021-02-25T13:15:58.589Z", - "editorType": "MARKDOWN", - "formatContent": "string", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaIds": [ - 0 - ], - "metaKeywords": "string", - "metas": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "id": 0, - "key": "string", - "postId": 0, - "value": "string" - } - ], - "originalContent": "string", - "password": "string", - "slug": "string", - "status": "DRAFT", - "summary": "string", - "tagIds": [ - 0 - ], - "tags": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2021-02-25T13:15:58.589Z", - "visits": 0, - "wordCount": 0 -} -``` - -#### 示例 - -获取文章标题: - -```html -${post.title!} -``` - -输出: - -```html -示例文章 -``` - -### prevPost(Object) - -#### 语法 - -```html -${prevPost.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "categories": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "categoryIds": [ - 0 - ], - "commentCount": 0, - "createTime": "2021-02-25T13:15:58.589Z", - "disallowComment": true, - "editTime": "2021-02-25T13:15:58.589Z", - "editorType": "MARKDOWN", - "formatContent": "string", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaIds": [ - 0 - ], - "metaKeywords": "string", - "metas": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "id": 0, - "key": "string", - "postId": 0, - "value": "string" - } - ], - "originalContent": "string", - "password": "string", - "slug": "string", - "status": "DRAFT", - "summary": "string", - "tagIds": [ - 0 - ], - "tags": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2021-02-25T13:15:58.589Z", - "visits": 0, - "wordCount": 0 -} -``` - -#### 示例 - -获取上一篇文章的信息: - -```html -<#if prevPost??> - 上一篇:${prevPost.title!} - -``` - -输出: - -```html -上一篇:title1 -``` - -### nextPost(Object) - -#### 语法 - -```html -${nextPost.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "categories": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "categoryIds": [ - 0 - ], - "commentCount": 0, - "createTime": "2021-02-25T13:15:58.589Z", - "disallowComment": true, - "editTime": "2021-02-25T13:15:58.589Z", - "editorType": "MARKDOWN", - "formatContent": "string", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaIds": [ - 0 - ], - "metaKeywords": "string", - "metas": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "id": 0, - "key": "string", - "postId": 0, - "value": "string" - } - ], - "originalContent": "string", - "password": "string", - "slug": "string", - "status": "DRAFT", - "summary": "string", - "tagIds": [ - 0 - ], - "tags": [ - { - "createTime": "2021-02-25T13:15:58.589Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2021-02-25T13:15:58.589Z", - "visits": 0, - "wordCount": 0 -} -``` - -#### 示例 - -获取下一篇文章的信息: - -```html -<#if nextPost??> - 下一篇:${nextPost.title!} - -``` - -输出: - -```html -下一篇:title3 -``` - -### categories(List) - -#### 语法 - -```html -<#list categories as category> -// do something - -``` - -#### 参数 - -```json -[{ - "createTime": "2021-02-25T13:32:11.189Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" -}] -``` - -#### 示例 - -获取文章的分类列表: - -```html -<#list categories as category> - ${category.name!} - -``` - -输出: - -```html -name1 -name2 -``` - -### tags(List) - -#### 语法 - -```html -<#list tags as tag> -// do something - -``` - -#### 参数 - -```json -[{ - "createTime": "2021-02-25T13:34:48.779Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" -}] -``` - -#### 示例 - -获取文章的标签列表: - -```html -<#list tags as tag> - ${tag.name!} - -``` - -输出: - -```html -name1 -name2 -``` - -### metas(Object) - -#### 语法 - -```html -${metas.key} -``` - -注:attribute 代表具体 key 值。 - -#### 参数 - -无 - -#### 示例 - -获取用户设置的音乐链接: - -```html - -``` - -输出: - -```html - -``` - -## 自定义页面(sheet.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/s/{slug}` - -### sheet(Object) - -#### 语法 - -```html -${sheet.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "commentCount": 0, - "createTime": "2021-02-25T13:37:29.775Z", - "disallowComment": true, - "editTime": "2021-02-25T13:37:29.775Z", - "editorType": "MARKDOWN", - "formatContent": "string", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaIds": [ - 0 - ], - "metaKeywords": "string", - "metas": [ - { - "createTime": "2021-02-25T13:37:29.775Z", - "id": 0, - "key": "string", - "postId": 0, - "value": "string" - } - ], - "originalContent": "string", - "password": "string", - "slug": "string", - "status": "DRAFT", - "summary": "string", - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2021-02-25T13:37:29.775Z", - "visits": 0, - "wordCount": 0 -} -``` - -#### 示例 - -获取页面标题: - -```html -${sheet.title!} -``` - -输出: - -```html -示例页面 -``` - -### metas(Object) - -#### 语法 - -```html -${metas.key} -``` - -注:attribute 代表具体 key 值。 - -#### 参数 - -无 - -#### 示例 - -获取用户设置的音乐链接: - -```html - -``` - -输出: - -```html - -``` - -## 文章归档页面(archives.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/archives` - -### posts(List) - -#### 语法 - -```html -<#list posts.content as post> -// do something - -``` - -#### 参数 - -```json -[{ - "content": [{ - "categories": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-13T13:23:39.143Z", - "disallowComment": true, - "editTime": "2020-10-13T13:23:39.143Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-13T13:23:39.143Z", - "visits": 0, - "wordCount": 0 - }], - "empty": true, - "first": true, - "last": true, - "number": 0, - "numberOfElements": 0, - "pageable": { - "page": 0, - "size": 0, - "sort": [ - "string" - ] - }, - "size": 0, - "sort": { - "sort": [ - "string" - ] - }, - "totalElements": 0, - "totalPages": 0 -}] -``` - -#### 示例 - -遍历输出归档页面的文章(无年份分组): - -```html -<#list posts.content as post> - ${post.title!} - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### archives(List) - -#### 语法 - -```html -<#list archives.content as archive> -// do something - -``` - -#### 参数 - -```json -{ - "content": [{ - "posts": [{ - "categories": [{ - "createTime": "2021-03-07T05:45:06.271Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2021-03-07T05:45:06.271Z", - "disallowComment": true, - "editTime": "2021-03-07T05:45:06.271Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "DRAFT", - "summary": "string", - "tags": [{ - "createTime": "2021-03-07T05:45:06.271Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2021-03-07T05:45:06.271Z", - "visits": 0, - "wordCount": 0 - }], - "year": 0 - }], - "hasContent": true, - "hasNext": true, - "hasPrevious": true, - "isEmpty": true, - "isFirst": true, - "page": 0, - "pages": 0, - "rpp": 0, - "total": 0 -} -``` - -#### 示例 - -遍历输出归档页面的文章(有年份分组): - -```html -<#list archives.content as archive> -

    ${archive.year?c}

    - <#list archive.posts as post> - ${post.title!} - - -``` - -输出: - -```html -

    2021

    -title1 -title2 -title3 -

    2020

    -title4 -title5 -title6 -``` - -## 分类目录页面(categories.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/categories` - -此页面无页面变量,可以使用 [模板标签](/developer-guide/theme/template-tag) 获取分类列表。 - -## 单个分类所属文章页面(category.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/categories/{slug}` - -### posts(List) - -#### 语法 - -```html -<#list posts.content as post> -// do something - -``` - -#### 参数 - -```json -[{ - "content": [{ - "categories": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-13T13:23:39.143Z", - "disallowComment": true, - "editTime": "2020-10-13T13:23:39.143Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-13T13:23:39.143Z", - "visits": 0, - "wordCount": 0 - }], - "empty": true, - "first": true, - "last": true, - "number": 0, - "numberOfElements": 0, - "pageable": { - "page": 0, - "size": 0, - "sort": [ - "string" - ] - }, - "size": 0, - "sort": { - "sort": [ - "string" - ] - }, - "totalElements": 0, - "totalPages": 0 -}] -``` - -#### 示例 - -遍历输出某个分类的文章: - -```html -<#list posts.content as post> - ${post.title!} - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### category(Object) - -#### 语法 - -```html -${category.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "createTime": "2020-10-11T05:59:40.622Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string", - "postCount": 0 -} -``` - -#### 示例 - -```html -分类:${category.name!} -``` - -输出: - -```html -分类:name1 -``` - -## 标签页面(tags.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/tags` - -此页面无页面变量,可以使用 [模板标签](/developer-guide/theme/template-tag) 获取标签列表。 - -## 单个标签所属文章页面(tag.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/tags/{slug}` - -### posts(List) - -#### 语法 - -```html -<#list posts.content as post> -// do something - -``` - -#### 参数 - -```json -[{ - "content": [{ - "categories": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-13T13:23:39.143Z", - "disallowComment": true, - "editTime": "2020-10-13T13:23:39.143Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-13T13:23:39.143Z", - "visits": 0, - "wordCount": 0 - }], - "empty": true, - "first": true, - "last": true, - "number": 0, - "numberOfElements": 0, - "pageable": { - "page": 0, - "size": 0, - "sort": [ - "string" - ] - }, - "size": 0, - "sort": { - "sort": [ - "string" - ] - }, - "totalElements": 0, - "totalPages": 0 -}] -``` - -#### 示例 - -遍历输出某个标签的文章: - -```html -<#list posts.content as post> - ${post.title!} - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### tag(Object) - -#### 语法 - -```html -${tag.attribute} -``` - -注:attribute 代表具体属性。 - -#### 参数 - -```json -{ - "createTime": "2020-10-11T06:14:30.595Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" -} -``` - -#### 示例 - -```html -标签:${tag.name!} -``` - -输出: - -```html -标签:name1 -``` - -## 文章搜索结果页面(search.ftl) - -访问路径:`http://yourdomain/search?keyword=keyword` - -### keyword(String) - -#### 语法 - -```html -${keyword!} -``` - -#### 参数 - -无 - -#### 示例 - -```html -搜索关键字为:${keyword!} -``` - -### posts(List) - -#### 语法 - -```html -<#list posts.content as post> -// do something - -``` - -#### 参数 - -```json -[{ - "content": [{ - "categories": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-13T13:23:39.143Z", - "disallowComment": true, - "editTime": "2020-10-13T13:23:39.143Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-13T13:23:39.143Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-13T13:23:39.143Z", - "visits": 0, - "wordCount": 0 - }], - "empty": true, - "first": true, - "last": true, - "number": 0, - "numberOfElements": 0, - "pageable": { - "page": 0, - "size": 0, - "sort": [ - "string" - ] - }, - "size": 0, - "sort": { - "sort": [ - "string" - ] - }, - "totalElements": 0, - "totalPages": 0 -}] -``` - -#### 示例 - -遍历输出某个搜索结果的文章: - -```html -<#list posts.content as post> - ${post.title!} - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -## 友情链接页面(links.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/links` - -此页面无页面变量,可以使用 [模板标签](/developer-guide/theme/template-tag) 获取友情链接列表。 - -## 图库页面(photos.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/photos` - -### photos(List) - -#### 语法 - -```html -<#list photos.content as photo> -// do something - -``` - -#### 参数 - -```json -{ - "content": [{ - "description": "string", - "id": 0, - "location": "string", - "name": "string", - "takeTime": "2021-03-07T05:28:12.352Z", - "team": "string", - "thumbnail": "string", - "url": "string" - }], - "hasContent": true, - "hasNext": true, - "hasPrevious": true, - "isEmpty": true, - "isFirst": true, - "page": 0, - "pages": 0, - "rpp": 0, - "total": 0 -} -``` - -#### 示例 - -```html -<#list photos.content as photo> - ${photo.description!} - -``` - -输出: - -```html -山川 -河流 -绿树 -``` - -## 日志页面(journals.ftl) - -访问路径不固定,视固定链接配置而定,默认为:`http://yourdomain/journals` - -### journals(List) - -#### 语法 - -```html -<#list journals.content as journal> -// do something - -``` - -#### 参数 - -```json -{ - "content": [{ - "commentCount": 0, - "content": "string", - "createTime": "2021-03-07T05:32:06.365Z", - "id": 0, - "likes": 0, - "sourceContent": "string", - "type": "INTIMATE" - }], - "hasContent": true, - "hasNext": true, - "hasPrevious": true, - "isEmpty": true, - "isFirst": true, - "page": 0, - "pages": 0, - "rpp": 0, - "total": 0 -} -``` - -#### 示例 - -```html -
      - <#list journals.content as journal> -
    • - ${journal.createTime?string('yyyy年MM月dd日')}:${journal.content!} -
    • - -
    -``` - -输出: - -```html -
      -
    • - 2021年3月7日:内容1 -
    • -
    • - 2021年3月7日:内容2 -
    • -
    -``` diff --git a/docs/developer-guide/theme/prepare.md b/docs/developer-guide/theme/prepare.md index 22b9426..15285cd 100644 --- a/docs/developer-guide/theme/prepare.md +++ b/docs/developer-guide/theme/prepare.md @@ -11,47 +11,34 @@ Halo 在本地开发环境的运行可参考[开发环境运行](../core/run.md) ## 新建一个主题 -Halo 的主题存放于工作目录的 `themes` 目录下,即 `~/halo-next/themes`,在该目录下新建一个文件夹,例如 `theme-foo`。当前一个最小可被系统加载的主题必须在主题根目录下包含 `theme.yaml` 配置文件。 - -以 [theme-default](https://github.com/halo-sigs/theme-default) 为例: +Halo 的主题存放于工作目录的 `themes` 目录下,即 `~/halo2-dev/themes`,在该目录下新建一个文件夹,例如 `theme-foo`。当前一个最小可被系统加载的主题必须在主题根目录下包含 `theme.yaml` 配置文件。 ```yaml title="theme.yaml" apiVersion: theme.halo.run/v1alpha1 kind: Theme metadata: - name: theme-default + name: theme-foo spec: - displayName: Default + displayName: 示例主题 author: name: halo-dev website: https://halo.run - description: Default theme for Halo 2.0 + description: 一个示例主题 logo: https://halo.run/logo - website: https://github.com/halo-sigs/theme-default - repo: https://github.com/halo-sigs/theme-default.git - settingName: "theme-default-setting" - configMapName: "theme-default-configMap" + website: https://github.com/halo-sigs/theme-foo + repo: https://github.com/halo-sigs/theme-foo.git + settingName: "theme-foo-setting" + configMapName: "theme-foo-configMap" version: 1.0.0 require: 2.0.0 ``` -| 字段 | 描述 | 是否必填 | -| --------------------- | ----------------------------------------------------------- | -------- | -| `metadata.name` | 主题的唯一标识 | 是 | -| `spec.displayName` | 显示名称 | 是 | -| `spec.author.name` | 作者名称 | 否 | -| `spec.author.website` | 作者网站 | 否 | -| `spec.description` | 主题描述 | 否 | -| `spec.logo` | 主题 Logo | 否 | -| `spec.website` | 主题网站 | 否 | -| `spec.repo` | 主题托管地址 | 否 | -| `spec.settingName` | 设置表单定义的名称,需要同时创建对应的 `settings.yaml` 文件 | 否 | -| `spec.configMapName` | 设置持久化的 ConfigMap 名称 | 否 | -| `spec.version` | 主题版本 | 是 | -| `spec.require` | 所需 Halo 的运行版本 | 是 | +:::info 提示 +主题的配置文件详细文档请参考 [配置文件](./config.md)。 +::: :::info 提示 -关于主题项目的目录结构请参考[主题目录结构](./structure.md)。 +主题项目的目录结构请参考 [主题目录结构](./structure.md)。 ::: ## 通过模板创建 @@ -69,7 +56,7 @@ spec: ## 创建第一个页面模板 -Halo 使用 [Thymeleaf](https://www.thymeleaf.org/) 作为后端模板引擎,后缀为 `.html`,与单纯编写 HTMl 一致。在 Halo 的主题中,主题的模板文件存放于 `templates` 目录下,例如 `~/halo-next/themes/theme-foo/templates`。为了此文档方便演示,我们先在 `templates` 创建一个首页的模板文件 `index.html`: +Halo 使用 [Thymeleaf](https://www.thymeleaf.org/) 作为后端模板引擎,后缀为 `.html`,与单纯编写 HTML 一致。在 Halo 的主题中,主题的模板文件存放于 `templates` 目录下,例如 `~/halo2-dev/themes/theme-foo/templates`。为了此文档方便演示,我们先在 `templates` 创建一个首页的模板文件 `index.html`: ```html title="templates/index.html" diff --git a/docs/developer-guide/theme/public-template-tag.md b/docs/developer-guide/theme/public-template-tag.md deleted file mode 100644 index 515a72a..0000000 --- a/docs/developer-guide/theme/public-template-tag.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: 公共宏模板 -description: 系统提供的一些宏模板 ---- - -> 为了减少重复代码,我们将某些常见的全局变量封装成了一个公共模板,我们只需要引入该模板,然后调用其中的宏模板即可。 - -## 公共 head 模板 - -> 需要注意的是,为了保证系统功能的完整性,我们强制要求在每个页面的 `` 标签下必须包含此模板。 - -```html -<@global.head /> -``` - -等同于: - -```html -<#if options.seo_spider_disabled!false> - - - -<@global.favicon /> -<@global.custom_head /> -<@global.custom_content_head /> -``` - -## 公共底部 - -> 需要注意的是,为了保证系统功能的完整性,我们强制要求在每个页面的尾部必须包含此模板。 - -```html -<@global.footer /> -``` - -等同于: - -```html -<@global.statistics /> -<@global.footer_info /> -```` - -## 相对时间 - -```html -<@global.timeline datetime="时间" /> - -// 输出 -x 年前/x 个月前/x 天前/昨天/x 小时前/x 分钟前/x 秒前/刚刚 -``` - -## 评论模块 - -```html -<@global.comment target= type="" /> -``` - -等同于: - -```html -<#if !post.disallowComment!false> - - - - -``` - -参数说明: - -- target:post / sheet / journal 对象 -- type:评论类型,可为:post / sheet / journal - -例子: - -在文章页面(post.ftl or post_xxx.ftl): - -```html -<@global.comment target=post type="post" /> -``` - -在自定义页面(sheet.ftl or post_sheet.ftl): - -```html -<@global.comment target=sheet type="sheet" /> -``` - -在日志页面(journals.ftl): - -```html -<@global.comment target=journal type="journal" /> -``` diff --git a/docs/developer-guide/theme/settings.md b/docs/developer-guide/theme/settings.md new file mode 100644 index 0000000..4f10b01 --- /dev/null +++ b/docs/developer-guide/theme/settings.md @@ -0,0 +1,129 @@ +--- +title: 设置选项 +description: 介绍主题如何定义以及使用设置选项。 +--- + +此文档将讲解如何在主题中定义和使用设置项,如 [表单定义](../form-schema) 中所说,目前 Halo 的 Console 端的所有表单都使用了 [FormKit](https://github.com/formkit/formkit) 的方案。 + +:::tip +有关 FormKit 定义表单的更多信息,请参考 [表单定义](../form-schema),此文档仅针对主题中的设置项进行讲解。 +::: + +## 定义表单 + +在主题中要使用设置项非常简单,只需要在主题根目录提供 `settings.yaml`,然后在 `theme.yaml` 中配置 `spec.settingName` 和 `spec.configMapName` 即可,在安装或者初始化主题的时候会自动识别并在 Console 端的主题设置中生成表单。 + +### 示例 + +```yaml title="theme-foo/theme.yaml" {14,15} +apiVersion: theme.halo.run/v1alpha1 +kind: Theme +metadata: + name: theme-foo +spec: + displayName: 示例主题 + author: + name: halo-dev + website: https://halo.run + description: 一个示例主题 + logo: https://halo.run/logo + website: https://github.com/halo-sigs/theme-foo + repo: https://github.com/halo-sigs/theme-foo.git + settingName: "theme-foo-setting" + configMapName: "theme-foo-configMap" + version: 1.0.0 + require: 2.0.0 +``` + +:::tip +`settingName` 和 `configMapName` 必须同时配置,且可以自定义名称,但是 `settingName` 必须和 Setting 的 `metadata.name` 一致。 +::: + +```yaml title="theme-foo/settings.yaml" {4} +apiVersion: v1alpha1 +kind: Setting +metadata: + name: theme-foo-setting +spec: + forms: + - group: style + label: 样式 + formSchema: + - $formkit: radio + name: color_scheme + label: 默认配色 + value: system + options: + - label: 跟随系统 + value: system + - label: 深色 + value: dark + - label: 浅色 + value: light + - $formkit: color + name: background_color + label: 背景颜色 + value: "#f2f2f2" + - group: layout + label: 布局 + formSchema: + - $formkit: radio + name: nav + label: 导航栏布局 + value: "single" + options: + - label: 单栏 + value: "single" + - label: 双栏 + value: "double" +``` + +:::tip +Setting 资源的 `metadata.name` 必须和 `theme.yaml` 中的 `spec.settingName` 一致。 +::: + +### 在主题模板中使用 + +在主题模板中,需要以 `theme.config.[group].[name]` 的形式进行调用。 + +其中: + +1. `group`: 即 `spec.forms[].group`,如上面示例中的 `style` 和 `layout`。 +2. `name`: 即 `spec.forms[].formSchema[].name`,如上面示例中的 `color_scheme` 和 `nav`。 + +示例: + +```html + + + +``` + +```html +
      + +
    + +
    + +
    +``` + +## 从 1.x 迁移 + +为了方便主题开发者从 1.x 迁移,我们提供了工具用于迁移设置表单配置文件。 + +工具仓库地址: + +```bash +# 1.x 版本主题 +cd path/to/theme + +npx @halo-dev/convert-theme-config-to-next settings +``` + +执行完成之后即可看到主题目录下生成了 `settings.2.0.yaml` 文件,重命名为 `settings.yaml` 即可。 + +:::tip +转换完成之后需要修改 `metadata.name` 字段。 +::: diff --git a/docs/developer-guide/theme/static-resources.md b/docs/developer-guide/theme/static-resources.md new file mode 100644 index 0000000..b9ec636 --- /dev/null +++ b/docs/developer-guide/theme/static-resources.md @@ -0,0 +1,55 @@ +--- +title: 静态资源 +description: 本文档介绍主题的静态资源的引用方法。 +--- + +通过 [目录结构](./structure.md) 的讲解我们可以知道,目前主题的静态资源统一托管在 `/templates/assets/` 目录下,下面讲解一下如何在模板中使用,大致会分为两种引入方式。 + +## 模板标签引用 + +```html + + + + +``` + +其中 `@{/assets/dist/style.css}` 表示引用 `/templates/assets/dist/style.css` 文件。最终会被渲染为: + +```html + +``` + +## API 引用 + +以上方式仅支持在 HTML 标签中使用,且必须使用 `@{}` 包裹才能渲染为正确的路径。如果需要在非 HTML 标签中得到正确的路径,我们提供了 `#theme.assets()` API。 + +:::info 注意 +需要注意的是,调用 `#theme.assets()` 的时候,资源地址不需要添加 `/assets/`。 +::: + +比如我们需要在 JavaScript 中异步获取一些资源: + +```html {3} + +``` + +:::info 提示 +关于在 JavaScript 中使用 Thymeleaf 语法可以参考 Thymeleaf 官方文档:[JavaScript inlining](https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html#javascript-inlining) +::: diff --git a/docs/developer-guide/theme/structure.md b/docs/developer-guide/theme/structure.md index bc65c32..ac5efe9 100644 --- a/docs/developer-guide/theme/structure.md +++ b/docs/developer-guide/theme/structure.md @@ -5,7 +5,7 @@ description: 主题的目录结构介绍 Halo 2.0 的主题基本目录结构如下: -```bash title="~/halo-next/themes/my-theme" +```bash title="~/halo2-dev/themes/my-theme" my-theme ├── templates/ │ ├── assets/ @@ -27,7 +27,7 @@ my-theme 详细说明: -1. `/templates/` - 主题模板目录,存放主题模板文件,所有模板都需要放在这个目录。 -2. `/templates/assets/` - 主题静态资源目录,存放主题的静态资源文件,目前静态资源文件只能放在这个目录。 -3. `/theme.yaml` - 主题配置文件,配置主题的基本信息,如主题名称、版本、作者等。 -4. `/settings.yaml` - 主题设置定义文件,配置主题的设置项表单。 +1. `/templates/` - 主题模板目录,存放主题模板文件,所有模板都需要放在这个目录。关于模板的详细说明,请查阅 [模板路由](./template-route-mapping)。 +2. `/templates/assets/` - 主题静态资源目录,存放主题的静态资源文件,目前静态资源文件只能放在这个目录,引用方式请查阅 [静态资源](./static-resources)。 +3. `/theme.yaml` - 主题配置文件,配置主题的基本信息,如主题名称、版本、作者等。详细文档请查阅 [配置文件](./config)。 +4. `/settings.yaml` - 主题设置定义文件,配置主题的设置项表单。详细文档请查阅 [设置选项](./settings)。 diff --git a/docs/developer-guide/theme/template-route-mapping.md b/docs/developer-guide/theme/template-route-mapping.md new file mode 100644 index 0000000..95b0ddc --- /dev/null +++ b/docs/developer-guide/theme/template-route-mapping.md @@ -0,0 +1,87 @@ +--- +title: 模板路由 +description: 本文档介绍路由与模板的映射关系,以及自定义模板。 +--- + +此文档讲解系统内部提供的路由与模板映射。 + +## 主要模板 + +### index.html + +站点的首页模板,访问地址为 `/`。 + +### post.html + +文章详情页面的模板,访问地址默认为 `/archives/:slug`。 + +### page.html + +独立页面详情的模板,访问地址默认为 `/:slug`。 + +### archives.html + +文章归档页面的模板,访问地址包括: + +- `/archives` +- `/archives/:year` +- `/archives/:year/:month` + +### tags.html + +标签集合页面的模板,访问地址默认为 `/tags`。 + +### tag.html + +标签归档页面的模板,访问地址默认为 `/tags/:slug`。 + +### categories.html + +分类集合页面的模板,访问地址默认为 `/categories`。 + +### category.html + +分类归档页面的模板,访问地址默认为 `/categories/:slug`。 + +## 自定义模板 {#custom-templates} + +一般情况下,上文提到的模板已经能够满足大部分的需求,但如果需要针对某个特定的页面进行自定义,可以通过自定义模板来实现。目前系统支持为 **文章**、**独立页面**和**分类归档** 设置自定义模板: + +在 `theme.yaml` 的 `spec` 节点下添加如下配置: + +```yaml +customTemplates: + {type}: + - name: {name} + description: {description} + screenshot: {screenshot} + file: {file}.html +``` + +示例: + +```yaml +customTemplates: + post: + - name: 文档 + description: 文档类型的文章 + screenshot: + file: post_documentation.html +``` + +字段说明: + +- `type`:模板类型,目前支持 `post` `page` `category`。 +- `name`:模板名称 +- `description`:模板描述 +- `screenshot`:模板预览图 +- `file`:模板文件名,需要在 `/templates/` 目录下创建 + +最终使用者即可在文章设置、独立页面设置、分类设置中选择自定义模板。 + +:::info 提示 + +1. 自定义模板与默认模板的功能相同,区别仅在于可以让使用者选择不同于默认模板风格的模板。 +2. 自定义模板的文件名需要以 `.html` 结尾,且需要在 `/templates/` 目录下创建。 + +::: diff --git a/docs/developer-guide/theme/template-tag.md b/docs/developer-guide/theme/template-tag.md deleted file mode 100644 index 9d45043..0000000 --- a/docs/developer-guide/theme/template-tag.md +++ /dev/null @@ -1,2746 +0,0 @@ ---- -title: 模板标签 -description: 用于获取数据的模板标签 ---- - -:::note -模板标签可以运用在页面的任何地方。 -::: - -## 文章(postTag) - -### 获取最新文章(latest) - -#### 语法 - -```html -<@postTag method="latest" top="获取条数"> -// do something - -``` - -参数: - -1. method:latest -2. top:所需要获取的条数 - -#### 返回参数 - -posts: - -```json -[{ - "categories": [{ - "createTime": "2020-10-11T05:22:08.264Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:22:08.264Z", - "disallowComment": true, - "editTime": "2020-10-11T05:22:08.264Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:22:08.264Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:22:08.264Z", - "visits": 0, - "wordCount": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="latest" top="3"> - <#list posts as post> - ${post.title!} - - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### 获取所有文章的数量(count) - -#### 语法 - -```html -<@postTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@postTag method="count"> -文章数量:${count!0} - -``` - -输出: - -```html -文章数量:20 -``` - -### 根据年份归档(archiveYear) - -#### 语法 - -```html -<@postTag method="archiveYear"> -// do something - -``` - -参数: - -1. method:archiveYear - -#### 返回参数 - -archives: - -```json -[{ - "posts": [{ - "categories": [{ - "createTime": "2020-10-11T05:30:45.245Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:30:45.245Z", - "disallowComment": true, - "editTime": "2020-10-11T05:30:45.245Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:30:45.245Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:30:45.245Z", - "visits": 0, - "wordCount": 0 - }], - "year": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="archiveYear"> - <#list archives as archive> -

    年份: ${archive.year?c}

    -
      - <#list archive.posts?sort_by("createTime")?reverse as post> -
    • - ${post.title!} -
    • - -
    - - -``` - -输出: - -```html -

    2019

    - -

    2018

    - -``` - -### 根据年月归档(archiveMonth) - -#### 语法 - -```html -<@postTag method="archiveMonth"> -// do something - -``` - -参数: - -1. method:archiveMonth - -#### 返回参数 - -archives: - -```json -[{ - "month": 0, - "posts": [{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.835Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.835Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.835Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.835Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.835Z", - "visits": 0, - "wordCount": 0 - }], - "year": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="archiveMonth"> - <#list archives as archive> -

    ${archive.year?c}-${archive.month?c}

    -
      - <#list archive.posts?sort_by("createTime")?reverse as post> -
    • - ${post.title!} -
    • - -
    - - -``` - -输出: - -```html -

    2019-01

    - -

    2018-12

    - -``` - -### 归档(archive) - -#### 语法 - -```html -<@postTag method="archive" type="year or month"> -// do something - -``` - -参数: - -1. method:archive -2. type: `year` 或者 `month` - -#### 返回参数 - -archives(year): - -```json -[{ - "posts": [{ - "categories": [{ - "createTime": "2020-10-11T05:30:45.245Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:30:45.245Z", - "disallowComment": true, - "editTime": "2020-10-11T05:30:45.245Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:30:45.245Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:30:45.245Z", - "visits": 0, - "wordCount": 0 - }], - "year": 0 -}] -``` - -archives(month): - -```json -[{ - "month": 0, - "posts": [{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.835Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.835Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.835Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.835Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.835Z", - "visits": 0, - "wordCount": 0 - }], - "year": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="archive" type="month"> - <#list archives as archive> -

    ${archive.year?c}-${archive.month?c}

    -
      - <#list archive.posts?sort_by("createTime")?reverse as post> -
    • - ${post.title!} -
    • - -
    - - -``` - -输出: - -```html -

    2019-01

    - -

    2018-12

    - -``` - -### 根据分类 id 获取文章(listByCategoryId) - -#### 语法 - -```html -<@postTag method="listByCategoryId" categoryId="分类 id"> -// do something - -``` - -参数: - -1. method:listByCategoryId -2. categoryId:分类 id - -#### 返回参数 - -posts: - -```json -[{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.811Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.811Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.811Z", - "visits": 0, - "wordCount": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="listByCategoryId" top="${category.id?c}"> - 分类 ${category.name!} 下的文章: - <#list posts as post> - ${post.title!} - - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### 根据分类 slug 获取文章(listByCategorySlug) - -#### 语法 - -```html -<@postTag method="listByCategorySlug" categorySlug="分类 slug"> -// do something - -``` - -参数: - -1. method:listByCategorySlug -2. categorySlug:分类 slug - -#### 返回参数 - -posts: - -```json -[{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.811Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.811Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.811Z", - "visits": 0, - "wordCount": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="listByCategorySlug" categorySlug="${category.slug!}"> - 分类 ${category.name!} 下的文章: - <#list posts as post> - ${post.title!} - - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### 根据标签 id 获取文章(listByTagId) - -#### 语法 - -```html -<@postTag method="listByTagId" tagId="标签 id"> -// do something - -``` - -参数: - -1. method:listByTagId -2. tagId:标签 id - -#### 返回参数 - -posts: - -```json -[{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.811Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.811Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.811Z", - "visits": 0, - "wordCount": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="listByTagId" tagId="${tag.id?c}"> - 标签 ${tag.name!} 下的文章: - <#list posts as post> - ${post.title!} - - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -### 根据标签 slug 获取文章(listByTagSlug) - -#### 语法 - -```html -<@postTag method="listByTagSlug" tagSlug="标签 slug"> -// do something - -``` - -参数: - -1. method:listByTagSlug -2. tagSlug:标签 slug - -#### 返回参数 - -posts: - -```json -[{ - "categories": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" - }], - "commentCount": 0, - "createTime": "2020-10-11T05:35:01.811Z", - "disallowComment": true, - "editTime": "2020-10-11T05:35:01.811Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "likes": 0, - "metaDescription": "string", - "metaKeywords": "string", - "metas": {}, - "password": "string", - "slug": "string", - "status": "PUBLISHED", - "summary": "string", - "tags": [{ - "createTime": "2020-10-11T05:35:01.811Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" - }], - "template": "string", - "thumbnail": "string", - "title": "string", - "topPriority": 0, - "topped": true, - "updateTime": "2020-10-11T05:35:01.811Z", - "visits": 0, - "wordCount": 0 -}] -``` - -#### 示例 - -```html -<@postTag method="listByTagSlug" tagSlug="${tag.slug!}"> - 标签 ${tag.name!} 下的文章: - <#list posts as post> - ${post.title!} - - -``` - -输出: - -```html -title1 -title2 -title3 -``` - -## 评论(commentTag) - -### 获取最新评论(latest) - -#### 语法 - -```html -<@commentTag method="latest" top="获取条数"> -// do something - -``` - -参数: - -1. method:latest -2. top:所需要获取的条数 - -#### 返回参数 - -comments: - -```json -[{ - "allowNotification": true, - "author": "string", - "authorUrl": "string", - "content": "string", - "createTime": "2020-10-13T12:35:54.974Z", - "email": "string", - "gravatarMd5": "string", - "id": 0, - "ipAddress": "string", - "isAdmin": true, - "parentId": 0, - "post": { - "createTime": "2020-10-13T12:35:54.974Z", - "editTime": "2020-10-13T12:35:54.974Z", - "editorType": "MARKDOWN", - "fullPath": "string", - "id": 0, - "metaDescription": "string", - "metaKeywords": "string", - "slug": "string", - "status": "PUBLISHED", - "title": "string", - "updateTime": "2020-10-13T12:35:54.974Z" - }, - "status": "PUBLISHED", - "userAgent": "string" -}] -``` - -#### 示例 - -```html -<@commentTag method="latest" top="获取条数"> -
      - <#list comments.content as comment> -
    • ${comment.author!}:${comment.content!}
    • - -
    - -``` - -输出: - -```html -
      -
    • author1:content1
    • -
    • author2:content2
    • -
    -``` - -### 获取所有评论的数量(count) - -#### 语法 - -```html -<@commentTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@commentTag method="count"> -评论数量:${count!0} - -``` - -输出: - -```html -文章数量:20 -``` - -## 分类目录(categoryTag) - -### 获取所有分类目录(list) - -#### 语法 - -```html -<@categoryTag method="list"> -// do something - -``` - -参数: - -1. method:list - -#### 返回参数 - -categories: - -```json -[{ - "createTime": "2020-10-11T05:59:40.622Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string", - "postCount": 0 -}] -``` - -#### 示例 - -```html -<@categoryTag method="list"> - <#list categories as category> - ${category.name!}(${category.postCount!}) - - -``` - -输出: - -```html -name1(2) -name2(12) -``` - -### 获取分类目录树结构(tree) - -#### 语法 - -```html -<@categoryTag method="tree"> -// do something - -``` - -参数: - -1. method:tree - -#### 返回参数 - -categories: - -```json -[ - { - "children": [ - { - "children": [], - "createTime": "2022-02-12T14:11:06.376Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - } - ], - "createTime": "2022-02-12T14:11:06.376Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "password": "string", - "slug": "string", - "thumbnail": "string" - } -] -``` - -#### 示例 - -```html -<@categoryTag method="tree"> -
      - <#list categories as category> -
    • - - ${category.name!} - -
    • - - <#if category.children?? && category.children?size gt 0> - <@renderCategories category.children> - - -
    - - -<#macro renderCategories categories> -
      - <#list categories as category> -
    • - - ${(category.name)!} - - <#if category.children?? && category.children?size gt 0> - <@renderCategories category.children> - -
    • - -
    - -``` - -输出: - -```html - -``` - -### 获取文章的所有分类(listByPostId) - -#### 语法 - -```html -<@categoryTag method="listByPostId" postId="文章 id"> -// do something - -``` - -参数: - -1. method:listByPostId -2. postId:文章 id - -#### 返回参数 - -categories: - -```json -[{ - "createTime": "2020-10-11T05:59:40.622Z", - "description": "string", - "fullPath": "string", - "id": 0, - "name": "string", - "parentId": 0, - "slug": "string", - "thumbnail": "string" -}] -``` - -#### 示例 - -```html -<@categoryTag method="listByPostId" postId="${post.id?c}"> - <#list categories as category> - ${category.name} - - -``` - -输出: - -```html -name1 -name2 -``` - -### 获取所有分类的数量(count) - -#### 语法 - -```html -<@categoryTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@categoryTag method="count"> -分类数量:${count!0} - -``` - -输出: - -```html -分类数量:20 -``` - -## 标签(tagTag) - -### 获取所有标签(list) - -#### 语法 - -```html -<@tagTag method="list"> -// 返回参数:tags - -``` - -参数: - -1. method:list - -#### 返回参数 - -tags: - -```json -[{ - "createTime": "2020-10-11T06:14:30.595Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string", - "postCount": 0 -}] -``` - -#### 示例 - -```html -<@tagTag method="list"> - <#list tags as tag> - ${tag.name!}(${tag.postCount!}) - - -``` - -输出: - -```html -name1(1) -name2(20) -``` - -### 获取文章的所有标签(listByPostId) - -#### 语法 - -```html -<@tagTag method="listByPostId" postId="文章 id"> -// do something - -``` - -参数: - -1. method:listByPostId -2. postId:文章 id - -#### 返回参数 - -tags: - -```json -[{ - "createTime": "2020-10-11T06:14:30.595Z", - "fullPath": "string", - "id": 0, - "name": "string", - "slug": "string", - "thumbnail": "string" -}] -``` - -#### 示例 - -```html -<@tagTag method="listByPostId" postId="${post.id?c}"> - <#list tags as tag> - ${tag.name} - - -``` - -输出: - -```html -name1 -name2 -``` - -### 获取所有标签的数量(count) - -#### 语法 - -```html -<@tagTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@tagTag method="count"> -标签数量:${count!0} - -``` - -输出: - -```html -标签数量:20 -``` - -## 菜单(menuTag) - -### 获取所有菜单(list) - -#### 语法 - -```html -<@menuTag method="list"> -// do something - -``` - -参数: - -1. method:list - -#### 返回参数 - -menus: - -```json -[{ - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" -}] -``` - -#### 示例 - -```html -<@menuTag method="list"> - - -``` - -输出: - -```html - -``` - -### 获取多级菜单(tree) - -#### 语法 - -```html -<@menuTag method="tree"> -// do something - -``` - -参数: - -1. method:tree - -#### 返回参数 - -menus: - -```json -[{ - "children": [{ - "children": [{}], - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" - }], - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" -}] -``` - -#### 示例 - -```html -<@menuTag method="tree"> -
      - <#list menus as menu> -
    • - ${menu.name!} - <#if menu.children?? && menu.children?size gt 0> - - -
    • - -
    - -``` - -输出: - -```html - -``` - -### 根据分组获取菜单(listByTeam) - -#### 语法 - -```html -<@menuTag method="listByTeam" team="team 名称"> -// do something - -``` - -参数: - -1. method:listByTeam -2. team:team 名称 - -#### 返回参数 - -menus: - -```json -[{ - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" -}] -``` - -#### 示例 - -```html -<@menuTag method="listByTeam" team="main"> - - -``` - -输出: - -```html - -``` - -### 根据分组获取多级菜单(treeByTeam) - -#### 语法 - -```html -<@menuTag method="treeByTeam" team="team 名称"> -// do something - -``` - -参数: - -1. method:treeByTeam -2. team:team 名称 - -#### 返回参数 - -menus: - -```json -[{ - "children": [{ - "children": [{}], - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" - }], - "icon": "string", - "id": 0, - "name": "string", - "parentId": 0, - "priority": 0, - "target": "string", - "team": "string", - "url": "string" -}] -``` - -#### 示例 - -```html -<@menuTag method="treeByTeam" team="main"> -
      - <#list menus as menu> -
    • - ${menu.name!} - <#if menu.children?? && menu.children?size gt 0> - - -
    • - -
    - -``` - -输出: - -```html - -``` - -## 友情链接(linkTag) - -### 获取所有友情链接(list) - -#### 语法 - -```html -<@linkTag method="list"> -// do something - -``` - -参数: - -1. method:list - -#### 返回参数 - -links: - -```json -[{ - "id": 0, - "name": "string", - "url": "string", - "logo": "string", - "description": "string", - "team": "string", - "priority": 0, - "createTime": "2021-01-10 20:48:00", - "updateTime": "2021-01-10 20:48:00" -}] -``` - -#### 示例 - -```html - -``` - -输出: - -```html - -``` - -### 乱序获取所有友情链接(listByRandom) - -#### 语法 - -```html -<@linkTag method="listByRandom"> -// do something - -``` - -参数: - -1. method:listByRandom - -#### 返回参数 - -```json -[{ - "id": 0, - "name": "string", - "url": "string", - "logo": "string", - "description": "string", - "team": "string", - "priority": 0, - "createTime": "2021-01-10 20:48:00", - "updateTime": "2021-01-10 20:48:00" -}] -``` - -#### 示例 - -```html - -``` - -输出: - -```html - -``` - -### 获取分组友情链接(listTeams) - -#### 语法 - -```html -<@linkTag method="listTeams"> -// do something - -``` - -参数: - -1. method:listTeams - -#### 返回参数 - -teams: - -```json -[{ - "team": "string", - "links": [{ - "id": 0, - "name": "string", - "url": "string", - "logo": "string", - "description": "string", - "team": "string", - "priority": 0 - }] -}] -``` - -#### 示例 - -```html -<@linkTag method="listTeams"> - <#list teams as team> -

    ${team.team}

    - - - -``` - -输出: - -```html -

    Halo 相关

    - -

    网友们

    - -``` - -### 乱序获取分组友情链接(listTeamsByRandom) - -#### 语法 - -```html -<@linkTag method="listTeamsByRandom"> -// do something - -``` - -参数: - -1. method:listTeamsByRandom - -#### 返回参数 - -teams: - -```json -[{ - "team": "string", - "links": [{ - "id": 0, - "name": "string", - "url": "string", - "logo": "string", - "description": "string", - "team": "string", - "priority": 0 - }] -}] -``` - -#### 示例 - -```html -<@linkTag method="listTeamsByRandom"> - <#list teams as team> -

    ${team.team}

    - - - -``` - -输出: - -```html -

    Halo 相关

    - -

    网友们

    - -``` - -### 获取所有友情链接的数量(count) - -#### 语法 - -```html -<@linkTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@linkTag method="count"> -友情链接数量:${count!0} - -``` - -输出: - -```html -友情链接数量:20 -``` - -## 图库(photoTag) - -### 获取所有图片(list) - -#### 语法 - -```html -<@photoTag method="list"> -// do something - -``` - -参数: - -1. method:list - -#### 返回参数 - -photos: - -```json -[{ - "id": 0, - "name": "string", - "description": "string", - "takeTime": "2021-01-10 20:48:00", - "location": "string", - "thumbnail": "string", - "url": "string", - "team": "string", - "createTime": "2021-01-10 20:48:00", - "updateTime": "2021-01-10 20:48:00" -}] -``` - -#### 示例 - -```html -<@photoTag method="list"> - <#list photos as photo> - ${photo.description} - - -``` - -输出: - -```html -山川 -河流 -绿树 -``` - -### 获取所有分组图片(listTeams) - -#### 语法 - -```html -<@photoTag method="listTeams"> -// do something - -``` - -参数: - -1. method:listTeams - -#### 返回参数 - -teams: - -```json -[{ - "team": "string", - "photos": [{ - "id": 0, - "name": "string", - "thumbnail": "string", - "takeTime": "2021-01-10 20:48:00", - "url": "string", - "team": "string", - "location": "string", - "description": "string" - }] -}] -``` - -#### 示例 - -```html -<@photoTag method="listTeams"> - <#list teams as team> -

    ${team.team}

    - <#list team.photos as photo> - ${photo.description} - - - -``` - -输出: - -```html -

    风景

    -山川 -河流 -绿树 -

    旅行

    -四川 -重庆 -深圳 -``` - -### 根据分组获取图片(listByTeam) - -#### 语法 - -```html -<@photoTag method="listByTeam" team="team 名称"> -// do something - -``` - -参数: - -1. method:listByTeam -2. team:team 名称 - -#### 返回参数 - -photos: - -```json -[{ - "id": 0, - "name": "string", - "description": "string", - "takeTime": "2021-01-10 20:48:00", - "location": "string", - "thumbnail": "string", - "url": "string", - "team": "string", - "createTime": "2021-01-10 20:48:00", - "updateTime": "2021-01-10 20:48:00" -}] -``` - -#### 示例 - -```html -<@photoTag method="listByTeam" team="风景"> - <#list photos as photo> - ${photo.description} - - -``` - -输出: - -```html -山川 -河流 -绿树 -``` - -### 获取所有图片的数量(count) - -#### 语法 - -```html -<@photoTag method="count"> -// do something - -``` - -参数: - -1. method:count - -#### 返回参数 - -```json -count: long -``` - -#### 示例 - -```html -<@linkTag method="count"> -图片数量:${count!0} - -``` - -输出: - -```html -图片数量:20 -``` - -## 分页(paginationTag) - -### 获取首页文章列表的分页数据(index) - -#### 语法 - -```html -<@paginationTag method="index" page="${posts.number}" total="${posts.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:index -2. page:当前页,通过 `${posts.number}` 得到 -3. total:总页数,通过 `${posts.totalPages}` 得到 -4. display:页码展示数量 - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="index" page="${posts.number}" total="${posts.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取文章归档列表的分页数据(archives) - -#### 语法 - -```html -<@paginationTag method="archives" page="${posts.number}" total="${posts.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:archives -2. page:当前页,通过 `${posts.number}` 得到 -3. total:总页数,通过 `${posts.totalPages}` 得到 -4. display:页码展示数量 - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="archives" page="${posts.number}" total="${posts.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取搜索结果文章列表的分页数据(search) - -#### 语法 - -```html -<@paginationTag method="search" page="${posts.number}" total="${posts.totalPages}" keyword="${keyword}" display="3"> -// do something - -``` - -参数: - -1. method:search -2. page:当前页,通过 `${posts.number}` 得到 -3. total:总页数,通过 `${posts.totalPages}` 得到 -4. keyword: 关键词 -5. display:页码展示数量 - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="search" page="${posts.number}" total="${posts.totalPages}" keyword="${keyword}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取标签下文章列表的分页数据(tagPosts) - -#### 语法 - -```html -<@paginationTag method="tagPosts" slug="${tag.slug!}" page="${posts.number}" total="${posts.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:tagPosts -2. page:当前页,通过 `${posts.number}` 得到 -3. total:总页数,通过 `${posts.totalPages}` 得到 -4. display:页码展示数量 -5. slug:标签 slug - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="tagPosts" slug="${tag.slug!}" page="${posts.number}" total="${posts.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取分类下文章列表的分页数据(categoryPosts) - -#### 语法 - -```html -<@paginationTag method="categoryPosts" slug="${category.slug!}" page="${posts.number}" total="${posts.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:categoryPosts -2. page:当前页,通过 `${posts.number}` 得到 -3. total:总页数,通过 `${posts.totalPages}` 得到 -4. display:页码展示数量 -5. slug:标签 slug - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="categoryPosts" slug="${category.slug!}" page="${posts.number}" total="${posts.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取图库页面图片列表的分页数据(photos) - -#### 语法 - -```html -<@paginationTag method="photos" page="${photos.number}" total="${photos.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:photos -2. page:当前页,通过 `${photos.number}` 得到 -3. total:总页数,通过 `${photos.totalPages}` 得到 -4. display:页码展示数量 - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="photos" page="${photos.number}" total="${photos.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` - -### 获取日志页面日志列表的分页数据(journals) - -#### 语法 - -```html -<@paginationTag method="journals" page="${journals.number}" total="${journals.totalPages}" display="3"> -// do something - -``` - -参数: - -1. method:journals -2. page:当前页,通过 `${journals.number}` 得到 -3. total:总页数,通过 `${journals.totalPages}` 得到 -4. display:页码展示数量 - -#### 返回参数 - -pagination: - -```json -{ - "nextPageFullPath": "string", - "prevPageFullPath": "string", - "hasPrev": true, - "hasNext": true, - "rainbowPages": [{ - "page": 0, - "fullPath": "string", - "isCurrent": true - }] -} -``` - -#### 示例 - -```html -
      - <@paginationTag method="journals" page="${journals.number}" total="${journals.totalPages}" display="3"> - <#if pagination.hasPrev> -
    • - 上一页 -
    • - - <#list pagination.rainbowPages as number> - <#if number.isCurrent> -
    • - ${number.page!} -
    • - <#else> -
    • - ${number.page!} -
    • - - - <#if pagination.hasNext> -
    • - 下一页 -
    • - - -
    -``` - -输出: - -```html - -``` diff --git a/docs/developer-guide/theme/template-variables.md b/docs/developer-guide/theme/template-variables.md new file mode 100644 index 0000000..84cb618 --- /dev/null +++ b/docs/developer-guide/theme/template-variables.md @@ -0,0 +1,7 @@ +--- +title: 模板变量 +--- + +import DocCardList from '@theme/DocCardList'; + + diff --git a/docs/developer-guide/theme/template-variables/archives.md b/docs/developer-guide/theme/template-variables/archives.md new file mode 100644 index 0000000..b7b80d1 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/archives.md @@ -0,0 +1,234 @@ +--- +title: 文章归档 +description: archives.html - /archives +--- + +## 路由信息 + +- 模板路径:`/templates/archives.html` +- 访问路径 + - `/archives` + - `/archives/:year` + - `/archives/:year/:month` + +## 变量 + +### archives + +#### 变量类型 + +[#UrlContextListResult](#urlcontextlistresultpostarchivevo) + +#### 示例 + +```html title="/templates/archives.html" + +

    +
      + +
    • + + +
    • +
      +
    +
    + +``` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### ListedPostVo + +```json title="ListedPostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.505Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T13:06:38.505Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### PostArchiveVo + +```json title="PostArchiveVo" +{ + "year": "string", + "months": [ + { + "month": "string", + "posts": "#ListedPostVo" + } + ] +} +``` + +- [#ListedPostVo](#listedpostvo) + +### UrlContextListResult + +```json title="UrlContextListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#PostArchiveVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0, + "nextUrl": "string", + "prevUrl": "string" +} +``` + +- [#PostArchiveVo](#postarchivevo) diff --git a/docs/developer-guide/theme/template-variables/categories.md b/docs/developer-guide/theme/template-variables/categories.md new file mode 100644 index 0000000..18e6bf0 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/categories.md @@ -0,0 +1,84 @@ +--- +title: 文章分类集合 +description: categories.html - /categories +--- + +## 路由信息 + +- 模板路径:`/templates/categories.html` +- 访问路径:`/categories` + +## 变量 + +### categories + +#### 变量类型 + +List<[#CategoryTreeVo](#categorytreevo)> + +#### 示例 + +```html title="/templates/categories.html" +
      +
    • +
    +``` + +```html title="/templates/category-tree.html" + +``` + +### _templateId + +#### 变量值 + +`categories` + +## 类型定义 + +### CategoryTreeVo + +```json title="CategoryTreeVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:18:49.230Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "children": "List<#CategoryTreeVo>", + "parentName": "string", + "postCount": 0 +} +``` + +- [#CategoryTreeVo](#categorytreevo) diff --git a/docs/developer-guide/theme/template-variables/category.md b/docs/developer-guide/theme/template-variables/category.md new file mode 100644 index 0000000..e5d571a --- /dev/null +++ b/docs/developer-guide/theme/template-variables/category.md @@ -0,0 +1,225 @@ +--- +title: 分类归档 +description: category.html - /categories/:slug +--- + +## 路由信息 + +- 模板路径:`/templates/category.html` +- 访问路径:`/categories/:slug` + +## 变量 + +### category + +#### 变量类型 + +[#CategoryVo](#categoryvo) + +### posts + +#### 变量类型 + +[#UrlContextListResult](#urlcontextlistresultlistedpostvo) + +#### 示例 + +```html title="/templates/category.html" +
    +

    +
      +
    • + +
    • +
    + +
    +``` + +### _templateId + +#### 变量值 + +`category` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### ListedPostVo + +```json title="ListedPostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.505Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T13:06:38.505Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### UrlContextListResult + +```json title="UrlContextListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ListedPostVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0, + "nextUrl": "string", + "prevUrl": "string" +} +``` + +- [#ListedPostVo](#listedpostvo) diff --git a/docs/developer-guide/theme/template-variables/index_.md b/docs/developer-guide/theme/template-variables/index_.md new file mode 100644 index 0000000..9d3f451 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/index_.md @@ -0,0 +1,218 @@ +--- +title: 首页 +description: index.html - / +--- + +## 路由信息 + +- 模板路径:`/templates/index.html` +- 访问路径:`/` + +## 变量 + +### posts + +#### 变量类型 + +[#UrlContextListResult](#urlcontextlistresultlistedpostvo) + +#### 示例 + +```html title="/templates/index.html" +
    +
      +
    • + +
    • +
    + +
    +``` + +### _templateId + +#### 变量值 + +`index` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### ListedPostVo + +```json title="ListedPostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.505Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T13:06:38.505Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### UrlContextListResult + +```json title="UrlContextListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ListedPostVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0, + "nextUrl": "string", + "prevUrl": "string" +} +``` + +- [#ListedPostVo](#listedpostvo) diff --git a/docs/developer-guide/theme/template-variables/page.md b/docs/developer-guide/theme/template-variables/page.md new file mode 100644 index 0000000..4aa1bb6 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/page.md @@ -0,0 +1,109 @@ +--- +title: 独立页面 +description: page.html - /:slug +--- + +## 路由信息 + +- 模板路径:`/templates/page.html` +- 访问路径:`/:slug` + +## 变量 + +### singlePage + +#### 变量类型 + +[#SinglePageVo](#singlepagevo) + +#### 示例 + +```html title="/templates/page.html" +
    +

    +
    +
    +``` + +### _templateId + +#### 变量值 + +`page` + +## 类型定义 + +### SinglePageVo + +```json title="SinglePageVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T14:29:44.601Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T14:29:44.601Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + }, + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "content": { + "raw": "string", + "content": "string" + } +} +``` diff --git a/docs/developer-guide/theme/template-variables/post.md b/docs/developer-guide/theme/template-variables/post.md new file mode 100644 index 0000000..c554038 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/post.md @@ -0,0 +1,182 @@ +--- +title: 文章 +description: post.html - /archives/:slug +--- + +## 路由信息 + +- 模板路径:`/templates/post.html` +- 访问路径:`/archives/:slug` + +## 变量 + +### post + +#### 变量类型 + +[#PostVo](#postvo) + +#### 示例 + +```html title="/templates/post.html" +
    +

    +
    +
    +``` + +### _templateId + +#### 变量值 + +`post` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### PostVo + +```json title="PostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T12:45:43.888Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T12:45:43.888Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + }, + "content": { + "raw": "string", + "content": "string" + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) diff --git a/docs/developer-guide/theme/template-variables/tag.md b/docs/developer-guide/theme/template-variables/tag.md new file mode 100644 index 0000000..8a968e0 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/tag.md @@ -0,0 +1,225 @@ +--- +title: 标签归档 +description: tag.html - /tags/:slug +--- + +## 路由信息 + +- 模板路径:`/templates/tag.html` +- 访问路径:`/tags/:slug` + +## 变量 + +### tag + +#### 变量类型 + +[#TagVo](#tagvo) + +### posts + +#### 变量类型 + +[#UrlContextListResult](#urlcontextlistresultlistedpostvo) + +#### 示例 + +```html title="/templates/tag.html" +
    +

    +
      +
    • + +
    • +
    + +
    +``` + +### _templateId + +#### 变量值 + +`tag` + +## 类型定义 + +### CategoryVo + +```json title="CategoryVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "description": "string", + "cover": "string", + "template": "string", + "priority": 0, + "children": [ + "string" + ] + }, + "status": { + "permalink": "string", + "postCount": 0, + "visiblePostCount": 0 + }, + "postCount": 0 +} +``` + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` + +### ListedPostVo + +```json title="ListedPostVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.505Z", + }, + "spec": { + "title": "string", + "slug": "string", + "releaseSnapshot": "string", + "headSnapshot": "string", + "baseSnapshot": "string", + "owner": "string", + "template": "string", + "cover": "string", + "deleted": false, + "publish": false, + "publishTime": "2022-11-20T13:06:38.505Z", + "pinned": false, + "allowComment": true, + "visible": "PUBLIC", + "priority": 0, + "excerpt": { + "autoGenerate": true, + "raw": "string" + }, + "categories": [ + "string" + ], + "tags": [ + "string" + ], + "htmlMetas": [ + { + "additionalProp1": "string" + } + ] + }, + "status": { + "permalink": "string", + "excerpt": "string", + "inProgress": true, + "commentsCount": 0, + "contributors": [ + "string" + ] + }, + "categories": "List<#CategoryVo>", + "tags": "List<#TagVo>", + "contributors": [ + { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + } + ], + "owner": { + "name": "string", + "displayName": "string", + "avatar": "string", + "bio": "string" + }, + "stats": { + "visit": 0, + "upvote": 0, + "comment": 0 + } +} +``` + +- [#CategoryVo](#categoryvo) +- [#TagVo](#tagvo) + +### UrlContextListResult + +```json title="UrlContextListResult" +{ + "page": 0, + "size": 0, + "total": 0, + "items": "List<#ListedPostVo>", + "first": true, + "last": true, + "hasNext": true, + "hasPrevious": true, + "totalPages": 0, + "nextUrl": "string", + "prevUrl": "string" +} +``` + +- [#ListedPostVo](#listedpostvo) diff --git a/docs/developer-guide/theme/template-variables/tags.md b/docs/developer-guide/theme/template-variables/tags.md new file mode 100644 index 0000000..a1b0920 --- /dev/null +++ b/docs/developer-guide/theme/template-variables/tags.md @@ -0,0 +1,61 @@ +--- +title: 文章标签集合 +description: tags.html - /tags +--- +## 路由信息 + +- 模板路径:`/templates/tags.html` +- 访问路径:`/tags` + +## 变量 + +### tags + +#### 变量类型 + +List<[#TagVo](#tagvo)> + +#### 示例 + +```html title="/templates/tags.html" +
      +
    • +
    +``` + +### _templateId + +#### 变量值 + +`tags` + +## 类型定义 + +### TagVo + +```json title="TagVo" +{ + "metadata": { + "name": "string", + "labels": { + "additionalProp1": "string" + }, + "annotations": { + "additionalProp1": "string" + }, + "creationTimestamp": "2022-11-20T13:06:38.512Z", + }, + "spec": { + "displayName": "string", + "slug": "string", + "color": "#F9fEB1", + "cover": "string" + }, + "status": { + "permalink": "string", + "visiblePostCount": 0, + "postCount": 0 + }, + "postCount": 0 +} +``` diff --git a/docusaurus.config.js b/docusaurus.config.js index 17b91e3..4542b35 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -63,6 +63,11 @@ const config = { themeConfig: /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ ({ + docs: { + sidebar: { + autoCollapseCategories: true, + }, + }, navbar: { title: "Halo Documents", logo: { diff --git a/sidebars.js b/sidebars.js index c60e186..c040e94 100644 --- a/sidebars.js +++ b/sidebars.js @@ -19,12 +19,18 @@ module.exports = { { type: "category", label: "入门", + link: { + type: "generated-index", + }, collapsed: false, items: [ "getting-started/prepare", { type: "category", label: "安装指南", + link: { + type: "generated-index", + }, items: [ // "getting-started/install/linux", "getting-started/install/docker", @@ -48,10 +54,16 @@ module.exports = { { type: "category", label: "开发者指南", + link: { + type: "generated-index", + }, items: [ { type: "category", label: "系统开发", + link: { + type: "generated-index", + }, items: [ // "developer-guide/core/structure", "developer-guide/core/prepare", @@ -62,21 +74,66 @@ module.exports = { { type: "category", label: "插件开发", + link: { + type: "generated-index", + }, items: ["developer-guide/plugin/prepare"], }, { type: "category", label: "主题开发", + link: { + type: "generated-index", + }, items: [ "developer-guide/theme/prepare", + "developer-guide/theme/config", "developer-guide/theme/structure", - // "developer-guide/theme/config-files", - // "developer-guide/theme/global-variable", - // "developer-guide/theme/public-template-tag", - // "developer-guide/theme/page-variable", - // "developer-guide/theme/template-tag", + "developer-guide/theme/template-route-mapping", + "developer-guide/theme/static-resources", + "developer-guide/theme/settings", + { + type: "category", + label: "模板变量", + link: { + type: "doc", + id: "developer-guide/theme/template-variables", + }, + items: [ + "developer-guide/theme/template-variables/index_", + "developer-guide/theme/template-variables/post", + "developer-guide/theme/template-variables/page", + "developer-guide/theme/template-variables/archives", + "developer-guide/theme/template-variables/tags", + "developer-guide/theme/template-variables/tag", + "developer-guide/theme/template-variables/categories", + "developer-guide/theme/template-variables/category", + ], + }, + { + type: "category", + label: "Finder API", + link: { + type: "doc", + id: "developer-guide/theme/finder-apis", + }, + items: [ + "developer-guide/theme/finder-apis/category", + "developer-guide/theme/finder-apis/tag", + "developer-guide/theme/finder-apis/post", + "developer-guide/theme/finder-apis/single-page", + "developer-guide/theme/finder-apis/comment", + "developer-guide/theme/finder-apis/contributor", + "developer-guide/theme/finder-apis/menu", + "developer-guide/theme/finder-apis/site-stats", + "developer-guide/theme/finder-apis/theme", + "developer-guide/theme/finder-apis/plugin", + ], + }, + "developer-guide/theme/code-snippets", ], }, + "developer-guide/form-schema", // { // type: "link", // label: "REST API", @@ -87,6 +144,9 @@ module.exports = { { type: "category", label: "参与贡献", + link: { + type: "generated-index", + }, items: ["contribution/issue", "contribution/pr"], }, "about", diff --git a/static/img/formkit/formkit-repeater.png b/static/img/formkit/formkit-repeater.png new file mode 100644 index 0000000..73dc532 Binary files /dev/null and b/static/img/formkit/formkit-repeater.png differ