Commit 6eb345f
Changed files (5)
src/main.ts
@@ -6,12 +6,10 @@ import { Octokit, RequestError } from 'octokit'
import { retry } from '@octokit/plugin-retry'
import { throttling } from '@octokit/plugin-throttling'
import { collect, Data } from './collect/collect.js'
-import { allBadges } from './all-badges/index.js'
-import { Badge, badgeCollection, BadgePresenter, ID } from './badges.js'
+import { Badge } from './badges.js'
import { updateReadme } from './update-readme.js'
import { updateBadges } from './update-badges.js'
-import path from 'node:path'
-import { fileURLToPath } from 'node:url'
+import { presentBadges } from './present-badges.js'
void (async function main() {
const { env } = process
@@ -107,62 +105,7 @@ void (async function main() {
}
}
- for (const { default: it } of allBadges) {
- const presenter: BadgePresenter = it
- const newBadges: Badge[] = []
- const grant = badgeCollection(newBadges)
- presenter.present(data, grant)
-
- if (newBadges.length === 0) {
- continue
- }
-
- // Enhance badges with image URLs.
- for (const b of newBadges) {
- const baseDir = path.basename(path.dirname(fileURLToPath(presenter.url)))
- b.image = `https://github.com/my-badges/my-badges/blob/master/src/all-badges/${baseDir}/${b.id}.png?raw=true`
- }
-
- const badgeFromPresenter = (x: Badge) =>
- (presenter.badges as ID[]).includes(x.id)
-
- // Merge existing userBadges with newBadges.
- if (compact && presenter.tiers) {
- const newHighestTierBadge = newBadges.reduce((prev, curr) => {
- return prev.tier > curr.tier ? prev : curr
- })
-
- const existingBadgeIndex = userBadges.findIndex(badgeFromPresenter)
- if (existingBadgeIndex === -1) {
- userBadges.push(newHighestTierBadge)
- } else if (
- newHighestTierBadge.tier >= userBadges[existingBadgeIndex].tier
- ) {
- userBadges[existingBadgeIndex] = newHighestTierBadge
-
- // Drop all other badges from the same presenter.
- userBadges = userBadges.filter(
- (x, i) => i === existingBadgeIndex || !badgeFromPresenter(x),
- )
- }
- } else {
- for (const badge of newBadges) {
- const index = userBadges.findIndex((x) => x.id === badge.id)
- if (index === -1) {
- userBadges.push(badge)
- } else {
- userBadges[index] = badge
- }
- }
- }
- }
-
- if (pickBadges.length > 0) {
- userBadges = userBadges.filter((x) => pickBadges.includes(x.id))
- }
- if (omitBadges.length > 0) {
- userBadges = userBadges.filter((x) => !omitBadges.includes(x.id))
- }
+ userBadges = presentBadges(data, userBadges, pickBadges, omitBadges, compact)
console.log(JSON.stringify(userBadges, null, 2))
src/present-badges.ts
@@ -0,0 +1,67 @@
+import { Badge, badgeCollection, BadgePresenter, ID } from './badges.js'
+import { allBadges } from './all-badges/index.js'
+import path from 'node:path'
+import { fileURLToPath } from 'node:url'
+import { Data } from './collect/collect.js'
+
+export const mergeBadges = (...badges: (Badge | Badge[])[]): Badge[] =>
+ Object.values(
+ badges
+ .flat()
+ .reduce<Record<string, Badge>>(
+ (m, v) => Object.assign(m, { [v.id]: v }),
+ {},
+ ),
+ )
+
+export const presentBadges = (
+ data: Data,
+ userBadges: Badge[],
+ pickBadges: string[],
+ omitBadges: string[],
+ compact: boolean,
+): Badge[] => {
+ const newBadges: Badge[] = []
+ const presenters: BadgePresenter[] = allBadges.map((m) => m.default)
+ for (const presenter of presenters) {
+ const grant = badgeCollection(newBadges)
+ presenter.present(data, grant)
+
+ // Enhance badges with image URLs.
+ for (const b of newBadges) {
+ const baseDir = path.basename(path.dirname(fileURLToPath(presenter.url)))
+ b.image = `https://github.com/my-badges/my-badges/blob/master/src/all-badges/${baseDir}/${b.id}.png?raw=true`
+ }
+ }
+
+ userBadges = mergeBadges(userBadges, newBadges)
+
+ if (compact) {
+ for (const presenter of presenters) {
+ if (!presenter.tiers) {
+ continue
+ }
+ const touchedBadges = userBadges.filter(({ id }) =>
+ (presenter.badges as ID[]).includes(id),
+ )
+ const newHighestTierBadge = touchedBadges.reduce(
+ (prev, curr) => (prev.tier > curr.tier ? prev : curr),
+ {} as Badge,
+ )
+
+ omitBadges.push(
+ ...touchedBadges
+ .map(({ id }) => id)
+ .filter((id) => id !== newHighestTierBadge.id),
+ )
+ }
+ }
+ if (pickBadges.length > 0) {
+ userBadges = userBadges.filter((x) => pickBadges.includes(x.id))
+ }
+ if (omitBadges.length > 0) {
+ userBadges = userBadges.filter((x) => !omitBadges.includes(x.id))
+ }
+
+ return userBadges
+}
src/utils.ts
@@ -2,6 +2,7 @@ import fs from 'node:fs/promises'
import path from 'node:path'
import { Octokit } from 'octokit'
import { Commit, Pull } from './collect/collect.js'
+import { Badge } from './badges.js'
export function linkCommit(commit: Commit): string {
return `<a href="https://github.com/${commit.repository.owner.login}/${
test/present-badges.test.ts
@@ -0,0 +1,122 @@
+import * as assert from 'node:assert'
+import { describe, it } from 'node:test'
+import { Data } from '../src/collect/collect.js'
+import { presentBadges } from '../src/present-badges.js'
+
+describe('present-badges', () => {
+ const data: Data = {
+ user: {} as Data['user'],
+ pulls: [] as Data['pulls'],
+ issues: {} as Data['issues'],
+ repos: [
+ {
+ stargazers_count: 1000,
+ name: 'bar',
+ owner: {
+ login: 'foo',
+ },
+ commits: [],
+ },
+ {
+ stargazers_count: 2000,
+ name: 'qux',
+ owner: {
+ login: 'foo',
+ },
+ commits: [] as any[],
+ },
+ ] as Data['repos'],
+ }
+
+ it('presentBadges() applies `pick`', () => {
+ const userBadges = presentBadges(
+ data,
+ [],
+ ['stars-100', 'stars-500'],
+ [],
+ false,
+ )
+
+ assert.deepEqual(userBadges, [
+ {
+ id: 'stars-100',
+ tier: 1,
+ desc: 'I collected 100 stars.',
+ body:
+ 'Repos:\n' +
+ '\n' +
+ '* <a href="https://github.com/foo/bar">foo/bar: ★1000</a>\n' +
+ '\n' +
+ "<sup>I have push, maintainer or admin permissions, so I'm definitely an author.<sup>\n",
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/pr-collaboration/stars-100.png?raw=true',
+ },
+ {
+ id: 'stars-500',
+ tier: 2,
+ desc: 'I collected 500 stars.',
+ body:
+ 'Repos:\n' +
+ '\n' +
+ '* <a href="https://github.com/foo/bar">foo/bar: ★1000</a>\n' +
+ '\n' +
+ "<sup>I have push, maintainer or admin permissions, so I'm definitely an author.<sup>\n",
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/pr-collaboration/stars-500.png?raw=true',
+ },
+ ])
+ })
+
+ it('presentBadges() applies `omit`', () => {
+ const userBadges = presentBadges(
+ data,
+ [],
+ ['stars-100', 'stars-500'],
+ ['stars-500'],
+ false,
+ )
+
+ assert.deepEqual(userBadges, [
+ {
+ id: 'stars-100',
+ tier: 1,
+ desc: 'I collected 100 stars.',
+ body:
+ 'Repos:\n' +
+ '\n' +
+ '* <a href="https://github.com/foo/bar">foo/bar: ★1000</a>\n' +
+ '\n' +
+ "<sup>I have push, maintainer or admin permissions, so I'm definitely an author.<sup>\n",
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/pr-collaboration/stars-100.png?raw=true',
+ },
+ ])
+ })
+
+ it('presentBadges() applies `compact`', () => {
+ const userBadges = presentBadges(
+ data,
+ [],
+ ['stars-1000', 'stars-2000', 'stars-5000'],
+ [],
+ true,
+ )
+
+ assert.deepEqual(userBadges, [
+ {
+ id: 'stars-2000',
+ tier: 4,
+ desc: 'I collected 2000 stars.',
+ body:
+ 'Repos:\n' +
+ '\n' +
+ '* <a href="https://github.com/foo/qux">foo/qux: ★2000</a>\n' +
+ '* <a href="https://github.com/foo/bar">foo/bar: ★1000</a>\n' +
+ '\n' +
+ "<sup>I have push, maintainer or admin permissions, so I'm definitely an author.<sup>\n",
+ image:
+ 'https://github.com/my-badges/my-badges/blob/master/src/all-badges/pr-collaboration/stars-2000.png?raw=true',
+ },
+ ])
+ })
+})
test/stars.test.ts
@@ -10,7 +10,7 @@ describe('stars', () => {
const grant = badgeCollection(badges)
const data: Data = {
user: {} as Data['user'],
- pulls: {} as Data['pulls'],
+ pulls: [] as Data['pulls'],
issues: {} as Data['issues'],
repos: [
{
@@ -19,6 +19,7 @@ describe('stars', () => {
owner: {
login: 'foo',
},
+ commits: [],
},
{
stargazers_count: 2000,
@@ -26,6 +27,7 @@ describe('stars', () => {
owner: {
login: 'foo',
},
+ commits: [] as any[],
},
] as Data['repos'],
}