From 59e7bb4072fa6ec7466c2a3c35ee50020cc491ce Mon Sep 17 00:00:00 2001 From: Asmit Mishra <260386875+yourasmit15-web@users.noreply.github.com> Date: Tue, 8 Sep 2026 14:23:25 +0530 Subject: [PATCH] feat: add screen-reader summary to generated SVGs (#3) --- src/generate-constellation.js | 51 ++++------------------------------- 1 file changed, 5 insertions(+), 46 deletions(-) diff --git a/src/generate-constellation.js b/src/generate-constellation.js index a705a12..6ab6724 100644 --- a/src/generate-constellation.js +++ b/src/generate-constellation.js @@ -40,11 +40,6 @@ const fs = require("fs"); const path = require("path"); const https = require("https"); -// --------------------------------------------------------------------------- -// Config: env vars with defaults. Centralized here so action.yml and this -// script can never drift out of sync — every input maps 1:1 to a key below. -// --------------------------------------------------------------------------- - const DEFAULTS = { COMMIT_CAP: 20, TWINKLE_MIN_COMMITS: 10, @@ -120,10 +115,6 @@ if (!GITHUB_TOKEN) { process.exit(1); } -// --------------------------------------------------------------------------- -// GitHub GraphQL -// --------------------------------------------------------------------------- - const query = ` query($userName: String!) { user(login: $userName) { @@ -182,10 +173,6 @@ function graphqlRequest(query, variables) { }); } -// --------------------------------------------------------------------------- -// Small helpers -// --------------------------------------------------------------------------- - function seededRandom(seed) { let h = 0; for (let i = 0; i < seed.length; i++) { @@ -245,8 +232,6 @@ const MONTH_NAMES = [ "Dec", ]; -// Row index (0=Sun..6=Sat, matching GitHub's contributionDays order) -> -// short label. Only Mon/Wed/Fri are labeled, GitHub-style. const DAY_LABELS = { 1: "Mon", 3: "Wed", 5: "Fri" }; function formatMonthYear(date) { @@ -296,10 +281,6 @@ function computeStats(sortedDays) { return { longest, current, mostActiveMonth, mostActiveTotal }; } -// --------------------------------------------------------------------------- -// SVG construction -// --------------------------------------------------------------------------- - function buildSvg(weeks, theme, layout) { const { bg, starDim, textColor, recentColor, oldColor } = theme; const isMinimal = layout === "minimal"; @@ -327,10 +308,6 @@ function buildSvg(weeks, theme, layout) { const totalDays = allDays.length; - // Size and opacity are driven purely by the ABSOLUTE commit count for - // that day (not scaled relative to this dataset's max), so a 3-commit - // day always looks like a 3-commit day. Growth is capped at COMMIT_CAP - // so a single outlier day doesn't flatten every other day's contrast. function starRadius(count) { if (count === 0) return 0.6; const capped = Math.min(count, COMMIT_CAP); @@ -345,8 +322,6 @@ function buildSvg(weeks, theme, layout) { return 0.5 + scale * 0.5; } - // Recency-based color spans the FULL year: index 0 (oldest) -> oldColor, - // last index (most recent) -> recentColor. Zero-count days stay dim/neutral. function starColor(day, index) { if (day.count === 0) return starDim; const t = totalDays > 1 ? index / (totalDays - 1) : 1; @@ -372,8 +347,6 @@ function buildSvg(weeks, theme, layout) { const sortedDays = [...allDays].sort((a, b) => (a.date < b.date ? -1 : 1)); - // Group consecutive active days (gap <= 1 day) into streaks, then draw - // each streak as ONE continuous Catmull-Rom spline through all its points. const streaks = []; let currentStreak = []; for (let i = 0; i < sortedDays.length; i++) { @@ -425,22 +398,14 @@ function buildSvg(weeks, theme, layout) { const stats = computeStats(sortedDays); const totalContributions = allDays.reduce((s, d) => s + d.count, 0); + const accessibilitySummary = `GitHub contribution constellation: ${totalContributions} contributions, longest streak ${stats.longest} days`; let monthLabelsSvg = ""; if (!isMinimal) { - // GitHub's contribution calendar almost always starts on a partial - // week, which can flag a "month change" one column after the very - // first label — e.g. a week starting Dec 30 gets labeled "Dec", then - // the next week (Jan 5) immediately gets labeled "Jan" just 12px to - // its right. Two 3-letter labels can't fit in 12px, so they render on - // top of each other. Enforce a minimum pixel gap between labels and - // simply skip any month change that's too close to the previous one — - // it'll still get labeled correctly whenever the *next* month change - // occurs with enough room. const monthLabels = []; let lastMonth = null; let lastLabelX = -Infinity; - const minLabelGap = cellSize * 3; // ~3 weeks of clearance per label + const minLabelGap = cellSize * 3; weeks.forEach((week, wi) => { const firstDay = week.contributionDays[0]; @@ -449,7 +414,7 @@ function buildSvg(weeks, theme, layout) { if (month === lastMonth) return; const x = paddingLeft + wi * cellSize; - lastMonth = month; // always advance, even if we skip rendering this one + lastMonth = month; if (x - lastLabelX < minLabelGap) return; monthLabels.push({ label: MONTH_NAMES[month], x }); @@ -481,8 +446,6 @@ function buildSvg(weeks, theme, layout) { crispLinesSvg += ``; }); - // Stars: dim/static first (background layer), then bright/animated - // (foreground layer) so twinkle glows aren't occluded by static dots. let dimStarsSvg = ""; let brightStarsSvg = ""; @@ -544,7 +507,8 @@ function buildSvg(weeks, theme, layout) { ${captionLine2}`; } - return ` + return ` + ${accessibilitySummary} @@ -588,10 +552,6 @@ function buildSvg(weeks, theme, layout) { `; } -// --------------------------------------------------------------------------- -// Entry point -// --------------------------------------------------------------------------- - async function main() { console.log( `[github-constellation] Fetching contributions for "${GITHUB_USER}"...`, @@ -624,7 +584,6 @@ async function main() { console.log(`[github-constellation] Wrote ${darkPath}`); console.log(`[github-constellation] Wrote ${lightPath}`); - // Expose paths for the composite action's later steps (e.g. commit step) if (process.env.GITHUB_OUTPUT) { fs.appendFileSync( process.env.GITHUB_OUTPUT,