Commit f39f585
Changed files (4)
src/present-badges.ts
@@ -3,19 +3,7 @@ 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 }),
- {},
- ),
- )
-
-const parseRegexp = (value: string): RegExp =>
- new RegExp(`^${value}$`.replace('*', '.+'))
+import { parseMask } from './utils.js'
export const presentBadges = (
presenters: BadgePresenter[],
@@ -30,43 +18,59 @@ export const presentBadges = (
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`
}
- userBadges = mergeBadges(userBadges, newBadges)
- }
+ const badgeFromPresenter = (x: Badge) =>
+ (presenter.badges as ID[]).includes(x.id)
- 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,
- )
+ // Merge existing userBadges with newBadges.
+ if (compact && presenter.tiers) {
+ const newHighestTierBadge = newBadges.reduce((prev, curr) => {
+ return prev.tier > curr.tier ? prev : curr
+ })
- omitBadges.push(
- ...touchedBadges
- .map(({ id }) => id)
- .filter((id) => id !== newHighestTierBadge.id),
- )
+ 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.map(parseRegexp).some((r) => r.test(x.id)),
+ pickBadges.map(parseMask).some((r) => r.test(x.id)),
)
}
+
if (omitBadges.length > 0) {
userBadges = userBadges.filter((x) =>
- omitBadges.map(parseRegexp).every((r) => !r.test(x.id)),
+ omitBadges.map(parseMask).every((r) => !r.test(x.id)),
)
}
src/utils.ts
@@ -31,30 +31,6 @@ export function quoteAttr(s: string) {
export const expectType = <T>(expression: T) => void 0
-export const decodeBase64 = (data: string) =>
- Buffer.from(data, 'base64').toString('utf8')
-export const encodeBase64 = (data: string) =>
- Buffer.from(data, 'utf8').toString('base64')
-
-export const upload = async (
- octokit: Octokit,
- route: Parameters<Octokit['request']>[0],
- data: Parameters<Octokit['request']>[1],
- dryrun?: boolean,
-) => {
- if (dryrun) {
- console.log(`Skipped pushing ${data?.path} (dryrun)`)
- const filepath = path.join(process.cwd(), data?.path as string)
-
- await fs.mkdir(path.dirname(filepath), { recursive: true })
- await fs.writeFile(filepath, data?.content as string)
-
- return
- }
-
- console.log(`Uploading ${data?.path}`)
- return octokit.request(route, {
- ...data,
- content: encodeBase64(data?.content as string),
- })
+export function parseMask(value: string): RegExp {
+ return new RegExp(`^${value}$`.replace('*', '.+'))
}
test/get-data.test.ts
@@ -5,7 +5,6 @@ import path from 'node:path'
import os from 'node:os'
import { Octokit } from 'octokit'
import { getData } from '../src/get-data.js'
-import { encodeBase64 } from '../src/utils.js'
const tempy = () => fs.mkdtempSync(path.join(os.tmpdir(), 'tempy-'))
test/present-badges.test.ts
@@ -2,6 +2,7 @@ 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'
+import { Badge, BadgePresenter } from '../src/badges.js'
describe('present-badges', () => {
const data: Data = {
@@ -11,7 +12,7 @@ describe('present-badges', () => {
},
} as Data['user'],
pulls: [] as Data['pulls'],
- issues: {} as Data['issues'],
+ issues: [] as Data['issues'],
repos: [
{
stargazers_count: 1000,
@@ -166,4 +167,46 @@ describe('present-badges', () => {
},
])
})
+
+ it('presentBadges() keeps existing order of badges', async () => {
+ const dumpPresenter: BadgePresenter = {
+ url: new URL('file:///tmp/dump.js'),
+ badges: ['a-commit', 'ab-commit', 'abc-commit'],
+ present: (_, grant) => {
+ grant('a-commit', 'a')
+ grant('ab-commit', 'ab')
+ grant('abc-commit', 'abc')
+ },
+ }
+
+ const oldUserBadges: Badge[] = [
+ {
+ id: 'a-commit',
+ tier: 0,
+ desc: 'a',
+ body: '',
+ image: '',
+ },
+ {
+ id: 'abc-commit',
+ tier: 0,
+ desc: 'abc',
+ body: '',
+ image: '',
+ },
+ ]
+
+ const userBadges = presentBadges(
+ [dumpPresenter],
+ data,
+ oldUserBadges,
+ [],
+ [],
+ false,
+ )
+ assert.deepEqual(
+ userBadges.map((x) => x.id),
+ ['a-commit', 'abc-commit', 'ab-commit'],
+ )
+ })
})