# 參與貢獻 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) 私下回報安全漏洞。
- 送出 pull request：請見下方。

如果不只是小修正，請先開啟 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 檢查關卡：`pnpm lint`（用 `pnpm lint:fix` 自動修正安全的項目）。這個關卡會在正確性錯誤時**阻擋**。既有的無障礙／樣式待處理項目，會以不阻擋的警告回報（請參閱 `biome.json`）。請盡量不要新增警告。
- **Rust**：後端必須通過 `cargo fmt` 且通過 `cargo clippy`。兩者在 CI 中都是**阻擋**的（`clippy` 以 `-D warnings` 執行）。推送之前，請執行 `cargo fmt` 和 `cargo clippy --all-targets --fix`。
- 配合周圍的程式碼：註解的密度、命名和慣用寫法。

## Pull request

1. Fork 並從 `main` 建立分支（`git checkout -b fix/short-description`）。
2. 讓變更保持專注。無關的重構請放進它自己的 PR。
3. 確認 `pnpm lint`、`pnpm build` 和 `cargo test --lib` 在本機都通過。
4. 填寫 PR 範本：連結 issue、說明變更內容、註明你如何測試。
5. CI 必須是綠燈（前端建置和 Rust 測試是必要的檢查）。

我們採用 squash merge，所以乾淨的 PR 標題就是 commit 訊息。我們歡迎但不強制要求 Conventional Commit 風格（例如 `fix: reject absolute paths in resolve`）。

## 發布（維護者）

發布是透過推送版本標籤來進行的。[`Release` workflow](https://github.com/Oleafly/Oleafly/blob/main/.github/workflows/release.yml) 會建置 macOS Apple Silicon、Windows x64、Linux x64 和 Linux ARM64 的安裝程式，並把它們附加到草稿供審閱。發布需要針對同一個標籤，再執行第二個有防護的 workflow。

```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 General Public License v3.0 or later](https://github.com/Oleafly/Oleafly/blob/main/LICENSE) 授權。
