feat(field-guide): add the habitat range map (FG-7) #108
No reviewers
Labels
No labels
area: arcade
area: art-studio
area: calendar
area: chapel
area: content
area: design
area: field-guide
area: infra
area: library
area: os
area: portal
area: sync
area: typing
blocked
breaking
bug
content: approved
content: changes-requested
content: drafting
content: needs-doctrinal-review
content: needs-review
dependencies
documentation
duplicate
enhancement
epic
github_actions
good first issue
help wanted
invalid
javascript
needs-triage
priority: high
priority: low
priority: medium
question
type: enhancement
type: feature
type: fix
type: perf
type: security
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Bosco/bosco!108
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/field-guide-range-map"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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
range?: { base, regions[], caption }sub-schema on topic frontmatter(creatures-only, enforced in
validateFieldGuide, mirroringanatomy).validateFieldGuidenow parses the committed base map and checks eachregions[]entry against its real<path id>set; a dangling region fails the build.parseSvgPathIdsis pure and the validator takes the region resolver, so both stay unit-testable —the plugin does the filesystem read at the
scanPublishedsite (thevalidateCrossLinks/validateArchivesprecedent).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.svgis inlined (atrusted asset) and the creature's regions are tinted via
data-active— a pure enhancement, nevera colour-only signal. Rendered by
ArticleViewwhen a creature declaresrange.in
CREDITS.md; caption/heading tokens added tocheck-offline.mjsso 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)
pnpm check(svelte-check)pnpm lint(prettier + eslint)guard:colour/guard:svgpnpm buildguard:external/content/provenance/offlinepnpm test:unitparseSvgPathIds, dangling region)pnpm test:e2e(Chromium + axe)The prerendered
/library/creatures/red-fox/HTML carries<section class="range-map">, the caption,the region list, and
data-activeon the three live regions — the tint bakes with no JS.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.6f587b57c8b852ad3877