# 为 Oleafly 做贡献

感谢你想让 Oleafly 变得更好！本指南带你从全新克隆一路走到可运行的开发构建，并介绍我们如何审阅和合并更改。

感谢你想让 Oleafly 变得更好！本指南带你从全新
克隆一路走到可运行的开发构建，并介绍我们如何审阅和合并更改。

## 参与贡献的方式

- 报告错误：提交一份[错误报告](https://github.com/Oleafly/Oleafly/issues/new/choose)。
- 请求功能：提交一份[功能请求](https://github.com/Oleafly/Oleafly/issues/new/choose)。
- 按照 [SECURITY.md](https://github.com/Oleafly/Oleafly/blob/main/SECURITY.md) 私下报告安全漏洞。
- 发送拉取请求：见下文。

对于比小修复更大的改动，请先提交一个 issue，这样我们可以在你投入时间之前就
方案达成一致。

## 前置条件

| 工具 | 版本 | 说明 |
| --- | --- | --- |
| [Node.js](https://nodejs.org) | 22.13+ | pnpm 11 要求 |
| [pnpm](https://pnpm.io) | 11.9+ | 启用 Corepack，或安装 `package.json` 中声明的版本 |
| [Rust](https://rustup.rs) | stable (1.77+) | 包含 `cargo` |
| 平台依赖 | - | 请参阅适用于你的操作系统的 [Tauri v2 前置条件](https://v2.tauri.app/start/prerequisites/)（在 Linux 上：`libwebkit2gtk-4.1-dev`、`librsvg2-dev`、`patchelf` 等） |

## 开始

```bash
git clone https://github.com/Oleafly/Oleafly.git
cd Oleafly
pnpm install

# Find your target with `rustc -vV | grep host`.
bash scripts/fetch-tectonic.sh aarch64-apple-darwin   # or your host triple
bash scripts/fetch-typst.sh aarch64-apple-darwin

# Run the app in dev mode (hot-reloads the frontend, rebuilds Rust on change):
pnpm tauri dev
```

> Tectonic、Biber 和 Typst 的二进制文件是**被 git 忽略的**，这是
> 有意为之，绝不要提交它们。获取脚本会把它们放到
> `src-tauri/binaries/`，这正是 `bundle.externalBin` 期望它们所在的位置。

### 在本地构建生产包

```bash
pnpm tauri build
```

安装程序会生成在 `src-tauri/target/release/bundle/` 中。

## 项目布局

```
src/                 React + TypeScript app shell
  components/         UI (editor, pdf, ai, layout, files, …)
  lib/               framework-agnostic helpers (ai-providers, github, …)
  store/             Zustand state slices
packages/            @oleafly/* engine packages, consumed as TypeScript source
src-tauri/src/       Rust backend (Tauri commands)
  commands.rs        Tauri command handlers and compile entry points
  latex_engine.rs    Tectonic and latexmk selection
  mcp/               local MCP server, routing, and native tools
  project.rs         project/file CRUD (path-sandboxed - see `resolve`)
  git.rs             git integration
  github.rs          GitHub OAuth device flow
  paths.rs           path helpers + project-id validation
docs/                user-facing documentation
scripts/             sidecar fetchers, language servers, release checks, icon generation
```

## 测试

```bash
pnpm test                    # frontend unit tests (Vitest)
cd src-tauri && cargo test --lib   # Rust backend tests
```

涉及文件系统、git 或用户路径的后端逻辑**必须**有
测试。路径沙箱辅助函数（`resolve_within`、`validate_project_id`）以及
日志/URL 解析器由 `#[cfg(test)]` 模块覆盖，修改那部分代码时请扩充它们。在前端，
决定拼写/语法检查器能看到什么内容的 LaTeX 屏蔽逻辑是纯函数，并在
`src/components/editor/cm/latex-mask.test.ts` 中有单元测试，改变
哪些内容算作正文时，请在那里添加一个用例。

## 代码风格

- **TypeScript**：前端必须通过类型检查并能构建：`pnpm build`，并且
  通过 Biome lint 关卡：`pnpm lint`（用
  `pnpm lint:fix` 自动修复安全的部分）。这个关卡会因正确性错误而**阻止**。现有的
  无障碍/风格方面的积压问题作为不阻止的警告报告（见
  `biome.json`）。请尽量不要新增警告。
- **Rust**：后端必须满足 `cargo fmt` 无差异、`cargo clippy` 无警告。
  两者在 CI 中都是**阻止性**的（`clippy` 带 `-D warnings` 运行）。推送前请运行
  `cargo fmt` 和 `cargo clippy --all-targets --fix`。
- 与周围的代码保持一致：注释密度、命名和惯用写法。

## 拉取请求

1. 从 `main` 派生并创建分支（`git checkout -b fix/short-description`）。
2. 让改动保持聚焦。不相关的重构请放在单独的 PR 中。
3. 确保 `pnpm lint`、`pnpm build` 和 `cargo test --lib` 在本地通过。
4. 填写 PR 模板：关联 issue、描述改动、说明你
   是如何测试的。
5. CI 必须是绿色的（前端构建和 Rust 测试是必需的检查）。

我们采用 squash 合并，所以一个干净的 PR 标题就是提交信息。我们欢迎使用 Conventional Commits
风格，但不是必需的（例如 `fix: reject absolute paths in resolve`）。

## 发布（维护者）

发布通过推送版本标签来进行。
[`Release` 工作流](https://github.com/Oleafly/Oleafly/blob/main/.github/workflows/release.yml)会构建 macOS Apple Silicon、Windows x64、Linux x64 和 Linux ARM64 的安装程序。它把这些安装程序附加到一份草稿上供审阅。发布则需要对同一标签再运行一次受保护的第二个工作流。

```bash
# Bump the version everywhere it's declared (package.json, Cargo.toml,
# Cargo.lock, tauri.conf.json) in one shot, so the tag can't drift:
./scripts/bump-version.sh 0.3.6

git commit -am "chore: release v0.2.0"
git tag v0.2.0 && git push origin v0.2.0
```

参与贡献即表示你同意，你的贡献将按
项目的 [GNU Affero 通用公共许可证第 3 版或更新版本](https://github.com/Oleafly/Oleafly/blob/main/LICENSE)授权。
