# 贡献

> 如何在本地搭建 htmlpress、提出更改以及发布版本。

Htmlpress 是一个开源项目，我们非常欢迎你的帮助，无论是修复 bug、完善文档，还是提议新功能。本指南将带你了解把一项更改从编辑器带进正式版本所需的一切。

## 快速开始

你需要 [Node.js](https://nodejs.org/) 24+、[pnpm](https://pnpm.io/) 11+ 和 [rustup](https://rustup.rs/)；如需构建 Python wheel，还需要 [uv](https://docs.astral.sh/uv/)。然后：

```
git clone https://github.com/datisthq/htmlpress.git
cd htmlpress
pnpm install
pnpm start
```

当 `cargo` 位于你的 `PATH` 中时，`pnpm install` 也会获取 Rust crate。`pnpm start` 会从源码运行 htmlpress，为本站位于 `rust/docs/` 中的页面提供服务并支持实时重载，这样你就可以一边迭代 htmlpress，一边在浏览器中查看结果。

## 仓库结构

```
htmlpress/
├── rust/                # the binary and the crates.io package `htmlpress`
│   ├── src/
│   │   ├── actions/     #   asset/escape + list, config/load, page/read + render, site/…
│   │   ├── commands/    #   the `build`, `start`, `preview`, `clear` and `escape` commands
│   │   ├── models/      #   Asset, Config, Page, Site, BuildOptions, Error
│   │   ├── components/  #   built-in components, compiled in, like styles/ and scripts/
│   │   ├── program.rs   #   the CLI
│   │   └── lib.rs       #   the library façade
│   ├── tests/           #   CLI integration tests
│   └── docs/            #   this site, HTML built by htmlpress itself
├── typescript/          # the npm package `gethtmlpress`: a shim that runs the binary
├── python/              # the PyPI package `htmlpress`: maturin binary wheels
├── .skills/             # shipped agent skills for people who use htmlpress
├── .agents/skills/      # repo skills for coding agents (see AGENTS.md)
├── .scripts/            # repo-wide guards and the `pnpm squash` script
└── htmlpress.yaml       # this site's htmlpress config
```

所有行为都位于 `rust/` 中。npm 和 PyPI 软件包只负责交付同一个二进制文件，因此任何功能都不会落在包装器中。

## 本地命令

在仓库根目录运行这些命令；每条命令都会通过 `pnpm -C <section>` 依次调用各个部分。

| 命令                 | 作用                                                   |
| ------------------ | ---------------------------------------------------- |
| `pnpm start`       | 从源码为文档站点提供服务，支持实时重载                                  |
| `pnpm build:docs`  | 文档站点的生产构建                                            |
| `pnpm build`       | 构建发布用的二进制文件、npm shim 和 Python wheel                  |
| `pnpm check:types` | 通过 `tsgo --noEmit` 和 `cargo check` 进行类型检查            |
| `pnpm check:lint`  | 格式检查 + lint（`vp fmt`、`vp lint`、`cargo fmt`、`clippy`） |
| `pnpm check`       | Lint + 类型检查                                          |
| `pnpm format`      | 自动修复格式（`vp fmt`、`cargo fmt`）                         |
| `pnpm test:unit`   | 运行仓库守卫检查、shim 的测试以及 `cargo test`                     |
| `pnpm test`        | Lint + 类型检查 + 单元测试                                   |
| `pnpm scan`        | 密钥和漏洞扫描（gitleaks、semgrep）                            |

当 `pnpm test` 全部通过且 `pnpm build:docs` 成功时，更改就可以推送了。

## 代码约定

- **Rust**：在固定的稳定版工具链上使用 2024 edition，通过 clippy 检查，测试之外不使用 `unwrap`/`expect`；单元测试以 `<module>_unit.rs` 的形式放在模块旁边，在 `rust/` 中用 `cargo test <name>` 运行单个测试。
- **TypeScript**：开启严格模式。未经许可不要使用 `any`、`as` 类型断言或非空断言 `!`。使用带 `.ts` 扩展名的完整 ESM 导入；测试以 `<module>.unit.ts` 的形式放在模块旁边。
- **注释**：文档注释只用于公开项。注释必须指明它所防止的错误，长度控制在三行左右，且注释数量绝不能超过代码；设计理由和历史应记录在 git 中。
- **文档页面**：使用语义化 HTML 和文档中列出的 `htmlpress-*` 组件，不使用内联样式。
- **格式**：`pnpm format`。2 空格缩进、无分号、双引号（LF、UTF-8）；rustfmt 限宽 90 列。

## 提出更改

1. **先提交 issue**：对于比错别字或小 bug 更大的改动，都应如此。在写代码之前先就方向达成一致会更容易。

2. **从 `main` 创建分支**，使用简短的描述性名称（例如 `fix-fragment-title`、`feat-search`）。

3. **保持提交历史聚焦**。Htmlpress 使用 [Conventional Commits](https://www.conventionalcommits.org/)；前缀决定 release-please 的行为：

   - `fix:` 修复安装者所获得内容中的 bug → 补丁版本
   - `feat:` 为安装者所获得的内容添加新功能 → 次版本
   - `chore:`、`docs:`、`refactor:`、`test:`、`perf:` → 不发布版本；用于 CI、工具、依赖、文档站点、随附的技能，以及安装者永远看不到的其他内容
   - 永远不要把提交标记为破坏性变更（`!` 或 `BREAKING CHANGE:` 页脚）

4. 推送前**运行 `pnpm test`**。

5. 针对 `main` **发起 PR**。说明*原因*（链接到对应 issue），为任何可见的改动附上截图或 CLI 输出，并指出评审者需要特别留意的地方。

## 版本发布

版本发布由 [release-please](https://github.com/googleapis/release-please) 驱动：当 `feat` 或 `fix` 合入 `main` 时，会打开一个 Release PR；合并它即会确定版本号、打上标签、为每个平台构建二进制文件，并以同一个共享版本发布到 crates.io、npm 和 PyPI。维护者从不手动提升版本号；`.release/manifest.json` 由 release-please 维护。

## 获取帮助

- **Bug 和功能请求**： [GitHub Issues](https://github.com/datisthq/htmlpress/issues)
- **讨论 / 想法**： [GitHub Discussions](https://github.com/datisthq/htmlpress/discussions)
- **源码**： [github.com/datisthq/htmlpress](https://github.com/datisthq/htmlpress)

感谢你帮助 htmlpress 变得更好。
