Loading demo/README.md was unusable — 65 themes × 15 SVGs = 975 images
in one page, and reloading made the tab lag for 10+ seconds. Restructure:
- demo/README.md shrinks to an index: one bullet per theme linking to
that theme's page. Zero images.
- demo/<theme>/README.md (new) embeds the 15 SVGs for that theme only,
grouped so the last-year / all-time variants sit side-by-side in HTML
tables. Readers compare LY vs AT without scrolling back and forth,
and fetch ~15 images instead of 975.
Per-theme page layout:
## At-a-glance profile · stats · streak (each full-width)
## Repos top-starred · repos-per-language
## Contributions heatmap · by-year, then
monthly shape: LY | AT (paired)
## When you commit hour-of-day: LY | AT
day-of-week: LY | AT
## What you commit language share: LY | AT
pair() and single() bash helpers skip missing SVGs so a future
partial-render doesn't emit dangling <img> tags.
The hardcoded cards[] array in demo.yml still listed the original 9,
so the S-tier additions (heatmap, streak, by-year, weekday pair,
top-starred) were rendered into demo/<theme>/ but never referenced in
demo/README.md. Expand the array to the full 15 in README card-table
order.
The dracula sample under output/dracula/ was a reference render for the
README. Now that demo/ auto-generates every card × every theme on each
push, the sample is redundant — and keeping it trackers means every
behavioral tweak shows up as a diff in committed SVGs.
- Delete output/dracula/*.svg.
- .gitignore: collapse `output/*` + `!output/dracula/` to a plain `output/`.
- demo.yml: drop `output/**` from paths-ignore (no longer part of any push).
- README / docs: point readers at demo/ instead of output/dracula/.
Runs on push to main (skipping its own demo/output/markdown commits),
builds the ghstats binary, renders every theme for the repo owner,
and writes a demo/README.md gallery back to main.
Adds an update-major-tag job that runs after test/docker/binaries all
pass. Extracts the major component from the pushed tag (v1.2.3 → v1)
and force-moves that tag to the current commit, then pushes.
Consumers using `uses: tiennm99/ghstats@v1` now pick up each new
minor/patch release automatically without a workflow edit on their
end. The v1 tag only moves if every artifact job succeeded, so it
never points at a commit whose binaries or Docker image failed to
publish.
- I3 — update FetchOptions doc to describe zero-value vs CLI-flag defaults.
- I5 — release workflow gates docker/binaries on a test job; tags no
longer ship broken artifacts.
- N1 — replace handwritten joinErrs with strings.Join.
- N3 — truncate() now backs up to a UTF-8 rune boundary so error
messages never end on a split codepoint.
- N4 — pin Docker base images (golang:1.26-alpine, alpine:3.21) to
SHA256 digests.
- N5 — pin third-party GitHub Actions to commit SHAs with version
comments for readability.
- N9 — drop the "(non-fork)" qualifier from the stats card label; the
underlying GraphQL doesn't actually filter forks, so the phrasing
was misleading.
- Add GraphQL client fetching profile, stats, language aggregation, and
per-repo commit histograms for the productive-time heatmap.
- Render real SVG cards (profile details, top languages, stats grid,
weekday×hour heatmap) with XML escaping and thousands-formatted numbers.
- Expand theme palette to 30 built-ins ported from github-readme-stats;
add -list-themes, multi-theme rendering, and 'all' shortcut.
- Package as Docker-based GitHub Action (action.yml, Dockerfile,
entrypoint.sh) with optional auto-commit of generated cards.
- Release workflow publishes GHCR image and cross-platform binaries on
v* tags.
- Unit tests cover rendering, XML escape, number formatting, language sort.