Skip to content

Commit 67e0963

Browse files
committed
feat(contributions): add an open source section with upstream pull requests
1 parent f8d6e51 commit 67e0963

6 files changed

Lines changed: 180 additions & 0 deletions

File tree

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
import type { Contribution } from "../lib/contributions";
3+
import { formatStars, pullRequestUrl, sortContributions } from "../lib/contributions";
4+
5+
interface Props {
6+
contributions: Contribution[];
7+
}
8+
9+
const items = sortContributions(Astro.props.contributions);
10+
---
11+
<h2 class="cat">{"// open source"} <span class="count"{items.length}</span></h2>
12+
<div class="grid">
13+
{items.map((item) => (
14+
<a class="card" href={pullRequestUrl(item)} data-state={item.state} rel="noopener">
15+
<div class="head">
16+
<span class="icon">{item.emoji}</span>
17+
<span class="title">{item.repo}</span>
18+
</div>
19+
<p class="desc" data-en={item.desc.en} data-es={item.desc.es}>{item.desc.en}</p>
20+
<div class="meta">
21+
<span class="chip">{formatStars(item.stars)}★</span>
22+
<span class="status">#{item.pr} · {item.state}</span>
23+
</div>
24+
</a>
25+
))}
26+
</div>

src/data/contributions.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type { Contribution } from "../lib/contributions";
2+
3+
export const contributions: Contribution[] = [
4+
{
5+
repo: "vitessio/vitess",
6+
emoji: "🐬",
7+
stars: 21000,
8+
pr: 20700,
9+
desc: {
10+
en: "A sharded query with EXISTS inside a CASE silently dropped half of its WHERE clause and returned the wrong rows.",
11+
es: "Una consulta con EXISTS dentro de un CASE perdía silenciosamente la mitad de su WHERE y devolvía filas incorrectas.",
12+
},
13+
state: "open",
14+
},
15+
{
16+
repo: "vitessio/vitess",
17+
emoji: "🐬",
18+
stars: 21000,
19+
pr: 20701,
20+
desc: {
21+
en: "An outer join against a reference table returned every preserved row once per shard instead of once.",
22+
es: "Un outer join contra una tabla de referencia devolvía cada fila preservada una vez por shard en lugar de una sola vez.",
23+
},
24+
state: "open",
25+
},
26+
{
27+
repo: "tobymao/sqlglot",
28+
emoji: "🧩",
29+
stars: 8000,
30+
pr: 7969,
31+
desc: {
32+
en: "DuckDB was modelled as returning NULL on division by zero, but it follows IEEE 754 and returns inf, so transpiled queries diverged.",
33+
es: "DuckDB estaba modelado como si devolviera NULL al dividir por cero, pero sigue IEEE 754 y devuelve inf, así que las consultas transpiladas divergían.",
34+
},
35+
state: "open",
36+
},
37+
{
38+
repo: "fonttools/fonttools",
39+
emoji: "🔠",
40+
stars: 4600,
41+
pr: 4137,
42+
desc: {
43+
en: "Instancing a variable font left the BASE table untouched, so instances kept the default baselines and a dangling variation store.",
44+
es: "Al instanciar una fuente variable la tabla BASE quedaba intacta, así que las instancias conservaban las líneas base por defecto y un almacén de variaciones huérfano.",
45+
},
46+
state: "open",
47+
},
48+
{
49+
repo: "MatthewKuKanich/FindMyFlipper",
50+
emoji: "📍",
51+
stars: 2170,
52+
pr: 144,
53+
desc: {
54+
en: "An infinite 2FA loop blocked report fetching: the anisette device identity was partly overwritten with random UUIDs. Behind seven reported issues.",
55+
es: "Un bucle infinito de 2FA impedía descargar los informes: la identidad de dispositivo de anisette se sobrescribía en parte con UUID aleatorios. Detrás de siete issues reportados.",
56+
},
57+
state: "open",
58+
},
59+
];

src/lib/contributions.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export type ContributionState = "open" | "merged" | "closed";
2+
3+
export interface Contribution {
4+
repo: string;
5+
emoji: string;
6+
stars: number;
7+
pr: number;
8+
desc: { en: string; es: string };
9+
state: ContributionState;
10+
}
11+
12+
export function pullRequestUrl(contribution: Contribution): string {
13+
return `https://github.com/${contribution.repo}/pull/${contribution.pr}`;
14+
}
15+
16+
export function formatStars(stars: number): string {
17+
return stars >= 1000 ? `${Math.round(stars / 100) / 10}k` : String(stars);
18+
}
19+
20+
/** Biggest repositories first, then by pull request number, so the order is stable. */
21+
export function sortContributions(contributions: Contribution[]): Contribution[] {
22+
return [...contributions].sort((a, b) => b.stars - a.stars || a.pr - b.pr);
23+
}

src/pages/index.astro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
---
2+
import ContributionList from "../components/ContributionList.astro";
23
import Footer from "../components/Footer.astro";
34
import Hero from "../components/Hero.astro";
45
import ProjectGrid from "../components/ProjectGrid.astro";
56
import TopBar from "../components/TopBar.astro";
7+
import { contributions } from "../data/contributions";
68
import { categoryOrder, projects } from "../data/projects";
79
import Base from "../layouts/Base.astro";
810
import { groupByCategory } from "../lib/projects";
@@ -13,5 +15,6 @@ const groups = groupByCategory(projects, categoryOrder);
1315
<TopBar />
1416
<Hero />
1517
<ProjectGrid groups={groups} />
18+
<ContributionList contributions={contributions} />
1619
<Footer />
1720
</Base>

src/styles/global.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ html[data-theme="light"] {
1313
--repo-accent: #8a8a8a;
1414
--chip-bg: #e7e4da;
1515
--rule: #cfcabb;
16+
--state-merged: #6f42c1;
17+
--state-closed: #cf222e;
1618
}
1719

1820
/* Dark theme */
@@ -26,6 +28,8 @@ html[data-theme="dark"] {
2628
--repo-accent: #5a6b5f;
2729
--chip-bg: #1d2620;
2830
--rule: #2a342d;
31+
--state-merged: #a371f7;
32+
--state-closed: #f85149;
2933
}
3034

3135
* {
@@ -198,6 +202,18 @@ body {
198202
.card[data-type="repo"] .status {
199203
color: var(--repo-accent);
200204
}
205+
.card[data-state="merged"] {
206+
border-left-color: var(--state-merged);
207+
}
208+
.card[data-state="merged"] .status {
209+
color: var(--state-merged);
210+
}
211+
.card[data-state="closed"] {
212+
border-left-color: var(--state-closed);
213+
}
214+
.card[data-state="closed"] .status {
215+
color: var(--state-closed);
216+
}
201217

202218
/* Footer */
203219
.foot {

tests/contributions.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { describe, expect, it } from "vitest";
2+
import {
3+
type Contribution,
4+
formatStars,
5+
pullRequestUrl,
6+
sortContributions,
7+
} from "../src/lib/contributions";
8+
9+
const c = (repo: string, stars: number, pr: number): Contribution => ({
10+
repo,
11+
emoji: "🔧",
12+
stars,
13+
pr,
14+
desc: { en: repo, es: repo },
15+
state: "open",
16+
});
17+
18+
describe("pullRequestUrl", () => {
19+
it("builds the pull request url from the repo and number", () => {
20+
expect(pullRequestUrl(c("vitessio/vitess", 21000, 20700))).toBe(
21+
"https://github.com/vitessio/vitess/pull/20700",
22+
);
23+
});
24+
});
25+
26+
describe("formatStars", () => {
27+
it("abbreviates thousands with one decimal", () => {
28+
expect(formatStars(21000)).toBe("21k");
29+
expect(formatStars(2170)).toBe("2.2k");
30+
expect(formatStars(1000)).toBe("1k");
31+
});
32+
33+
it("leaves counts below a thousand untouched", () => {
34+
expect(formatStars(610)).toBe("610");
35+
});
36+
});
37+
38+
describe("sortContributions", () => {
39+
it("puts bigger repos first and breaks ties by pull request number", () => {
40+
const sorted = sortContributions([
41+
c("small/repo", 2170, 144),
42+
c("big/repo", 21000, 20701),
43+
c("big/repo", 21000, 20700),
44+
]);
45+
expect(sorted.map((x) => x.pr)).toEqual([20700, 20701, 144]);
46+
});
47+
48+
it("does not mutate the input", () => {
49+
const input = [c("small/repo", 100, 2), c("big/repo", 900, 1)];
50+
sortContributions(input);
51+
expect(input.map((x) => x.repo)).toEqual(["small/repo", "big/repo"]);
52+
});
53+
});

0 commit comments

Comments
 (0)