docs: resync after card fixes — title auto-fit, truncate, abbreviated ticks (#15)

Several recent code changes hadn't propagated to the docs:

- design-guidelines
  * Card frame title row: document the 11–15 px auto-shrink (not a flat
    15 px anymore).
  * Donut Top-N: already 7 (updated earlier).
  * Bar-chart section renamed to cover weekday + by-year too; document
    the peak-vs-dim highlight convention and the niceTicks yMax ≥ max
    invariant.
  * Add Heatmap / Stat-column (streak) / List (top-starred) card
    sections — they were missing entirely.
  * Rewrite "Text overflow" from "we don't truncate" to the current
    truth (truncate helper, formatTick abbreviations).
  * Replace dangling `truncateName` reference with `truncate`.

- code-standards
  * SVG output standards: call out truncate, formatTick abbreviation,
    header auto-fit so the card-review gate reflects what the renderers
    actually do.

- codebase-summary
  * Layout tree: svg.go / axis.go comments list the helpers they now
    contain; productive.go notes the weekday histogram.
  * demo/ tree shows the index vs per-theme split.
  * Data-flow diagram includes Weekday in the productive pass.
  * Test coverage row lists TestCardsFitFrame / TestFitTitleFontSize /
    TestNiceTicksCoversMax — the new invariant guards.

- system-architecture
  * Shared primitives list adds renderWeekday and renderHeatmap; donut
    blurb updated to "top 7".
  * New "Chart-geometry invariants" block documents niceTicks ceiling,
    formatTick abbreviation, header auto-fit.

- project-roadmap
  * Phase 7.5 bullet updated to describe the index + per-theme demo
    split (was single-README TOC).
This commit is contained in:
2026-04-19 10:22:03 +07:00
committed by GitHub
parent fc29729aa2
commit 88397e80a3
5 changed files with 67 additions and 22 deletions
+9 -7
View File
@@ -15,13 +15,13 @@ ghstats/
│ │ ├── queries.go # profileQuery, commitHistoryQuery, contributionYearQuery
│ │ ├── model.go # Profile, RepoInfo, LangStat, LangEdge, DailyContribution
│ │ ├── profile.go # FetchProfile — user + owned repos + stats + calendar
│ │ ├── productive.go # FetchProductive — commit history → hour histogram + lang buckets
│ │ ├── productive.go # FetchProductive — commit history → hour + weekday histograms + lang buckets
│ │ ├── contributions_all_time.go # FetchContributionsAllTime — per-year loop → seed list + daily series
│ │ └── profile_test.go # sortLangStats tiebreak
│ ├── card/ # SVG renderers; one file per card
│ │ ├── card.go # Card interface, RenderAll, allCards slice
│ │ ├── svg.go # escapeXML, formatInt, header, footer
│ │ ├── axis.go # niceTicks (d3-style 1/2/5 × 10^k), formatTick
│ │ ├── svg.go # escapeXML, formatInt, truncate, header (auto-fit title), footer
│ │ ├── axis.go # niceTicks (d3-style, last tick ≥ max), formatTick (1500→"1.5k")
│ │ ├── icons.go # Octicon path strings
│ │ ├── profile.go # profile-details
│ │ ├── repos_per_language.go # repos-per-language
@@ -45,8 +45,10 @@ ghstats/
│ └── demo.yml # Renders every theme for the repo owner on push to main
├── docs/ # This directory
├── plans/ # Research reports + implementation plans
└── demo/ # Auto-generated gallery — every card × every theme + README
# (`output/` is entirely gitignored; see demo/ for reference renders)
└── demo/ # Auto-generated gallery
├── README.md # Lightweight index (links only, zero images)
└── <theme>/ # Per-theme page: 15 SVGs + README pairing LY / AT variants
# (`output/` is entirely gitignored; see demo/ for reference renders)
```
## Module responsibilities
@@ -99,7 +101,7 @@ contributionYearQuery ─┬──► SeedRepos + DailyContributionsAllTime + To
└─ seed into ─►
commitHistoryQuery ──► Productive + CommitsByLanguage (+ AllTime variants)
commitHistoryQuery ──► Productive + Weekday + CommitsByLanguage (+ AllTime variants)
15 SVG files per theme
@@ -107,7 +109,7 @@ commitHistoryQuery ──► Productive + CommitsByLanguage (+ AllTime variants)
## Test coverage
- `internal/card/card_test.go``RenderAll` produces 15 valid SVGs; XML escape through real render pipeline; `formatInt` cases; `TestDonutSingleSlice` (guards the empty-arc regression); `TestDonutEmpty` (no-data fallback).
- `internal/card/card_test.go``RenderAll` produces 15 valid SVGs; XML escape through real render pipeline; `formatInt` cases; `TestDonutSingleSlice` / `TestDonutEmpty` (donut edge cases); `TestCardsFitFrame` (renders every card against an adversarial profile and asserts text + coordinates stay in the 340×200 frame); `TestFitTitleFontSize` (pins the auto-shrink table for every real title); `TestNiceTicksCoversMax` (guards the `yMax ≥ dataMax` invariant so bars can't overflow chartH).
- `internal/github/profile_test.go``sortLangStats` ordering and tiebreak.
- `main_test.go``TestUTCOffsetLabel` covers UTC, Asia/Saigon, half-hour (Kolkata), quarter-hour (Kathmandu) zones.