## 1. Project Overview & Quickstart (nelvko/prepare)

# prepare

Open-source repository nelvko/prepare

### Repository Details
- **Repository:** [nelvko/prepare](https://github.com/nelvko/prepare)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (nelvko/docs)

## File: docs/contribution/issue.md

---
title: 问题反馈
---

:::info
如果您在使用过程中遇到了什么问题，您可以通过下面的方式反馈，但请尽量按照要求提出反馈。
:::

## GitHub Issues

链接：<https://github.com/halo-dev/halo/issues>

如果你在使用过程中，遇到了一些 bug 或者需要添加某些新特性，请尽量在 GitHub Issues 进行反馈，这非常有助于我们跟踪解决此问题，您也可以很方便的接收到处理状态。

建议步骤：

1. 在 [Issues 列表](https://github.com/halo-dev/halo/issues) 搜索相关问题，看看是否有其他人已经提到了此问题。
2. 如果当前还没有人遇到您类似的问题，那么请点击右上角的 `New issue` 按钮创建新的 issue。
3. 选择正确的反馈类型。
4. 请尽可能详细的按照模板填写内容。
5. 点击 `Submit new issue` 提交 issue。

## Halo 官方社区

链接：<https://bbs.halo.run>

此平台主要目的用于与其他 Halo 用户进行交流。但如果您对 GitHub 不是很熟悉或者没有账号，您也可以在此平台进行反馈。

---

## File: docs/contribution/pr.md

---
title: 代码贡献
---

欢迎关注并有想法参与 Halo 的开发，以下是关于如何参与到 Halo 项目的指南，仅供参考。

## 发现 Issue

所有的代码尽可能都有依据（Issue），不是凭空产生。

### 寻找一个 Good First Issue

> 这个步骤非常适合首次贡献者。

在 [halo-dev](https://github.com/halo-dev) 和 [halo-sigs](https://github.com/halo-sigs) 组织下，有非常多的仓库。每个仓库下都有可能包含一些“首次贡献者”友好的 Issue，主要是为了给贡献者提供一个友好的体验。 该类 Issue
一般会用 `good-first-issue` 标签标记。标签 `good-first-issue` 表示该 Issue 不需要对 Halo 有深入的理解也能够参与。

请点击：[good-first-issue](https://github.com/issues?q=org%3Ahalo-dev+is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+no%3Aassignee+)
查看关于 Halo 的 Good First Issue。

### 认领 Issue

若对任何一个 Issue 感兴趣，请尝试在 Issue 进行回复，讨论解决 Issue 的思路。确定后可直接通过 `/assign` 或者 `/assign @GitHub 用户名` 认领这个
Issue。这样可避免两位贡献者在同一个问题上花时间。

## 代码贡献步骤

1. Fork 此仓库

   点击 Halo 仓库主页右上角的 `Fork` 按钮即可。

2. Clone 仓库到本地

   ```bash
   git clone https://github.com/{YOUR_USERNAME}/halo --recursive
   # 或者 git clone git@github.com:{YOUR_USERNAME}/halo.git --recursive
   ```

3. 添加主仓库

   添加主仓库方便未来同步主仓库最新的 commits 以及创建新的分支。

   ```bash
   git remote add upstream https://github.com/halo-dev/halo.git
   # 或者 git remote add upstream git@github.com:halo-dev/halo.git
   git fetch upstream main
   ```

4. 创建新的开发分支

   我们需要从主仓库的主分支创建一个新的开发分支。

   ```bash
   git checkout upstream/main
   git checkout -b {BRANCH_NAME}
   ```

5. 提交代码

   ```bash
   git add .
   git commit -s -m "Fix a bug king"
   git push origin {BRANCH_NAME}
   ```

6. 合并主分支

   在提交 Pull Request 之前，尽量保证当前分支和主分支的代码尽可能同步，这时需要我们手动操作。示例：

   ```bash
   git fetch upstream/main
   git merge upstream/main
   git push origin {BRANCH_NAME}
   ```

## Pull Request

进入此阶段说明已经完成了代码的编写，测试和自测，并且准备好接受 Code Review。

### 创建 Pull Request

回到自己的仓库页面，选择 `New pull request` 按钮，创建 `Pull request` 到原仓库的 `main` 分支。
然后等待我们 Review 即可，如有 `Change Request`，再本地修改之后再次提交即可。

提交 Pull Request 的注意事项：

- 提交 Pull Request 请充分自测。
- 每个 Pull Request 尽量只解决一个 Issue，特殊情况除外。
- 应尽可能多的添加单元测试，其他测试（集成测试和 E2E 测试）可看情况添加。
- 不论需要解决的 Issue 发生在哪个版本，提交 Pull Request 的时候，请将主仓库的主分支设置为 `main`。例如：即使某个 Bug 于 Halo 2.0.x 被发现，但是提交 Pull Request 仍只针对
  `main` 分支，等待 Pull Request 合并之后，我们会通过 `/cherrypick release-2.0` 或者 `/cherry-pick release-2.1` 指令将此 Pull Request
  的修改应用到 `release-2.0` 和 `release-2.1` 分支上。

### 更新 commits

Code Review 阶段可能需要 Pull Request 作者重新修改代码，请直接在当前分支 commit 并 push 即可，无需关闭并重新提交 Pull Request。示例：

```bash
git add .
git commit -s -m "Refactor some code according code review"
git push origin bug/king
```

同时，若已经进入 Code Review 阶段，请不要强制推送 commits 到当前分支。否则 Reviewers 需要从头开始 Code Review。

### 开发规范

请参考 [https://docs.halo.run/developer-guide/core/code-style](https://docs.halo.run/developer-guide/core/code-style)
，请确保所有代码格式化之后再提交。

---

## File: docs/contribution/sponsor.md

---
title: 赞助我们
---

## 为什么需要赞助

我们花费了大量的精力来维护这个软件，并且也提供了不少资金来维护服务器，域名等。因此我们需要赞助来节省部分开发成本。你的赞助不仅仅会被我们用来支付一些开发成本（比如服务器，OSS，域名等），还会让我们有更多的信心和精力投入到这个开源项目的开发中。从而让项目保持更加健康的成长以及迭代。

## 赞助形式

:::info
你可以通过任何形式对我们赞助，不限于资金。
:::

### 资金赞助

- 爱发电：<https://afdian.net/a/halo-dev>

### 通过我们的推广链接购买服务器

如果你当前还没有购买服务器，可以考虑通过以下链接购买，这会为我们带来一部分收益。

- 阿里云：<https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=j57gyupo>
- 阿里云新人专享：<https://www.aliyun.com/minisite/goods?userCode=j57gyupo>
- 腾讯云：<https://curl.qcloud.com/9Ogon25Y>

---

## File: docs/developer-guide/core/build.md

---
title: 构建
---

:::info
在此之前，我们推荐你先阅读[《准备工作》](./prepare)，检查本地环境是否满足要求。
:::

一般情况下，为了保证版本一致性和可维护性，我们并不推荐自行构建和二次开发。

## 克隆项目

如果你已经 Fork 了相关仓库，请将以下命令中的 `halo-dev` 替换为你的 GitHub 用户名。

```bash
git clone https://github.com/halo-dev/halo

# 或者使用 ssh 的方式 clone（推荐）
# git clone git@github.com:halo-dev/halo.git

# 或者使用 GitHub CLI 克隆（推荐）
# gh repo clone halo-dev/halo 

# 或者使用 GitHub CLI Fork（推荐）
# gh repo fork halo-dev/halo

cd halo

# 切换到特定的分支或标签，请替换 ${branch_name}
git checkout ${branch_name}
```

## 构建 Fat Jar

构建之前需要修改 `gradle.properties` 中的 `version` 属性（推荐遵循 [SemVer 规范](https://semver.org/)），例如：`version=2.13.0`

```bash
cd path/to/halo
```

下载预设插件（可选）：

```bash
# Windows
./gradlew.bat downloadPluginPresets

# macOS / Linux
./gradlew downloadPluginPresets
```

构建：

```bash
# Windows
./gradlew.bat clean build -x check

# macOS / Linux
./gradlew clean build -x check
```

构建完成之后，在 Halo 项目下产生的 `application/build/libs/halo-${version}.jar` 即为构建完成的文件。

最终部署文档可参考：[使用 JAR 文件部署](../../getting-started/install/jar-file.md)。

## 构建 Docker 镜像

在此之前，请确认已经构建好了 Fat Jar。

```bash
cd path/to/halo
```

```bash
# 请替换 ${tag_name}
docker build -t halo-dev/halo:${tag_name} .
```

```bash
# 插件构建完成的版本
docker images | grep halo
```

最终部署文档可参考：[使用 Docker Compose 部署](../../getting-started/install/docker-compose.md)。

---

## File: docs/developer-guide/core/code-style.md

---
title: 代码风格
---

Halo 添加了 checkstyle 插件，来保证每位提交者代码的风格保持一致，减少无效代码的修改。本篇文章主要讲解如何在 IDEA 中添加 CheckStyle 插件，并引入项目所提供的 checkstyle.xml 配置。

## 安装 CheckStyle-IDEA

- 进入 IDEA 插件市场。
- 搜索 CheckStyle-IDEA，点击安装即可。

## 配置 CheckStyle

- 进入 CheckStyle 配置（File | Settings | Tools | Checkstyle）。
- 选择 Checkstyle 版本：9.3（以文件 `application/build.gradle` 中指定的版本为准）。
- 在配置文件中点击添加按钮，配置描述可随便填写（推荐 Halo Checks），选择 ./config/checkstyle/checkstyle.xml，点击下一步和完成。
- 勾选刚刚创建的配置文件。

## 配置 Editor

- 进入编辑器配置（File | Settings | Editor | Code Style）

- 导入 checkstyle.xm 配置：



- 选择 `./config/checkstyle/checkstyle.xml` 配置文件，点击确定即可。

至此，有关代码风格检查工具和格式化配置已经完成。

---

## File: docs/developer-guide/core/prepare.md

---
title: 准备工作
---

## 环境要求

- [OpenJDK 17 LTS](https://github.com/openjdk/jdk)
- [Node.js 18 LTS](https://nodejs.org)
- [pnpm 8](https://pnpm.io/)
- [IntelliJ IDEA](https://www.jetbrains.com/idea/)
- [Git](https://git-scm.com/)
- [Docker](https://www.docker.com/)（可选）

## 名词解释

### 工作目录

指 Halo 所依赖的工作目录，在 Halo 运行的时候会在系统当前用户目录下产生一个 halo-next 的文件夹，绝对路径为 ~/halo-next。里面通常包含下列目录或文件：

1. `db`：存放 H2 Database 的物理文件，如果你使用其他数据库，那么不会存在这个目录。
2. `themes`：里面包含用户所安装的主题。
2. `plugins`：里面包含用户所安装的插件。
5. `attachments`：附件目录。
4. `logs`：运行日志目录。

---

## File: docs/developer-guide/core/run.md

---
title: 开发环境运行
---

:::info
在此之前，我们推荐你先阅读[《准备工作》](./prepare)，检查本地环境是否满足要求。
:::

## 项目结构说明

目前如果需要完整的运行 Halo，总共需要三个部分：

1. Halo 主项目（[halo-dev/halo](https://github.com/halo-dev/halo)）
2. UI，包括 Console 控制台和 UC 个人中心（托管在 Halo 主项目）
3. 主题（Halo 主项目内已包含默认主题）

:::info 说明
从 Halo 2.13 开始，Halo 项目的 `ui` 目录同时包含了 Console（管理控制台）和 UC（个人中心），以下统称为 UI。

当前 Halo 主项目并不会将 UI 的构建资源托管到 Git 版本控制，所以在开发环境是需要同时运行 UI 项目的。当然，在我们的最终发布版本的时候会在 CI 中自动构建 UI 到 Halo 主项目。
:::

## 克隆项目

如果你已经 Fork 了相关仓库，请将以下命令中的 `halo-dev` 替换为你的 GitHub 用户名。

```bash
git clone https://github.com/halo-dev/halo

# 或者使用 ssh 的方式 clone（推荐）
# git clone git@github.com:halo-dev/halo.git

# 或者使用 GitHub CLI 克隆（推荐）
# gh repo clone halo-dev/halo 

# 或者使用 GitHub CLI Fork（推荐）
# gh repo fork halo-dev/halo
```

## 运行 UI 服务

```bash
cd path/to/halo
```

Linux / macOS 平台：

```bash
./gradlew :ui:dev
```

Windows 平台：

```bash
./gradlew.bat :ui:dev
```

最终控制台打印了如下信息即代表运行正常：

```bash
VITE v4.2.3  ready in 638 ms

# Console 控制台服务
➜  Local:   http://localhost:3000/console/

# UC 个人中心服务
➜  Local:   http://localhost:4000/uc/
```

:::info 提示
请不要直接使用 UI 的运行端口（3000 / 4000）访问，会因为跨域问题导致无法正常登录，建议按照后续的步骤以 dev 的配置文件运行 Halo，在 dev 的配置文件中，我们默认代理了 UI 页面的访问地址，所以后续访问 UI 页面使用 `http://localhost:8090/console` 和 `http://localhost:8090/uc` 访问即可，代理的相关配置：

```yaml
halo:
  console:
    proxy:
      endpoint: http://localhost:3000/
      enabled: true
  uc:
    proxy:
      endpoint: http://localhost:4000/
      enabled: true
```

:::

## 运行 Halo

1. 在 IntelliJ IDEA 中打开 Halo 项目，等待 Gradle 初始化和依赖下载完成。

2. 下载预设插件（可选）

    ```bash
    # Windows
    ./gradlew.bat downloadPluginPresets

    # macOS / Linux
    ./gradlew downloadPluginPresets
    ```

3. 修改 IntelliJ IDEA 的运行配置

    - Windows

      将 Active Profiles 改为 `dev,win`，如图所示：

      

    - macOS / Linux

      将 Active Profiles 改为 `dev`，如图所示：

      

4. 点击 IntelliJ IDEA 的运行按钮，等待项目启动完成。

5. 或者使用 Gradle 运行

    ```bash
    # macOS / Linux
    ./gradlew bootRun --args="--spring.profiles.active=dev"

    # Windows
    gradlew.bat bootRun --args="--spring.profiles.active=dev,win"
    ```

6. 最终提供以下访问地址：
   1. 网站首页：<http://localhost:8090>
   2. Console 控制台：<http://localhost:8090/console>
   3. UC 个人中心：<http://localhost:8090/uc>

---

## File: docs/developer-guide/core/structure.md

---
title: 系统结构
---

[Halo](https://github.com/halo-dev/halo) 博客系统分为以下四个部分：

| 项目名称                                                 | 简介                                                                                                                   |
| :------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
| [halo](https://github.com/halo-dev/halo)                 | 提供整个系统的服务，采用 [Spring Boot](https://spring.io/) 开发                                                        |
| [halo-admin](https://github.com/halo-dev/halo-admin)     | 负责后台管理的渲染，采用 [Vue](https://vuejs.org/) 开发，已集成在 Halo 运行包内，无需独立部署。                                      |
| [halo-comment](https://github.com/halo-dev/halo-comment) | 评论插件，采用 [Vue](https://vuejs.org/) 开发，在主题中运行方式引入构建好的 `JavaScript` 文件即可                      |
| [halo-theme-\*](https://github.com/halo-dev)             | 主题项目集，采用 [FreeMarker](https://freemarker.apache.org/) 模板引擎编写，需要包含一些特殊的配置才能够被 halo 所使用 |

## 自定义配置

> 为什么要提前讲自定义配置呢？是因为在这里让大家了解到 `Halo` 的`配置方式`，以及`配置优先级`，不至于未来运行项目的时候不知道如何优雅地修改配置。

`Halo` 配置目录优先级如下（从上到下优先级越来越小，上层的配置将会覆盖下层）:

- `Halo` 自定义配置
  - file:~/.halo/
  - file:~/.halo-dev/
- `Spring Boot` 默认配置
  - file:./config/
  - file:./
  - classpath:/config/
  - classpath:/

> 参考: [Application Property Files](https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files)

在开发的时候，希望大家能够在 `~/halo-dev/application.yml` 中进行添加自定义配置。当然后面也会讲到如何用`运行参数` 和 `VM options` 进行控制配置，届时可根据具体情况进行选择。

:::warning
开发的时候，我们不建议直接更改`项目源码`中的所包含的`配置文件`，包括 `application.yml`、`application-dev.yml`、`application-test.yml` 和 `application-user.yml`。
:::

---

## File: docs/developer-guide/plugin/api-reference/ui/extension-points/interface/Attachment.md

```ts
export interface Attachment {
  apiVersion: "storage.halo.run/v1alpha1"
  kind: "Attachment"
  metadata: {
    annotations: {}
    creationTimestamp: string
    labels: {}
    name: string                                // 附件的唯一标识
    version: number
  }
  spec: {
    displayName: string                         // 附件名称
    groupName: string                           // 附件分组
    mediaType: string                           // 附件类型
    ownerName: string                           // 附件上传者
    policyName: string                          // 附件存储策略
    size: number                                // 附件大小
    tags: Array<string>
  }
  status: {
    permalink: string                           // 附件固定访问地址
  }
}
```

---

## File: docs/developer-guide/plugin/api-reference/ui/extension-points/interface/ListedPost.md

```ts
export interface ListedPost {
  categories: Array<{                             // 文章的分类集合
    apiVersion: "content.halo.run/v1alpha1";
    kind: "Category";
    metadata: {
      annotations: {};
      creationTimestamp: string;
      labels: {};
      name: string;                               // 分类的唯一标识
      version: number;
    };
    spec: {
      children: Array<string>;                    // 子分类
      cover: string;                              // 分类封面图
      description: string;                        // 分类描述
      displayName: string;                        // 分类名称
      priority: number;                           // 分类优先级
      slug: string;                               // 分类别名
      template: string;                           // 分类渲染模板
    };
    status: {
      permalink: string;                          // 分类的永久链接
      postCount: number;                          // 分类下的文章总数
      visiblePostCount: number;                   // 分类下可见的文章总数
    };
  }>;
  contributors: Array<{                           // 文章的贡献者集合
    avatar: string;                               // 贡献者头像
    displayName: string;                          // 贡献者名称
    name: string;                                 // 贡献者唯一标识
  }>;
  owner: {                                        // 文章的作者信息
    avatar: string;                               // 作者头像
    displayName: string;                          // 作者名称
    name: string;                                 // 作者唯一标识
  };
  post: {                                         // 文章信息
    apiVersion: "content.halo.run/v1alpha1";
    kind: "Post";
    metadata: {
      annotations: {};
      creationTimestamp: string;
      labels: {};
      name: string;                               // 文章的唯一标识
      version: number;
    };
    spec: {
      allowComment: boolean;                      // 是否允许评论
      baseSnapshot: string;                       // 内容基础快照
      categories: Array<string>;                  // 文章所属分类
      cover: string;                              // 文章封面图
      deleted: boolean;                           // 是否已删除
      excerpt: {                                  // 文章摘要
        autoGenerate: boolean;                    // 是否自动生成
        raw: string;                              // 摘要内容
      };
      headSnapshot: string;                       // 内容最新快照
      htmlMetas: Array<{}>;
      owner: string;                              // 文章作者的唯一标识
      pinned: boolean;                            // 是否置顶
      priority: number;                           // 文章优先级
      publish: boolean;                           // 是否发布
      publishTime: string;                        // 发布时间
      releaseSnapshot: string;                    // 已发布的内容快照
      slug: string;                               // 文章别名
      tags: Array<string>;                        // 文章所属标签
      template: string;                           // 文章渲染模板
      title: string;                              // 文章标题
      visible: string;                            // 文章可见性
    };
    status: {
      commentsCount: number;                      // 文章评论总数
      conditions: Array<{
        lastTransitionTime: string;
        message: string;
        reason: string;
        status: string;
        type: string;
      }>;
      contributors: Array<string>;
      excerpt: string;                            // 最终的文章摘要，根据是否自动生成计算
      inProgress: boolean;                        // 是否有未发布的内容
      lastModifyTime: string;                     // 文章最后修改时间
      permalink: string;                          // 文章的永久链接
      phase: string;
    };
  };
  stats: {
    approvedComment: number;                      // 已审核的评论数
    totalComment: number;                         // 评论总数
    upvote: number;                               // 点赞数
    visit: number;                                // 访问数
  };
  tags: Array<{                                   // 文章的标签集合
    apiVersion: "content.halo.run/v1alpha1";
    kind: "Tag";
    metadata: {
      annotations: {};
      creationTimestamp: string;
      labels: {};
      name: string;                               // 标签的唯一标识
      version: number;
    };
    spec: {
      color: string;                              // 标签颜色
      cover: string;                              // 标签封面图
      displayName: string;                        // 标签名称
      slug: string;                               // 标签别名
    };
    status: {
      permalink: string;                          // 标签的永久链接
      postCount: number;                          // 标签下的文章总数
      visiblePostCount: number;                   // 标签下可见的文章总数
    };
  }>;
}

```

---

## File: docs/developer-guide/plugin/api-reference/ui/extension-points/interface/OperationItem.md

```ts title="OperationItem"
export interface OperationItem<T> {
  priority: number;                 // 排序优先级
  component: Raw<Component>;        // 菜单项组件
  props?: Record<string, unknown>;  // 菜单项组件属性
  action?: (item?: T) => void;      // 菜单项点击事件
  label?: string;                   // 菜单项标题
  hidden?: boolean;                 // 菜单项是否隐藏
  permissions?: string[];           // 菜单项 UI 权限
  children?: OperationItem<T>[];    // 子菜单项
}
```

---

## File: docs/developer-guide/plugin/api-reference/ui/extension-points/interface/Plugin.md

```ts
export interface Plugin {
  apiVersion: "plugin.halo.run/v1alpha1"
  kind: "Plugin"
  metadata: {
    annotations: {}
    creationTimestamp: string         // 创建时间
    labels: {}
    name: string                      // 唯一标识
    version: number
  }
  spec: {
    author: {                         // 作者信息
      name: string
      website: string
    }
    configMapName: string             // 关联的 ConfigMap 模型，用于存储配置
    description: string               // 插件描述
    displayName: string               // 插件名称
    enabled: boolean
    homepage: string                  // 插件主页
    license: Array<{                  // 插件协议
      name: string
      url: string
    }>
    logo: string
    pluginDependencies: {}
    repo: string                      // 插件仓库地址
    requires: string                  // 所依赖的 Halo 版本
    settingName: string               // 关联的 Setting 模型，用于渲染配置表单
    version: string                   // 插件版本
  }
  status: {
    conditions: Array<{
      lastTransitionTime: string
      message: string
      reason: string
      status: string
      type: string
    }>
    entry: string
    lastProbeState: string
    lastStartTime: string
    loadLocation: string
    logo: string                      // 插件 Logo 地址
    phase: string
    stylesheet: string
  }
}
```