feat(field-guide): add the habitat range map (FG-7) #108

Merged
manlycucumber merged 1 commit from feat/field-guide-range-map into develop 2026-07-12 21:07:16 +00:00

What

The last Field Guide engine PR (FG-7): a creature can show where it lives on a small
habitat range map. Built as SVG/DOM — never PixiJS — so it prerenders and stays readable with no JS,
per the Field Guide blueprint (docs/architecture/field-guide.md → "The habitat range map").

How

  • Schema — a range?: { base, regions[], caption } sub-schema on topic frontmatter
    (creatures-only, enforced in validateFieldGuide, mirroring anatomy).
  • Build-time integrityvalidateFieldGuide now parses the committed base map and checks each
    regions[] entry against its real <path id> set; a dangling region fails the build.
    parseSvgPathIds is pure and the validator takes the region resolver, so both stay unit-testable —
    the plugin does the filesystem read at the scanPublished site (the
    validateCrossLinks/validateArchives precedent).
  • RangeMap.svelte — the no-JS truth is the caption (a full sentence) plus a static,
    non-focusable list of region names. The committed, SVGO-clean static/maps/base.svg is inlined (a
    trusted asset) and the creature's regions are tinted via data-active — a pure enhancement, never
    a colour-only signal
    . Rendered by ArticleView when a creature declares range.
  • Reference — one range on red-fox (North America, Europe, Asia). Base map bundled + credited
    in CREDITS.md; caption/heading tokens added to check-offline.mjs so the no-JS bake is guarded.

After FG-7, v0.4.0 is content-only (the field-guide epic's last engine child).

Verification (dev container, Node 24 / pnpm 9.15.9)

step result
pnpm check (svelte-check) 0 errors / 0 warnings
pnpm lint (prettier + eslint) clean
guard:colour / guard:svg pass (base map SVGO-clean)
pnpm build pass (2 Pagefind records; range validated at build)
guard:external / content / provenance / offline pass (caption token baked)
pnpm test:unit 210 passed (+13: range schema, parseSvgPathIds, dangling region)
pnpm test:e2e (Chromium + axe) 42 passed (+1: range map bakes caption/regions/tint)

The prerendered /library/creatures/red-fox/ HTML carries <section class="range-map">, the caption,
the region list, and data-active on the three live regions — the tint bakes with no JS.

The Forgejo ci check will show red — that is the repo-wide missing-runner issue (every run fails,
including plain pushes to develop), not this change. Every gate step above was run locally.

## What The last Field Guide **engine** PR (FG-7): a creature can show **where it lives** on a small habitat range map. Built as SVG/DOM — never PixiJS — so it prerenders and stays readable with no JS, per the Field Guide blueprint (`docs/architecture/field-guide.md` → "The habitat range map"). ## How - **Schema** — a `range?: { base, regions[], caption }` sub-schema on topic frontmatter (creatures-only, enforced in `validateFieldGuide`, mirroring `anatomy`). - **Build-time integrity** — `validateFieldGuide` now parses the committed base map and checks each `regions[]` entry against its real `<path id>` set; a **dangling region fails the build**. `parseSvgPathIds` is pure and the validator takes the region resolver, so both stay unit-testable — the plugin does the filesystem read at the `scanPublished` site (the `validateCrossLinks`/`validateArchives` precedent). - **`RangeMap.svelte`** — the **no-JS truth** is the caption (a full sentence) plus a static, non-focusable list of region names. The committed, SVGO-clean `static/maps/base.svg` is inlined (a trusted asset) and the creature's regions are tinted via `data-active` — a **pure enhancement, never a colour-only signal**. Rendered by `ArticleView` when a creature declares `range`. - **Reference** — one range on **red-fox** (North America, Europe, Asia). Base map bundled + credited in `CREDITS.md`; caption/heading tokens added to `check-offline.mjs` so the no-JS bake is guarded. After FG-7, **v0.4.0 is content-only** (the field-guide epic's last engine child). ## Verification (dev container, Node 24 / pnpm 9.15.9) | step | result | | --- | --- | | `pnpm check` (svelte-check) | 0 errors / 0 warnings | | `pnpm lint` (prettier + eslint) | clean | | `guard:colour` / `guard:svg` | pass (base map SVGO-clean) | | `pnpm build` | pass (2 Pagefind records; range validated at build) | | `guard:external` / `content` / `provenance` / `offline` | pass (caption token baked) | | `pnpm test:unit` | 210 passed (+13: range schema, `parseSvgPathIds`, dangling region) | | `pnpm test:e2e` (Chromium + axe) | 42 passed (+1: range map bakes caption/regions/tint) | The prerendered `/library/creatures/red-fox/` HTML carries `<section class="range-map">`, the caption, the region list, and `data-active` on the three live regions — the tint bakes with no JS. > The Forgejo `ci` check will show red — that is the repo-wide missing-runner issue (every run fails, > including plain pushes to `develop`), not this change. Every gate step above was run locally.
feat(field-guide): add the habitat range map (FG-7)
Some checks failed
ci / ci (pull_request) Failing after 38s
6f587b57c8
The last Field Guide engine PR: a creature can now show WHERE it lives,
built as SVG/DOM (never PixiJS) so it prerenders and stays readable with
no JS.

- Schema: a `range?: { base, regions[], caption }` sub-schema (creatures
  only, enforced in validateFieldGuide, mirroring `anatomy`).
- validateFieldGuide is extended to parse the committed base map and check
  every `regions[]` entry against its real `<path id>` set — a dangling
  region fails the build. The SVG parse (parseSvgPathIds) is pure and the
  validator takes the region resolver, so both stay unit-testable; the
  plugin does the filesystem read at the scanPublished site.
- RangeMap.svelte: the no-JS truth is the caption (a full sentence) plus a
  static list of region names; the committed, SVGO-clean
  static/maps/base.svg is inlined (a trusted asset) and the creature's
  regions are tinted via data-active — a pure enhancement, never a
  colour-only signal. Rendered by ArticleView when a creature declares
  `range`.
- One reference range on red-fox (North America, Europe, Asia); the base
  map is bundled and credited in CREDITS.md; caption/heading tokens are
  added to check-offline.mjs so the no-JS bake is guarded.

Verified in the dev container: check, lint, guard:colour/svg, build,
guard:external/content/provenance/offline, and test:unit (210) all green;
test:e2e 42/42 including axe and the zero-external-requests offline proof.
manlycucumber force-pushed feat/field-guide-range-map from 6f587b57c8
Some checks failed
ci / ci (pull_request) Failing after 38s
to b852ad3877
Some checks failed
ci / ci (pull_request) Failing after 35s
2026-07-12 21:06:43 +00:00
Compare
manlycucumber deleted branch feat/field-guide-range-map 2026-07-12 21:07:16 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Bosco/bosco!108
No description provided.