diff --git a/src/components/ContributionList.astro b/src/components/ContributionList.astro index e479789..fd98eec 100644 --- a/src/components/ContributionList.astro +++ b/src/components/ContributionList.astro @@ -1,6 +1,6 @@ --- import type { Contribution } from "../lib/contributions"; -import { formatStars, pullRequestUrl, sortContributions } from "../lib/contributions"; +import { formatStars, pullRequestUrl, sortContributions, statusLabel } from "../lib/contributions"; interface Props { contributions: Contribution[]; @@ -10,7 +10,9 @@ const items = sortContributions(Astro.props.contributions); ---

{"// open source"} · {items.length}

- {items.map((item) => ( + {items.map((item) => { + const status = statusLabel(item); + return (
{item.emoji} @@ -19,8 +21,9 @@ const items = sortContributions(Astro.props.contributions);

{item.desc.en}

{formatStars(item.stars)}★ - #{item.pr} · {item.state} + {status.en}
- ))} + ); + })}
diff --git a/src/data/contributions.ts b/src/data/contributions.ts index 3d2de4d..ef131af 100644 --- a/src/data/contributions.ts +++ b/src/data/contributions.ts @@ -98,7 +98,8 @@ export const contributions: Contribution[] = [ en: "Every pull request had a red lint job: the pinned linter was built with an older Go than CI installs, so it panicked before reporting anything.", es: "Cada pull request tenía el job de lint en rojo: el linter fijado estaba compilado con un Go anterior al que instala el CI, así que hacía panic antes de reportar nada.", }, - state: "open", + state: "superseded", + supersededBy: 1745, }, { repo: "tobymao/sqlglot", diff --git a/src/lib/contributions.ts b/src/lib/contributions.ts index 4a33af5..3dac8b3 100644 --- a/src/lib/contributions.ts +++ b/src/lib/contributions.ts @@ -1,14 +1,20 @@ -export type ContributionState = "open" | "merged" | "closed"; +export type ContributionState = "open" | "merged" | "closed" | "superseded"; -export interface Contribution { +interface ContributionBase { repo: string; emoji: string; stars: number; pr: number; desc: { en: string; es: string }; - state: ContributionState; } +/** A superseded pull request was closed because another one landed the same fix. */ +export type Contribution = ContributionBase & + ( + | { state: Exclude } + | { state: "superseded"; supersededBy: number } + ); + export function pullRequestUrl(contribution: Contribution): string { return `https://github.com/${contribution.repo}/pull/${contribution.pr}`; } @@ -21,3 +27,14 @@ export function formatStars(stars: number): string { export function sortContributions(contributions: Contribution[]): Contribution[] { return [...contributions].sort((a, b) => b.stars - a.stars || a.pr - b.pr); } + +export function statusLabel(contribution: Contribution): { en: string; es: string } { + if (contribution.state === "superseded") { + return { + en: `#${contribution.pr} · fixed in #${contribution.supersededBy}`, + es: `#${contribution.pr} · resuelto en #${contribution.supersededBy}`, + }; + } + const label = `#${contribution.pr} · ${contribution.state}`; + return { en: label, es: label }; +} diff --git a/src/styles/global.css b/src/styles/global.css index de16f86..f635f6c 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -214,6 +214,12 @@ body { .card[data-state="closed"] .status { color: var(--state-closed); } +.card[data-state="superseded"] { + border-left-color: var(--repo-accent); +} +.card[data-state="superseded"] .status { + color: var(--repo-accent); +} /* Footer */ .foot { diff --git a/tests/contributions.test.ts b/tests/contributions.test.ts index 11286d5..2ec0b15 100644 --- a/tests/contributions.test.ts +++ b/tests/contributions.test.ts @@ -4,6 +4,7 @@ import { formatStars, pullRequestUrl, sortContributions, + statusLabel, } from "../src/lib/contributions"; const c = (repo: string, stars: number, pr: number): Contribution => ({ @@ -51,3 +52,18 @@ describe("sortContributions", () => { expect(input.map((x) => x.repo)).toEqual(["small/repo", "big/repo"]); }); }); + +describe("statusLabel", () => { + it("shows the pull request number and its state", () => { + expect(statusLabel({ ...c("big/repo", 900, 12), state: "merged" })).toEqual({ + en: "#12 · merged", + es: "#12 · merged", + }); + }); + + it("names the pull request that landed the fix when it was superseded", () => { + expect( + statusLabel({ ...c("traefik/yaegi", 8402, 1731), state: "superseded", supersededBy: 1745 }), + ).toEqual({ en: "#1731 · fixed in #1745", es: "#1731 · resuelto en #1745" }); + }); +});