|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +XMOJ-Script is a browser userscript that enhances the XMOJ online judge platform (xmoj.tech). This repository consists of: |
| 8 | +- **Main userscript** (`XMOJ.user.js`): ~5000 line single-file userscript with all features. **See "Working with XMOJ.user.js" section below for CRITICAL instructions on using the xmoj-code-navigator agent.** |
| 9 | +- **Update/version management scripts** (`Update/`): Automation for version bumping and releases |
| 10 | +- **Metadata and documentation**: `Update.json` tracks version history, README and contributing guides |
| 11 | + |
| 12 | +The `backend/` directory is a git submodule pointing to https://github.com/XMOJ-Script-dev/XMOJ-bbs and should be modified in that repository, not here. |
| 13 | + |
| 14 | +## Working with XMOJ.user.js (CRITICAL) |
| 15 | + |
| 16 | +**IMPORTANT: Due to the large size of XMOJ.user.js (~5000 lines), you MUST use the xmoj-code-navigator agent whenever you need to explore, search, or understand any part of this file.** |
| 17 | + |
| 18 | +### When to use xmoj-code-navigator |
| 19 | + |
| 20 | +Use the Task tool with `subagent_type="xmoj-code-navigator"` for: |
| 21 | + |
| 22 | +- **Finding specific functions or features**: "Where is the auto-refresh functionality implemented?" |
| 23 | +- **Understanding code sections**: "How does the login authentication work?" |
| 24 | +- **Locating code patterns**: "Find all API calls to the backend" |
| 25 | +- **Searching for specific implementations**: "Show me the dark mode toggle implementation" |
| 26 | +- **Verifying if code exists**: "Does XMOJ.user.js have a function for parsing XML?" |
| 27 | +- **ANY exploration task involving XMOJ.user.js** |
| 28 | + |
| 29 | +### Why use this agent |
| 30 | + |
| 31 | +Loading the entire XMOJ.user.js file into context: |
| 32 | +- Wastes context window space |
| 33 | +- Makes responses slower |
| 34 | +- Is unnecessary when you only need specific sections |
| 35 | + |
| 36 | +The xmoj-code-navigator agent efficiently locates and retrieves only the relevant code sections you need. |
| 37 | + |
| 38 | +### Example usage |
| 39 | + |
| 40 | +``` |
| 41 | +Instead of: Read tool on XMOJ.user.js (loads entire 5000 lines) |
| 42 | +Use: Task tool with xmoj-code-navigator agent to find specific sections |
| 43 | +``` |
| 44 | + |
| 45 | +**Exception**: Only use Read tool on XMOJ.user.js when: |
| 46 | +- You need to edit a specific line number you already know |
| 47 | +- You're making targeted edits and already know the exact location |
| 48 | +- You need to verify a small, specific section (use offset and limit parameters) |
| 49 | + |
| 50 | +## Development Workflow |
| 51 | + |
| 52 | +### Branch Structure and PR Requirements |
| 53 | + |
| 54 | +- `master`: Production branch - **DO NOT make PRs directly to master** |
| 55 | +- `dev`: Development branch - **ALL PRs must be based on and target this branch** |
| 56 | +- `extern-contrib`: External contributors must submit PRs to this branch |
| 57 | + |
| 58 | +**CRITICAL: All pull requests must:** |
| 59 | +1. Be based on the `dev` branch (branch off from `dev`) |
| 60 | +2. Target the `dev` branch (not `master`) |
| 61 | +3. Merge latest `dev` into your branch before submitting to resolve conflicts |
| 62 | + |
| 63 | +The workflow is: `dev` → (when ready) → `master` for releases. Direct PRs to `master` are not accepted. |
| 64 | +You should follow the PR template that can be found [here](https://raw.githubusercontent.com/XMOJ-Script-dev/.github/refs/heads/main/.github/PULL_REQUEST_TEMPLATE.md). |
| 65 | + |
| 66 | +### Version Management (CRITICAL - Fully Automated) |
| 67 | + |
| 68 | +Version updates are **fully automated** via GitHub Actions. When a PR to `dev` modifies `XMOJ.user.js`: |
| 69 | + |
| 70 | +1. The `UpdateVersion` workflow runs `Update/UpdateVersion.js` which automatically: |
| 71 | + - Bumps patch version in `package.json` |
| 72 | + - Updates `@version` in `XMOJ.user.js` metadata block |
| 73 | + - Adds/updates entry in `Update.json` with PR number, title, and timestamp |
| 74 | + - Commits changes back to the PR branch with `github-actions[bot]` |
| 75 | + |
| 76 | +2. Version sync is enforced between: |
| 77 | + - `package.json` → `"version": "x.y.z"` |
| 78 | + - `XMOJ.user.js` → `// @version x.y.z` (in metadata block) |
| 79 | + - `Update.json` → `UpdateHistory["x.y.z"]` (JSON key) |
| 80 | + |
| 81 | +**Never manually edit version numbers** - the automation handles this based on PR metadata. |
| 82 | + |
| 83 | +### Release Notes in PRs |
| 84 | + |
| 85 | +To add release notes to a PR that will appear in the release, include an HTML comment block in the PR description: |
| 86 | + |
| 87 | +```markdown |
| 88 | +<!-- release-notes |
| 89 | +Your release notes here in markdown format |
| 90 | +--> |
| 91 | +``` |
| 92 | + |
| 93 | +The `UpdateVersion.js` script extracts this and adds it to `Update.json` as the `Notes` field. |
| 94 | + |
| 95 | +### Bypassing Automation |
| 96 | + |
| 97 | +To prevent CI from touching your PR (e.g., during merge conflicts or debugging), add `//!ci-no-touch` anywhere in `Update.json`. The automation will remove it and exit without making other changes. |
| 98 | + |
| 99 | +### Release Process |
| 100 | + |
| 101 | +- **Pre-release**: Push to `dev` triggers a pre-release with `"Prerelease": true` in Update.json |
| 102 | +- **Release**: Merge `dev` to `master` triggers a production release |
| 103 | +- Releases are created by `Update/GetVersion.js` reading the version from XMOJ.user.js |
| 104 | +- Both workflows deploy to Cloudflare Pages and GitHub Pages |
| 105 | + |
| 106 | +## Code Structure |
| 107 | + |
| 108 | +### Main Userscript (`XMOJ.user.js`) |
| 109 | + |
| 110 | +A single-file userscript (~5000 lines) organized as: |
| 111 | + |
| 112 | +1. **Metadata block** (lines 1-50): Userscript headers |
| 113 | + - `@name`, `@version`, `@description`, `@author` |
| 114 | + - `@match` patterns for xmoj.tech and 116.62.212.172 |
| 115 | + - `@require` declarations for external libraries (CryptoJS, CodeMirror, FileSaver, marked, DOMPurify) |
| 116 | + - `@grant` permissions for GM APIs |
| 117 | + |
| 118 | +2. **Main script body**: Direct DOM manipulation and feature injection |
| 119 | + - Page detection and routing based on URL patterns |
| 120 | + - UI enhancements using Bootstrap classes |
| 121 | + - Feature implementations (auto-refresh, code checking, test data fetching, dark mode, etc.) |
| 122 | + - API calls to backend at `api.xmoj-bbs.tech` / `api.xmoj-bbs.me` |
| 123 | + |
| 124 | +Key classes/functions: |
| 125 | +- `compareVersions()` (line 112): Version comparison logic |
| 126 | +- `NavbarStyler` class (line 589): Navigation bar styling |
| 127 | +- `replaceMarkdownImages()` (line 715): Markdown image processing |
| 128 | + |
| 129 | +### Update Scripts (`Update/`) |
| 130 | + |
| 131 | +Node.js scripts run by GitHub Actions (not for local development): |
| 132 | + |
| 133 | +- **`UpdateVersion.js`**: Automated version bumping for PRs to `dev` |
| 134 | + - Reads PR number, title, body from command line args |
| 135 | + - Uses `gh` CLI to check out PR branch |
| 136 | + - Parses `<!-- release-notes -->` blocks from PR body |
| 137 | + - Updates version in all three locations |
| 138 | + - Pushes changes back to PR branch |
| 139 | + |
| 140 | +- **`GetVersion.js`**: Extracts current version from XMOJ.user.js for release workflows |
| 141 | + |
| 142 | +- **`UpdateToRelease.js`**: Changes `"Prerelease": false` when promoting to production |
| 143 | + |
| 144 | +- **`AutoLabel.js`**: Auto-labels PRs based on content |
| 145 | + |
| 146 | +These scripts directly manipulate `Update.json` and `XMOJ.user.js` using Node.js fs module. |
| 147 | + |
| 148 | +## Coding Standards |
| 149 | + |
| 150 | +### Style Guidelines (from CONTRIBUTING.md) |
| 151 | + |
| 152 | +- **Variables**: camelCase |
| 153 | +- **Functions**: PascalCase |
| 154 | +- **Classes**: TitleCase |
| 155 | +- **Line endings**: Unix (LF) |
| 156 | +- **Do NOT run code formatters** - maintain original formatting |
| 157 | +- **Use Bootstrap classes** instead of custom CSS |
| 158 | +- **No external libraries** without permission (script already includes many via `@require`) |
| 159 | + |
| 160 | +### Development Principles |
| 161 | + |
| 162 | +- **Stability before features**: Bug fixes take priority |
| 163 | +- Respect the original code style, even if inconsistent |
| 164 | +- New features require prior discussion in an issue |
| 165 | +- Before submitting PRs, merge `dev` into your branch and resolve conflicts |
| 166 | + |
| 167 | +## Testing |
| 168 | + |
| 169 | +No automated test suite exists. Manual testing workflow: |
| 170 | + |
| 171 | +1. Install the userscript in Tampermonkey/ScriptCat/Violentmonkey |
| 172 | +2. Navigate to xmoj.tech (or 116.62.212.172) |
| 173 | +3. Test features on relevant pages: |
| 174 | + - Problem lists |
| 175 | + - Problem detail pages |
| 176 | + - Status/submission pages |
| 177 | + - Contest pages |
| 178 | + - User profiles |
| 179 | + |
| 180 | +Observe browser console for errors and verify UI enhancements appear correctly. |
| 181 | + |
| 182 | +## Common Issues |
| 183 | + |
| 184 | +### Version Sync Errors |
| 185 | + |
| 186 | +If you see "XMOJ.user.js and Update.json have different patch versions": |
| 187 | +- The automation keeps these in sync normally |
| 188 | +- If manually editing (not recommended), update both files |
| 189 | +- Use `//!ci-no-touch` if you need to bypass automation temporarily |
| 190 | + |
| 191 | +### PR Requirements |
| 192 | + |
| 193 | +- **All PRs must be based on and target `dev` branch, not `master`** |
| 194 | +- Only PRs from the same repository (not forks) trigger auto-versioning |
| 195 | +- PRs must modify `XMOJ.user.js` to trigger version bumps |
| 196 | +- Must merge `dev` into your branch before submitting |
| 197 | +- External contributors must target `extern-contrib` branch |
| 198 | + |
| 199 | +### Single-File Architecture |
| 200 | + |
| 201 | +The entire userscript is intentionally in one file - do not split into modules. Userscript managers load it as a single file, with external dependencies via `@require` headers in the metadata block. |
0 commit comments