feat(docs): phase 14 - game-neutral core docs, an Ultima Online group, and checkTerms
All checks were successful
PR checks / checks (pull_request) Successful in 2m10s

PLAN.md §16, D63/D64, plus D67-D69 taken 2026-10-22.

- Core docs use core's words: a Team, a game server, the sidecar, the bridge
  plugin, the game module. Detail that belonged to Ultima Online moved into
  its pages rather than being dropped.
- New "Ultima Online" sidebar group (nine pages): an overview, Connect a
  ServUO shard, Verify the bridge, The shard connection, Client files,
  Troubleshooting, Bridge.cfg, sidecar.toml, Shard event catalog. Five moved
  URLs answer a real 301 (src/config/redirects.mjs, asserted by the served
  test).
- Getting started is game-neutral. "Connect your game server" keeps the old
  URL and hands off to each game; Rust links docs main:rust-link/INSTALL.md
  until phase 15. "Verify the whole stack" stays, neutral (D69).
- D68: GameExample.astro labels a game's real example on a core page with the
  game's name; checkTerms allows that game's words inside it.
- scripts/checkTerms.mjs, the twelfth check: 16 game words, docs pages and
  both sidebar trees, one allowlisted phrase (Discord's "Guild (server) ID").
  Wired into verify and pr-checks.yml.
- canonicalDocs grouped by game; the Rust group carries four documents.
- D67: the screenshot rule from #32 is adopted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-22 08:54:37 -05:00
parent 6046214d71
commit 4426d3e339
52 changed files with 1415 additions and 557 deletions

View File

@@ -0,0 +1,37 @@
---
import platform from '../data/platform.json';
/**
* A worked example that belongs to one game, quoted on a core page (PLAN.md §16, D68).
*
* D63 keeps a game's vocabulary inside that game's section, but a core page sometimes needs a
* real example rather than an invented one: a module manifest, an event dimension, the flag
* that tells the installer which game it is setting up. §1 prefers the real thing, because an
* invented example is checked by nothing and goes stale without anybody noticing.
*
* So the example keeps its game's words and says whose they are. This prints the game's name
* above the block — the same bargain D67 strikes for a screenshot: a game's words are honest
* on a core page when the game is named right beside them. `scripts/checkTerms.mjs` reads the
* `game` attribute and allows that game's words, and only that game's, between the tags.
*
* The name comes from `platform.json` rather than from the caller, so the label cannot say
* one game while the attribute that the check reads says another.
*/
interface Props {
/** A key of `platform.json`'s `games`: `uo` or `rust`. */
game: keyof typeof platform.games;
}
const { game } = Astro.props;
const entry = platform.games[game];
if (!entry) {
throw new Error(
`GameExample: unknown game "${game}". Use a key of platform.json's games: ${Object.keys(platform.games).join(', ')}.`,
);
}
---
<figure class="game-example" data-game={game}>
<figcaption class="game-example__label">{entry.name}</figcaption>
<div class="game-example__body"><slot /></div>
</figure>