Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
## Main Libraries

- **Node.js**: `>=24`
- **Framework**: `@docusaurus/core`, `@docusaurus/preset-classic` (`^3.10`)
- **Framework**: `@docusaurus/core`, `@docusaurus/preset-classic` (`^3.10`); `@docusaurus/faster` (Rspack/SWC, `future.faster: true`)
- **Language**: TypeScript (`tsx` components, `ts` config files)
- **React**: `^18`
- **Syntax highlighting**: `prism-react-renderer`
- **Search**: `@easyops-cn/docusaurus-search-local` — client-side, index built at compile time. Configured in `docusaurus.config.ts` (`themes` array). Add new locales to its `language` array when adding a new i18n locale. Search only works in the production build (`npm run build` + `npm run serve`), not in the dev server (`npm run start`).
- **Image zoom**: `docusaurus-plugin-image-zoom` (`themeConfig.zoom.selector`)
- **Search**: `@easyops-cn/docusaurus-search-local` — client-side, index built at compile time. Configured in `docusaurus.config.ts` (`themes` array). Add new locales to its `language` array when adding a new i18n locale, only if lunr has a stemmer for it (use the base language code for regional variants). Search only works in the production build (`npm run build` + `npm run serve`), not in the dev server (`npm run start`, which serves only `en`; other locales: `npm run start -- --locale <code>`).

## Architecture

Expand All @@ -24,22 +25,25 @@
- `sidebars.ts` — docs sidebar definition
- `src/pages/index.tsx` — homepage, composes section components (Hero and closing CTA inlined here)
- `src/pages/download.tsx` — Download page (`/download`)
- `src/releaseInfo.ts` — single source of truth for release versions/dates (homepage banner + Download page); edit only this file on a new release
- `src/components/<Name>/index.tsx` — one component per homepage section
- `src/components/<Name>/styles.module.css` — scoped styles per component
- `src/css/custom.css` — global CSS variable overrides (color palette)
- `src/theme/Footer/LinkItem/` — swizzled footer link (adds icons)
- `plugins/` — `blog-changelog.js` (changelog blog wrapper: rewords translator context in `options.json`), `remark-zoom-large-images.js`
- `docs/` — English documentation (Markdown)
- `blog/` — Blog posts (`/blog`); `changelog/` — Changelog posts (`/changelog`, second blog plugin instance)
- `i18n/<locale>/` — translations (`code.json` for UI strings; mirrored `docs/`, `blog/`, `changelog/` for content)
- `static/img/` — images (`amule-logo.svg`, `social-card.png`, favicons, `screenshots/`, `docs/`)
- `static/img/` — images (`amule-logo.svg`, `social-card.png`, favicons, `screenshots/`, `docs/`); `static/manifest.webmanifest`; `static/skins/` (downloadable GUI skins)

## Documentation

`docsSidebar` (see `sidebars.ts`) opens with two standalone docs — Overview (`docs/index.md`) and Quick Start (`docs/quickstart-guide.md`) — then **four top-level categories** by audience. Keep them separate — never mix audiences.

- **User Manual** (`docs/manual/`) — install, configure, use, troubleshoot; for basic and expert users. Subdivided into `installation/`, `configuration/` (network config: `directories`, `network-connectivity`, `firewall`, `upnp`, `proxy`, `events`, `macos` + **editable text config files** in `config-files/`: `amule.conf`, `remote.conf`), `interfaces/` (GUI under `gui/`, plus `amuled`, `amuleapi` (folder `amuleapi/`: daemon `index` + `web-ui` subpage), `amulecmd`, `amuleweb`), `utilities/` (standalone helpers), `migration/`, `troubleshooting/`, `faq/`.
- **User Manual** (`docs/manual/`) — install, configure, use, troubleshoot; for basic and expert users. Subdivided into `installation/`, `configuration/` (topic pages + **editable text config files** in `config-files/`: `amule.conf`, `remote.conf`, `amuleapi.conf`), `interfaces/` (GUI under `gui/`, plus `amuled`, `amuleapi` (folder `amuleapi/`: daemon `index` + `web-ui` subpage), `amulecmd`, `amuleweb`), `utilities/` (standalone helpers), `migration/`, `troubleshooting/`, `faq` (single doc).
- **Developer Guide** (`docs/developer/`) — for aMule developers and advanced integrators: compilation (`compilation/`), debugging, testing, translations, documentation, code style, the **file-format reference** (`file-formats/`: byte layouts of `.met`/`.dat` files), and the **EC protocol**.
- **P2P Networks** (`docs/p2p-networks/`) — general **protocol** description and historical reference: eD2k (`ed2k/`), Kademlia (`kademlia`), `concepts`, `other-networks`. **Do not mix protocol with aMule's concrete implementation** — implementation details belong in the User Manual / Developer Guide and are linked, not embedded.
- **Contributing** (`docs/contributing/`) — `bug-report`.
- **Contributing** (`docs/contributing/`) — `bug-report`, `translating` (translator-facing Weblate guide; admin setup stays in `developer/translations/weblate`).

## Homepage Components

Expand All @@ -50,11 +54,11 @@ Inlined in `src/pages/index.tsx`: split Hero (logo, tagline, intro, CTA buttons
| `FeaturesSection` | Alternating screenshot/feature rows + "And much more" card grid |

- Screenshots: `static/img/screenshots/*.png`, cropped from `static/img/docs/` (the up-to-date captures). Class `home-zoom` enables click-to-zoom (`zoom.selector` in `docusaurus.config.ts`).
- Motion: CSS only (`animation-timeline: view()` scroll reveal), guarded by `prefers-reduced-motion`.
- Motion: CSS only (hero fade-in, `animation-timeline: view()` scroll reveal in `FeaturesSection`), always inside `@media (prefers-reduced-motion: no-preference)`.

## i18n

- Default locale: `en`. The enabled locales are defined in `docusaurus.config.ts` (`i18n.locales`) — that array is the source of truth; don't duplicate the list here.
- Default locale: `en`. The enabled locales are defined in `docusaurus.config.ts` (`i18n.locales`) — that array is the source of truth; don't duplicate the list here. `i18n/` also holds Weblate-synced locales not yet in that array; they are not built.
- UI strings (React components): `i18n/<locale>/code.json` — each entry has `message` (translate this) and `description` (context, do not translate).
- **Translated JSON files contain only `message`** — the `description` is translator context and belongs **only** in the English base (`i18n/en/`). Never write `description` into any non-`en` locale file (`code.json`, `navbar.json`, `footer.json`, `current.json`, blog/changelog `options.json`). `write-translations -- --locale <code>` re-adds them and Docusaurus has no option to disable this, so strip them before committing (Weblate keeps the translated files `message`-only via the WebExtension JSON format).
- Docs content: `i18n/<locale>/docusaurus-plugin-content-docs/current/` mirrors `docs/`.
Expand All @@ -63,7 +67,7 @@ Inlined in `src/pages/index.tsx`: split Hero (logo, tagline, intro, CTA buttons
- Add a new locale: register in `docusaurus.config.ts`, run `npm run write-translations -- --locale <code>`, then translate generated files.
- Update translations after English changes: run `npm run write-translations -- --locale <code>` (adds new keys, preserves existing ones), then translate new entries in `code.json` and update changed docs files manually.
- **Weblate base files**: `i18n/en/` holds the English source files for Weblate, generated by `npm run write-translations` (no `--locale`). After adding/changing any `<Translate>`/`translate()` string, run it and commit `i18n/en/` — the `Build Check` CI runs the same command and **fails if `i18n/en/` drifts**.
- **All page/component text must be translatable**: wrap visible text in `<Translate id="...">text</Translate>` (JSX) or `translate({id, message})` (attributes). ID convention: `homepage.<section>.<key>`. The `id` and text **must be static string literals** — never `<Translate id={variable}>` nor `translate({id: variable})`, as `write-translations` extracts via static analysis and errors on dynamic values. In data-driven lists (`FEATURES`, `DOWNLOAD_OSES`, …) store the content as `<Translate>` nodes (typed `React.ReactNode`) or `translate({...})` calls **inside** the array, not as `*Id`/`*Default` fields.
- **All page/component text must be translatable**: wrap visible text in `<Translate id="...">text</Translate>` (JSX) or `translate({id, message})` (attributes). ID convention: `homepage.<section>.<key>`. The `id` and text **must be static string literals** — never `<Translate id={variable}>` nor `translate({id: variable})`, as `write-translations` extracts via static analysis and errors on dynamic values. In data-driven lists (`SHOWCASES`, `DOWNLOAD_OSES`, …) store the content as `<Translate>` nodes (typed `React.ReactNode`) or `translate({...})` calls **inside** the array, not as `*Id`/`*Default` fields.
- **Interpolation in `<Translate>`**: Docusaurus only supports `{varName}` placeholders — **not** `<tag>chunks</tag>` (FormatJS/react-intl syntax). For inline markup (`<strong>`, `<code>`, `<kbd>`) or links use `values`, e.g. `values={{ code: <code>flag</code> }}` or `values={{ link: <Link to="..."><Translate id="...">text</Translate></Link> }}` with `{code}` / `{link}` in the message. Prefer this over `dangerouslySetInnerHTML`.
- **Translation reference**: English is always the source of truth. All translations must faithfully reflect the English original — do not paraphrase or simplify.
- **Precision over naturalness**: Translations must be as accurate as possible. Readers are software users familiar with technical terminology, so use technical language freely. Keep English terms (e.g. "hash", "changelog", "release", "peer") when a translated equivalent would be less precise or less commonly used in the target language.
Expand All @@ -76,7 +80,7 @@ Inlined in `src/pages/index.tsx`: split Hero (logo, tagline, intro, CTA buttons

## Important Notes

- **Theming**: All styling must be theme-aware (light/dark). Use Infima CSS variables (`--ifm-background-color`, `--ifm-background-surface-color`, `--ifm-heading-color`, `--ifm-color-emphasis-*`, `--ifm-color-primary`) — never hardcoded hex colors or `rgba(255 255 255 / …)` overlays in page/component CSS modules. Exception: overlays over their own dark backdrop (e.g. the screenshots lightbox modal).
- **Theming**: All styling must be theme-aware (light/dark). Use Infima CSS variables (`--ifm-background-color`, `--ifm-background-surface-color`, `--ifm-heading-color`, `--ifm-color-emphasis-*`, `--ifm-color-primary`) — never hardcoded hex colors or `rgba(255 255 255 / …)` overlays in page/component CSS modules. Exception: overlays over their own dark backdrop.
- **Markdown line wrapping**: Do **not** hard-wrap prose. Write each paragraph/sentence on a single line (no manual line breaks mid-sentence). Keep tables, code blocks and list items as-is.
- **Images in docs**: referenced as `/img/docs/<file>` (served from `static/`).
- **Image zoom**: always use plain Markdown (`![alt](/img/docs/<file>)`), never hardcoded HTML `<img>` (Markdown paths are build-validated, `<img>` paths are not). Click-to-zoom is added automatically to large images (width ≥ 850px) by `plugins/remark-zoom-large-images.js`.
Expand Down
Loading