diff --git a/COMPLIANCE.md b/COMPLIANCE.md deleted file mode 100644 index 4268bfe..0000000 --- a/COMPLIANCE.md +++ /dev/null @@ -1,164 +0,0 @@ -# Obsidian Plugin Development Compliance Checklist - -This document verifies that the Git File Push plugin follows Obsidian's plugin development guidelines. - -## ✅ Required Files - -- [x] **manifest.json** - Plugin metadata - - [x] `id`: "git-file-push" - - [x] `name`: "Git File Push" - - [x] `version`: "1.0.0" - - [x] `minAppVersion`: "0.15.0" - - [x] `description`: Clear description of plugin functionality - - [x] `author`: "tianyao" - - [x] `authorUrl`: GitHub profile URL - - [x] `isDesktopOnly`: false (supports mobile) - -- [x] **main.js** - Compiled plugin code - - [x] Generated by esbuild - - [x] Not tracked in git (in .gitignore) - - [x] Uploaded to GitHub releases - -- [x] **styles.css** - Plugin styles (optional but included) - -- [x] **versions.json** - Version compatibility mapping - ```json - { - "1.0.0": "0.15.0" - } - ``` - -- [x] **LICENSE** - 0-BSD License - -## ✅ Build Configuration - -### esbuild.config.mjs -- [x] Entry point: `src/main.ts` -- [x] Output: `main.js` -- [x] Format: CommonJS (`cjs`) -- [x] Target: ES2018 -- [x] External dependencies properly configured: - - [x] `obsidian` - - [x] `electron` - - [x] All `@codemirror/*` packages - - [x] All `@lezer/*` packages - - [x] Node.js built-in modules -- [x] Source maps: inline for dev, disabled for production -- [x] Minification: enabled for production -- [x] Tree shaking: enabled - -### tsconfig.json -- [x] Module: ESNext -- [x] Target: ES6 -- [x] Strict type checking enabled -- [x] Source maps: inline -- [x] Library: DOM, ES5, ES6, ES7 - -## ✅ Project Structure - -``` -git-file-push/ -├── .github/ -│ └── workflows/ # CI/CD workflows -├── src/ -│ ├── main.ts # Plugin entry point -│ ├── settings.ts # Settings interface -│ ├── logic/ # Business logic -│ ├── services/ # API services -│ └── ui/ # UI components -├── tests/ # Test files -├── manifest.json # Plugin metadata -├── versions.json # Version mapping -├── styles.css # Plugin styles -├── package.json # NPM configuration -├── tsconfig.json # TypeScript config -├── esbuild.config.mjs # Build config -├── .gitignore # Git ignore rules -├── LICENSE # License file -└── README.md # Documentation -``` - -## ✅ Plugin Class - -- [x] Main class extends `Plugin` from Obsidian API -- [x] Implements `onload()` method -- [x] Implements `onunload()` method -- [x] Properly registers: - - [x] Commands via `addCommand()` - - [x] Ribbon icons via `addRibbonIcon()` - - [x] Settings tab via `addSettingTab()` - - [x] View types via `registerView()` - - [x] Event handlers via `registerEvent()` - - [x] Context menu items via `registerEvent()` - -## ✅ Settings - -- [x] Settings interface defined -- [x] Default settings provided -- [x] Settings loaded in `onload()` via `loadData()` -- [x] Settings saved via `saveData()` -- [x] Settings tab UI implemented - -## ✅ Development Scripts - -- [x] `npm run dev` - Development mode with watch -- [x] `npm run build` - Production build -- [x] `npm run version` - Version bump script -- [x] `npm run lint` - Code linting -- [x] `npm run test` - Run tests - -## ✅ Git Configuration - -- [x] `.gitignore` properly configured: - - [x] `node_modules/` excluded - - [x] `main.js` excluded (built file) - - [x] `*.map` excluded (source maps) - - [x] IDE files excluded - - [x] `data.json` excluded (user data) - -## ✅ Release Process - -- [x] GitHub Actions workflow for releases -- [x] Automated version bumping -- [x] Release assets include: - - [x] `main.js` - - [x] `manifest.json` - - [x] `styles.css` - -## ✅ Best Practices - -- [x] TypeScript with strict mode -- [x] ESLint configuration -- [x] Unit tests with Vitest -- [x] Proper error handling -- [x] User notifications via `Notice` -- [x] Async operations properly handled -- [x] No blocking operations in main thread -- [x] Mobile compatibility (`isDesktopOnly: false`) -- [x] Proper cleanup in `onunload()` - -## ✅ API Usage - -- [x] Uses official Obsidian API -- [x] No direct DOM manipulation outside Obsidian API -- [x] Proper use of `App`, `Plugin`, `PluginSettingTab` -- [x] Proper use of `TFile`, `Vault` APIs -- [x] Proper use of `Modal`, `Notice` for UI -- [x] Proper use of `WorkspaceLeaf`, `ItemView` for custom views - -## ✅ Documentation - -- [x] README.md with: - - [x] Plugin description - - [x] Features list - - [x] Installation instructions - - [x] Usage guide - - [x] Configuration guide -- [x] CHANGELOG.md for version history -- [x] LICENSE file - -## Summary - -✅ **The Git File Push plugin fully complies with Obsidian plugin development guidelines.** - -All required files are present, build configuration is correct, and the plugin follows best practices for Obsidian plugin development. diff --git a/README.md b/README.md index 3a33bbf..c1888aa 100644 --- a/README.md +++ b/README.md @@ -5,18 +5,26 @@ An Obsidian plugin that enables seamless synchronization of individual notes wit ## Features - **Multiple Git Services**: Support for both GitLab and GitHub (user selectable) +- **GitHub Organization Support**: Works with both personal and organization repositories - **Push to Remote**: Upload individual notes to your Git repository - **Pull from Remote**: Download and sync notes from your repository -- **Batch Operations**: Push or pull all modified files at once +- **Batch Operations**: Push or pull all modified files at once with progress tracking - **Sync Status View**: Visual dashboard showing all files' sync status with complete git diff +- **Remote-Only Files Detection**: Shows files that exist on remote but not locally +- **Batch Selection**: Select multiple files for batch push/pull/delete operations +- **Status Filtering**: Filter files by sync status (All/Synced/Modified/Not in remote/Remote only) +- **Progress Bar**: Real-time progress indicator during sync operations +- **Last Sync Time**: Display when the last sync check was performed - **Conflict Resolution**: Visual diff viewer to compare local and remote versions when conflicts occur - **Vault Folder Filter**: Optionally sync only files within a specific vault folder - **Ribbon Icon**: Quick access button in the left sidebar for pushing the current note - **Command Palette**: Commands for pushing and pulling files (single or batch) - **Context Menu**: Right-click any file to push or pull directly from the file menu - **Cross-Platform**: Works on both desktop and mobile versions of Obsidian +- **Mobile Optimized**: Responsive UI design for small screens - **Sync Tracking**: Maintains metadata to track last synced SHA and timestamp for each file - **Conflict Detection**: Automatically detects conflicts and prompts for resolution +- **Auto-Refresh**: Automatically updates file status after push/pull operations ## Setup @@ -42,39 +50,120 @@ An Obsidian plugin that enables seamless synchronization of individual notes wit ## Usage -### View Sync Status +### Sync Status View + +The Sync Status View is the main interface for managing your file synchronization. + +**Opening the view:** - Click the list-checks icon in the left ribbon, or - Use Command Palette: "Open sync status view" -- Click "Refresh Status" to check all files against the remote repository -- View complete git diff for modified files -- Push or pull individual files directly from the status view -- Use "Push All Modified" or "Pull All Modified" for batch operations + +**Understanding the interface:** + +1. **Service Information Panel** + - Shows current service (GitLab/GitHub), branch, and vault folder + - Displays last sync time + +2. **Control Buttons** + - **Refresh status**: Check all files against remote repository (shows progress bar) + - **Select all**: Select all files in current filter view + - **Deselect all**: Clear all selections + - **Push selected (N)**: Push all selected files to remote + - **Pull selected (N)**: Pull all selected files from remote + - **Delete selected (N)**: Delete selected local files (with confirmation) + +3. **Status Filters** + - **All**: Show all files + - **Synced**: Files that match remote (✓) + - **Modified**: Files with local changes (⚠) + - **Not in remote**: Local files not yet pushed (✗) + - **Remote only**: Files on remote but not local (↓) + +4. **File Status Summary** + - Shows count of files in each status category + +5. **File List** + - Each file shows: checkbox, status icon, file path, and status text + - Click checkbox to select files for batch operations + - Files show different actions based on status: + - **Modified files**: Show diff button, Push, and Pull buttons + - **Not in remote**: Push to remote, Remove local file buttons + - **Remote only**: Pull from remote button + +**Workflow examples:** + +*Sync all changes to remote:* +1. Click "Refresh status" +2. Review modified files +3. Click "Select all" or manually select files +4. Click "Push selected" + +*Pull new files from remote:* +1. Click "Refresh status" +2. Click "Remote only" filter +3. Click "Select all" +4. Click "Pull selected" + +*Clean up local files not in remote:* +1. Click "Refresh status" +2. Click "Not in remote" filter +3. Select unwanted files +4. Click "Delete selected" ### Push Files + **Single file:** - Click the cloud upload icon in the left ribbon, or - Use Command Palette: "Push current file to GitLab/GitHub", or - Right-click a file and select "Push to GitLab/GitHub" +- Status updates automatically after push -**All files:** -- Use Command Palette: "Push all markdown files" -- Or use "Push All Modified" button in the sync status view +**Multiple files:** +- Open Sync Status View +- Select files using checkboxes +- Click "Push selected (N)" +- Or use "Refresh status" and filter by "Modified" or "Not in remote" ### Pull Files + **Single file:** - Use Command Palette: "Pull current file from GitLab/GitHub", or - Right-click a file and select "Pull from GitLab/GitHub" +- Status updates automatically after pull -**All files:** +**Multiple files:** +- Open Sync Status View +- Select files using checkboxes +- Click "Pull selected (N)" +- Or filter by "Remote only" to see files only on remote + +**Pull remote-only files:** +- These are files that exist on remote but not in your local vault +- Open Sync Status View → Click "Remote only" filter +- Select files and click "Pull selected" to download them + +### Batch Operations + +**Push all modified files:** +- Use Command Palette: "Push all markdown files" +- Confirms before pushing +- Shows progress during operation +- Auto-refreshes status when complete + +**Pull all modified files:** - Use Command Palette: "Pull all markdown files" -- Or use "Pull All Modified" button in the sync status view +- Warns about overwriting local changes +- Shows progress during operation +- Auto-refreshes status when complete ### Conflict Resolution + When a conflict is detected: 1. A modal will appear showing both local and remote versions 2. Review the differences in the diff viewer 3. Choose to keep either the local or remote version 4. The chosen version will be synced +5. File status updates automatically ## Development diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 4aa4446..0000000 --- a/RELEASE.md +++ /dev/null @@ -1,138 +0,0 @@ -# Release Guide - -This guide explains how to create a new release for the Git File Push plugin. - -## Prerequisites - -- Ensure all changes are committed and pushed to the main branch -- All tests pass (`npm run test`) -- Build succeeds (`npm run build`) - -## Release Process - -### 1. Update Version - -Run the version bump script: - -```bash -# For patch version (1.0.0 -> 1.0.1) -npm version patch - -# For minor version (1.0.0 -> 1.1.0) -npm version minor - -# For major version (1.0.0 -> 2.0.0) -npm version major -``` - -This will: -- Update `package.json` version -- Update `manifest.json` version -- Update `versions.json` with the new version -- Create a git commit with the version bump - -### 2. Update CHANGELOG.md - -Edit `CHANGELOG.md` and add a new section for the version: - -```markdown -## [1.0.1] - 2026-04-24 - -### Added -- New feature description - -### Fixed -- Bug fix description - -### Changed -- Change description - -[1.0.1]: https://github.com/tianyao/gitlab-files-push/releases/tag/1.0.1 -``` - -Commit the changelog: - -```bash -git add CHANGELOG.md -git commit -m "docs: update changelog for v1.0.1" -``` - -### 3. Create and Push Tag - -```bash -# Create a tag matching the version -git tag 1.0.1 - -# Push the tag to trigger the release workflow -git push origin 1.0.1 -``` - -### 4. Automated Release - -The GitHub Actions workflow will automatically: -1. Run tests -2. Build the plugin -3. Create a GitHub release -4. Upload `main.js`, `manifest.json`, and `styles.css` as release assets - -### 5. Verify Release - -1. Go to https://github.com/tianyao/git-file-push/releases -2. Verify the new release is created -3. Check that all three files are attached -4. Review the release notes - -## Manual Release (if needed) - -If the automated workflow fails, you can create a release manually: - -1. Build the plugin: - ```bash - npm run build - ``` - -2. Go to GitHub → Releases → Draft a new release -3. Choose the tag you created -4. Add release notes from CHANGELOG.md -5. Upload `main.js`, `manifest.json`, and `styles.css` -6. Publish the release - -## Version Numbering - -Follow [Semantic Versioning](https://semver.org/): - -- **MAJOR** (x.0.0): Breaking changes -- **MINOR** (0.x.0): New features, backwards compatible -- **PATCH** (0.0.x): Bug fixes, backwards compatible - -## Troubleshooting - -### Workflow fails on test - -```bash -npm run test -``` - -Fix any failing tests before creating the release. - -### Workflow fails on build - -```bash -npm run build -``` - -Ensure the build succeeds locally. - -### Tag already exists - -```bash -# Delete local tag -git tag -d 1.0.1 - -# Delete remote tag -git push origin :refs/tags/1.0.1 - -# Create new tag -git tag 1.0.1 -git push origin 1.0.1 -``` diff --git a/RELEASE_GUIDE.md b/RELEASE_GUIDE.md deleted file mode 100644 index f128cf1..0000000 --- a/RELEASE_GUIDE.md +++ /dev/null @@ -1,191 +0,0 @@ -# 发布新版本指南 - -本项目提供两种发布方式: - -## 方式一:自动版本管理(推荐) - -使用 GitHub Actions 自动更新版本号并发布。 - -### 步骤: - -1. 进入 GitHub 仓库 -2. 点击 **Actions** 标签 -3. 选择 **Auto Release** workflow -4. 点击 **Run workflow** 按钮 -5. 选择版本类型: - - **patch**: 修复 bug (1.0.0 → 1.0.1) - - **minor**: 新功能 (1.0.0 → 1.1.0) - - **major**: 重大变更 (1.0.0 → 2.0.0) -6. 点击 **Run workflow** - -### 自动执行的操作: - -✅ 运行测试 -✅ 更新 package.json 版本号 -✅ 更新 manifest.json 版本号 -✅ 更新 versions.json -✅ 更新 CHANGELOG.md -✅ 提交并推送更改 -✅ 创建 git tag -✅ 创建 GitHub Release -✅ 上传 main.js, manifest.json, styles.css - -### 优点: - -- 一键完成所有操作 -- 不会遗漏任何步骤 -- 版本号自动同步 -- 减少人为错误 - ---- - -## 方式二:手动发布 - -适合需要更多控制的情况。 - -### 步骤: - -1. **更新版本号** - ```bash - # 修复 bug - npm version patch - - # 新功能 - npm version minor - - # 重大变更 - npm version major - ``` - -2. **手动更新 manifest.json** - ```bash - # 编辑 manifest.json,更新 version 字段 - ``` - -3. **手动更新 versions.json** - ```json - { - "1.0.0": "0.15.0", - "1.0.1": "0.15.0" // 添加新版本 - } - ``` - -4. **更新 CHANGELOG.md** - ```markdown - ## [1.0.1] - 2026-04-24 - - ### Fixed - - Bug fix description - ``` - -5. **提交更改** - ```bash - git add . - git commit -m "chore: bump version to 1.0.1" - git push - ``` - -6. **创建并推送 tag** - ```bash - git tag 1.0.1 - git push origin 1.0.1 - ``` - -7. **GitHub Actions 自动创建 Release** - - release.yml workflow 会自动触发 - - 构建插件 - - 创建 GitHub Release(草稿) - - 上传文件 - -8. **编辑 Release** - - 进入 GitHub Releases - - 编辑草稿 release - - 添加发布说明 - - 发布 - ---- - -## 版本号规范 - -遵循 [语义化版本](https://semver.org/lang/zh-CN/): - -- **MAJOR (x.0.0)**: 不兼容的 API 变更 -- **MINOR (0.x.0)**: 向后兼容的新功能 -- **PATCH (0.0.x)**: 向后兼容的 bug 修复 - -### 示例: - -- `1.0.0` → `1.0.1`: 修复了一个 bug -- `1.0.1` → `1.1.0`: 添加了新功能 -- `1.1.0` → `2.0.0`: 重大变更,可能不兼容旧版本 - ---- - -## 发布检查清单 - -在发布前确认: - -- [ ] 所有测试通过 (`npm run test`) -- [ ] 构建成功 (`npm run build`) -- [ ] Lint 检查通过 (`npm run lint`) -- [ ] 在 Obsidian 中测试过 -- [ ] 更新了 CHANGELOG.md -- [ ] README.md 是最新的 - ---- - -## 故障排除 - -### Workflow 失败 - -**测试失败:** -```bash -npm run test -``` -修复失败的测试后重试。 - -**构建失败:** -```bash -npm run build -``` -确保本地构建成功。 - -**权限错误:** -- 检查仓库设置 → Actions → General → Workflow permissions -- 选择 "Read and write permissions" - -### Tag 已存在 - -```bash -# 删除本地 tag -git tag -d 1.0.1 - -# 删除远程 tag -git push origin :refs/tags/1.0.1 - -# 重新创建 -git tag 1.0.1 -git push origin 1.0.1 -``` - ---- - -## 首次发布到 Obsidian 社区 - -完成首次 release 后: - -1. Fork [obsidian-releases](https://github.com/obsidianmd/obsidian-releases) -2. 编辑 `community-plugins.json`,添加: - ```json - { - "id": "git-file-push", - "name": "Git File Push", - "author": "tianyao", - "description": "Sync individual notes with GitLab or GitHub. Push, pull, and track changes across mobile and desktop with visual diff and conflict resolution.", - "repo": "tianyao/git-file-push" - } - ``` -3. 创建 Pull Request -4. 等待 Obsidian 团队审核 - -详见 [SUBMISSION.md](./SUBMISSION.md) diff --git a/RELEASE_OPTIONS.md b/RELEASE_OPTIONS.md deleted file mode 100644 index 5fa11f0..0000000 --- a/RELEASE_OPTIONS.md +++ /dev/null @@ -1,191 +0,0 @@ -# 发布方式总览 - -本项目提供三种发布方式,根据你的需求选择: - -## 🚀 方式一:Semantic Release(推荐) - -**完全自动化,基于 commit message** - -### 优点 -- ✅ 完全自动化,无需手动操作 -- ✅ 强制规范的 commit message -- ✅ 自动生成 CHANGELOG -- ✅ 版本号由代码变更决定,更合理 -- ✅ 不会遗漏任何步骤 - -### 使用方法 -```bash -# 1. 按规范提交代码 -git commit -m "feat: add new feature" - -# 2. 推送到主分支 -git push origin main - -# 3. 自动发布! -``` - -### Commit 规范 -- `feat:` → 新功能 → MINOR 版本 (1.0.0 → 1.1.0) -- `fix:` → Bug 修复 → PATCH 版本 (1.0.0 → 1.0.1) -- `BREAKING CHANGE:` → 重大变更 → MAJOR 版本 (1.0.0 → 2.0.0) - -### 配置文件 -- `.releaserc.json` - Semantic Release 配置 -- `.github/workflows/semantic-release.yml` - GitHub Actions workflow - -### 详细文档 -参见 [SEMANTIC_RELEASE.md](./SEMANTIC_RELEASE.md) - ---- - -## 🎯 方式二:Auto Release - -**手动触发,选择版本类型** - -### 优点 -- ✅ 可以手动控制发布时机 -- ✅ 简单的版本选择(patch/minor/major) -- ✅ 自动更新所有文件 - -### 使用方法 -1. 进入 GitHub → Actions → Auto Release -2. 点击 "Run workflow" -3. 选择版本类型: - - **patch**: 1.0.0 → 1.0.1 - - **minor**: 1.0.0 → 1.1.0 - - **major**: 1.0.0 → 2.0.0 -4. 点击 "Run workflow" - -### 自动执行 -- 运行测试 -- 更新版本号(package.json, manifest.json, versions.json) -- 更新 CHANGELOG -- 创建 commit 和 tag -- 构建插件 -- 创建 GitHub Release -- 上传文件 - -### 配置文件 -- `.github/workflows/auto-release.yml` - ---- - -## 📦 方式三:Manual Release - -**完全手动控制** - -### 优点 -- ✅ 完全控制每个步骤 -- ✅ 适合特殊情况 - -### 使用方法 -```bash -# 1. 更新版本号 -npm version patch # 或 minor, major - -# 2. 手动更新 manifest.json 和 versions.json - -# 3. 更新 CHANGELOG.md - -# 4. 提交更改 -git add . -git commit -m "chore: bump version to 1.0.1" -git push - -# 5. 创建并推送 tag -git tag 1.0.1 -git push origin 1.0.1 - -# 6. GitHub Actions 自动创建 Release(草稿) - -# 7. 手动编辑并发布 Release -``` - -### 配置文件 -- `.github/workflows/release.yml` - ---- - -## 📊 对比表 - -| 特性 | Semantic Release | Auto Release | Manual Release | -|------|-----------------|--------------|----------------| -| 自动化程度 | 🟢 完全自动 | 🟡 半自动 | 🔴 手动 | -| 版本决策 | 🟢 基于代码变更 | 🟡 手动选择 | 🟡 手动选择 | -| CHANGELOG | 🟢 自动生成 | 🟡 需要手动编辑 | 🔴 完全手动 | -| Commit 规范 | 🟢 强制规范 | 🔴 无要求 | 🔴 无要求 | -| 出错风险 | 🟢 低 | 🟡 中 | 🔴 高 | -| 学习成本 | 🟡 需要学习规范 | 🟢 简单 | 🟢 简单 | - ---- - -## 🎯 推荐使用场景 - -### 使用 Semantic Release(推荐) -- ✅ 日常开发和发布 -- ✅ 团队协作项目 -- ✅ 需要规范的 commit history -- ✅ 希望完全自动化 - -### 使用 Auto Release -- ✅ 不想学习 commit 规范 -- ✅ 需要手动控制发布时机 -- ✅ 快速发布 - -### 使用 Manual Release -- ✅ 特殊情况需要完全控制 -- ✅ 调试发布流程 -- ✅ 紧急修复 - ---- - -## 🔧 配置 - -### 启用 Semantic Release - -如果你选择使用 Semantic Release,建议禁用其他两个 workflow 以避免冲突: - -```bash -# 重命名或删除其他 workflows -mv .github/workflows/auto-release.yml .github/workflows/auto-release.yml.disabled -mv .github/workflows/release.yml .github/workflows/release.yml.disabled -``` - -### 同时使用多个方式 - -如果你想保留多个选项: -- Semantic Release 用于日常自动发布 -- Auto Release 用于紧急手动发布 -- Manual Release 作为备用 - ---- - -## 📚 相关文档 - -- [SEMANTIC_RELEASE.md](./SEMANTIC_RELEASE.md) - Semantic Release 详细指南 -- [RELEASE_GUIDE.md](./RELEASE_GUIDE.md) - 手动发布指南 -- [WORKFLOWS.md](./WORKFLOWS.md) - GitHub Actions 说明 -- [SUBMISSION.md](./SUBMISSION.md) - Obsidian 插件提交指南 - ---- - -## 🚀 快速开始 - -### 推荐:使用 Semantic Release - -1. **学习 commit 规范**(5 分钟) - - `feat:` 新功能 - - `fix:` Bug 修复 - - `docs:` 文档更新 - -2. **正常开发** - ```bash - git commit -m "feat: add new feature" - git push origin main - ``` - -3. **自动发布!** - - 无需其他操作 - - 检查 GitHub Releases 查看结果 - -就这么简单!🎉 diff --git a/SEMANTIC_RELEASE.md b/SEMANTIC_RELEASE.md deleted file mode 100644 index 4a0af55..0000000 --- a/SEMANTIC_RELEASE.md +++ /dev/null @@ -1,236 +0,0 @@ -# Semantic Release 使用指南 - -本项目使用 [semantic-release](https://semantic-release.gitbook.io/) 自动管理版本号和发布。 - -## 工作原理 - -Semantic Release 根据 **commit message** 自动决定版本号: - -- `feat:` → **MINOR** 版本 (1.0.0 → 1.1.0) -- `fix:` → **PATCH** 版本 (1.0.0 → 1.0.1) -- `BREAKING CHANGE:` → **MAJOR** 版本 (1.0.0 → 2.0.0) - -## Commit Message 规范 - -使用 [Conventional Commits](https://www.conventionalcommits.org/) 格式: - -``` -(): - - - -