Commit a029e66
Changed files (18)
src
all-badges
abc-commit
bad-words
chore-commit
covid-19
dead-commit
delorean
fix-commit
github-anniversary
mass-delete-commit
my-badges-contributor
revert-revert-commit
star-gazer
stars
time-of-commit
yeti
src/all-badges/abc-commit/abc-commit.ts
@@ -1,17 +1,17 @@
import { Commit, Repo } from '../../collect/collect.js'
import { BadgePresenter, ID, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
+ tiers = true
badges = [
- 'abcdef-commit',
- 'abcde-commit',
- 'abcd-commit',
- 'abc-commit',
- 'ab-commit',
'a-commit',
+ 'ab-commit',
+ 'abc-commit',
+ 'abcd-commit',
+ 'abcde-commit',
+ 'abcdef-commit',
] as const
- tiers = true as const
present: Present = (data, grant) => {
const types: [string, ID][] = [
['abcdef', 'abcdef-commit'],
@@ -29,10 +29,9 @@ export default new (class implements BadgePresenter {
const re = new RegExp(`^(${prefix})`)
if (re.test(commit.sha)) {
order[prefix.length] = () =>
- grant(
- badge,
- `One of my commit sha starts with "${prefix}".`,
- ).evidence(link(re, repo, commit))
+ grant(badge, `One of my commit sha starts with "${prefix}".`)
+ .evidence(link(re, repo, commit))
+ .tier(prefix.length)
break
}
}
src/all-badges/bad-words/bad-words.ts
@@ -2,7 +2,7 @@ import { Commit, Repo } from '../../collect/collect.js'
import { Present, BadgePresenter } from '../../badges.js'
import { linkCommit } from '../../utils.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['bad-words'] as const
present: Present = (data, grant) => {
src/all-badges/chore-commit/chore-commit.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['chore-commit'] as const
tiers = false
src/all-badges/covid-19/covid-19.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['covid-19'] as const
present: Present = (data, grant) => {
src/all-badges/dead-commit/dead-commit.ts
@@ -1,7 +1,7 @@
import { Commit, Repo } from '../../collect/collect.js'
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['dead-commit'] as const
present: Present = (data, grant) => {
src/all-badges/delorean/delorean.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['delorean'] as const
present: Present = (data, grant) => {
src/all-badges/fix-commit/fix-commit.ts
@@ -1,8 +1,9 @@
import { BadgePresenter, Grant, Present } from '../../badges.js'
import { Commit } from '../../collect/collect.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
+ tiers = true
badges = [
'fix-2',
'fix-3',
@@ -11,7 +12,6 @@ export default new (class implements BadgePresenter {
'fix-6',
'fix-6+', // For more than 6
] as const
- tiers = true
present: Present = (data, grant) => {
for (const repo of data.repos) {
const sequences: Commit[][] = []
@@ -48,17 +48,29 @@ export default new (class implements BadgePresenter {
const description = `I did ${count} sequential fixes.`
if (count === 2)
- grant('fix-2', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-2', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(1)
else if (count === 3)
- grant('fix-3', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-3', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(2)
else if (count === 4)
- grant('fix-4', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-4', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(3)
else if (count === 5)
- grant('fix-5', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-5', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(4)
else if (count === 6)
- grant('fix-6', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-6', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(5)
else if (count > 6)
- grant('fix-6+', description).evidenceCommitsWithMessage(...sec)
+ grant('fix-6+', description)
+ .evidenceCommitsWithMessage(...sec)
+ .tier(6)
}
}
}
src/all-badges/github-anniversary/github-anniversary.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = [
'github-anniversary-5',
src/all-badges/mass-delete-commit/mass-delete-commit.ts
@@ -1,12 +1,9 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
- badges = [
- 'mass-delete-commit-10k',
- 'mass-delete-commit'
- ] as const
tiers = true
+ badges = ['mass-delete-commit-10k', 'mass-delete-commit'] as const
present: Present = (data, grant) => {
for (const repo of data.repos) {
for (const commit of repo.commits) {
@@ -14,20 +11,18 @@ export default new (class implements BadgePresenter {
(commit.deletions ?? 0) > 1000 &&
(commit.deletions ?? 0) / (commit.additions ?? 0) > 100
) {
- grant(
- 'mass-delete-commit',
- 'When I delete code, I delete a lot.',
- ).evidenceCommits(commit)
+ grant('mass-delete-commit', 'When I delete code, I delete a lot.')
+ .evidenceCommits(commit)
+ .tier(1)
}
if (
(commit.deletions ?? 0) > 10_000 &&
(commit.deletions ?? 0) / (commit.additions ?? 0) > 100
) {
- grant(
- 'mass-delete-commit-10k',
- 'When I delete code, I delete a lot.',
- ).evidenceCommits(commit)
+ grant('mass-delete-commit-10k', 'When I delete code, I delete a lot.')
+ .evidenceCommits(commit)
+ .tier(2)
}
}
}
src/all-badges/my-badges-contributor/my-badges-contributor.ts
@@ -1,7 +1,7 @@
import { Pull } from '../../collect/collect.js'
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['my-badges-contributor'] as const
present: Present = (data, grant) => {
src/all-badges/revert-revert-commit/revert-revert-commit.ts
@@ -1,7 +1,7 @@
import { Commit } from '../../collect/collect.js'
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['revert-revert-commit'] as const
present: Present = (data, grant) => {
src/all-badges/star-gazer/star-gazer.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['star-gazer'] as const
present: Present = (data, grant) => {
src/all-badges/stars/stars.ts
@@ -1,17 +1,17 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
+ tiers = true
badges = [
- 'stars-20000',
- 'stars-10000',
- 'stars-5000',
- 'stars-2000',
- 'stars-1000',
- 'stars-500',
'stars-100',
+ 'stars-500',
+ 'stars-1000',
+ 'stars-2000',
+ 'stars-5000',
+ 'stars-10000',
+ 'stars-20000',
] as const
- tiers = true
present: Present = (data, grant) => {
let totalStars = 0
@@ -34,12 +34,26 @@ ${reasonable.join('\n')}
<sup>I have push, maintainer or admin permissions, so I'm definitely an author.<sup>
`
-
- this.badges.forEach((badge) => {
- const limit = +badge.slice(6)
- if (totalStars >= limit) {
- grant(badge, `I collected ${limit} stars.`).evidence(text)
- }
- })
+ if (totalStars >= 100) {
+ grant('stars-100', `I collected 100 stars.`).evidence(text).tier(1)
+ }
+ if (totalStars >= 500) {
+ grant('stars-500', 'I collected 500 stars.').evidence(text).tier(2)
+ }
+ if (totalStars >= 1000) {
+ grant('stars-1000', 'I collected 1000 stars.').evidence(text).tier(3)
+ }
+ if (totalStars >= 2000) {
+ grant('stars-2000', 'I collected 2000 stars.').evidence(text).tier(4)
+ }
+ if (totalStars >= 5000) {
+ grant('stars-5000', 'I collected 5000 stars.').evidence(text).tier(5)
+ }
+ if (totalStars >= 10000) {
+ grant('stars-10000', 'I collected 10000 stars.').evidence(text).tier(6)
+ }
+ if (totalStars >= 20000) {
+ grant('stars-20000', 'I collected 20000 stars.').evidence(text).tier(7)
+ }
}
})()
src/all-badges/time-of-commit/time-of-commit.ts
@@ -1,7 +1,7 @@
import { BadgePresenter, Present } from '../../badges.js'
import { Commit, User } from '../../collect/collect.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['midnight-commits', 'morning-commits', 'evening-commits'] as const
present: Present = (data, grant) => {
src/all-badges/yeti/yeti.ts
@@ -1,6 +1,6 @@
import { BadgePresenter, Present } from '../../badges.js'
-export default new (class implements BadgePresenter {
+export default new (class extends BadgePresenter {
url = new URL(import.meta.url)
badges = ['yeti'] as const
present: Present = (data, grant) => {
src/badges.ts
@@ -12,11 +12,11 @@ for (const {
export type ID = (typeof allBadges)[number]['default']['badges'][number]
-export interface BadgePresenter {
- url: URL
- badges: unknown
- tiers?: boolean
- present: Present
+export abstract class BadgePresenter {
+ abstract url: URL
+ tiers = false
+ abstract badges: unknown
+ abstract present: Present
}
export type Grant = ReturnType<typeof badgeCollection>
@@ -25,73 +25,102 @@ export type Present = (data: Data, grant: Grant) => void
export type Badge = {
id: ID
+ tier: number
desc: string
body: string
image: string
}
-const voidGrant = {
- evidence() {},
- evidenceCommits() {},
- evidenceCommitsWithMessage() {},
- evidencePRs() {},
-}
-
export function badgeCollection(
- badges: Badge[],
- baseUrl: URL,
+ userBadges: Badge[],
+ presenter: (typeof allBadges)[number]['default'],
pickBadges: string[],
omitBadges: string[],
+ compact: boolean,
) {
- const indexes = new Map(badges.map((x, i) => [x.id, i]))
- const baseDir = path.basename(path.dirname(fileURLToPath(baseUrl)))
+ const indexes = new Map(userBadges.map((x, i) => [x.id, i]))
+ const baseDir = path.basename(path.dirname(fileURLToPath(presenter.url)))
return function grant(id: ID, desc: string) {
- if (!pickBadges.includes(id) || omitBadges.includes(id)) {
- if (indexes.has(id)) {
- badges.splice(indexes.get(id)!, 1)
- }
- return voidGrant
- }
+ // if (!pickBadges.includes(id) || omitBadges.includes(id)) {
+ // if (indexes.has(id)) {
+ // badges.splice(indexes.get(id)!, 1)
+ // }
+ // return voidGrant
+ // }
const badge: Badge = {
id,
+ tier: 0,
desc,
body: '',
image: `https://github.com/my-badges/my-badges/blob/master/src/all-badges/${baseDir}/${id}.png?raw=true`,
}
- if (!indexes.has(id)) {
- badges.push(badge)
- indexes.set(id, badges.length - 1)
+ if (compact) {
+ let found = false
+ for (const badgeId of presenter.badges) {
+ if (indexes.has(badgeId)) {
+ const index = indexes.get(badgeId)!
+ const alreadyExistingBadge = userBadges[index]
+ if (alreadyExistingBadge.tier < badge.tier) {
+ userBadges[index] = badge
+ }
+ }
+ }
+ if (!found) {
+ userBadges.push(badge)
+ indexes.set(id, userBadges.length - 1)
+ }
} else {
- badges[indexes.get(id)!] = badge
+ if (indexes.has(id)) {
+ userBadges[indexes.get(id)!] = badge
+ } else {
+ userBadges.push(badge)
+ indexes.set(id, userBadges.length - 1)
+ }
}
- return {
- evidence(text: string) {
- badge.body = text
- },
- evidenceCommits(...commits: Commit[]) {
- this.evidence(
- 'Commits:\n\n' + commits.map((x) => `- ${linkCommit(x)}`).join('\n'),
- )
- },
- evidenceCommitsWithMessage(...commits: Commit[]) {
- this.evidence(
- 'Commits:\n\n' +
- commits.map((x) => `- ${linkCommit(x)}: ${x.message}`).join('\n'),
- )
- },
- evidencePRs(...pulls: Pull[]) {
- this.evidence(
- 'Pull requests:\n\n' +
- pulls
- .map(linkPull)
- .map((x) => '- ' + x)
- .join('\n'),
- )
- },
- }
+ return new Evidence(badge)
+ }
+}
+
+class Evidence {
+ constructor(private badge: Badge) {}
+
+ tier(tier: number) {
+ this.badge.tier = tier
+ return this
+ }
+
+ evidence(text: string) {
+ this.badge.body = text
+ return this
+ }
+
+ evidenceCommits(...commits: Commit[]) {
+ this.evidence(
+ 'Commits:\n\n' + commits.map((x) => `- ${linkCommit(x)}`).join('\n'),
+ )
+ return this
+ }
+
+ evidenceCommitsWithMessage(...commits: Commit[]) {
+ this.evidence(
+ 'Commits:\n\n' +
+ commits.map((x) => `- ${linkCommit(x)}: ${x.message}`).join('\n'),
+ )
+ return this
+ }
+
+ evidencePRs(...pulls: Pull[]) {
+ this.evidence(
+ 'Pull requests:\n\n' +
+ pulls
+ .map(linkPull)
+ .map((x) => '- ' + x)
+ .join('\n'),
+ )
+ return this
}
}
src/main.ts
@@ -15,7 +15,7 @@ void (async function main() {
const { env } = process
const argv = minimist(process.argv.slice(2), {
string: ['data', 'repo', 'token', 'size', 'user', 'pick', 'omit'],
- boolean: ['dryrun', 'tiers'],
+ boolean: ['dryrun', 'compact'],
})
const {
token = env.GITHUB_TOKEN,
@@ -26,7 +26,7 @@ void (async function main() {
dryrun,
pick,
omit,
- tiers,
+ compact,
} = argv
const [owner, repo] = repository?.split('/', 2) || [username, username]
const pickBadges = pick ? pick.split(',') : names
@@ -74,7 +74,7 @@ void (async function main() {
fs.writeFileSync(`data/${username}.json`, JSON.stringify(data, null, 2))
}
- let badges: Badge[] = []
+ let userBadges: Badge[] = []
let oldJson: string | undefined
let jsonSha: string | undefined
if (owner && repo) {
@@ -92,7 +92,7 @@ void (async function main() {
'utf8',
)
jsonSha = myBadgesResp.data.sha
- badges = JSON.parse(oldJson)
+ userBadges = JSON.parse(oldJson)
} catch (err) {
if (err instanceof RequestError && err.response?.status != 404) {
throw err
@@ -101,13 +101,27 @@ void (async function main() {
}
for (const { default: presenter } of allBadges) {
- const grant = badgeCollection(badges, presenter.url, pickBadges, omitBadges)
+ const grant = badgeCollection(
+ userBadges,
+ presenter,
+ pickBadges,
+ omitBadges,
+ compact,
+ )
presenter.present(data, grant)
}
- console.log('Badges', badges)
+ console.log('Badges', userBadges)
if (owner && repo) {
- await updateBadges(octokit, owner, repo, badges, oldJson, jsonSha, dryrun)
- await updateReadme(octokit, owner, repo, badges, size, dryrun, tiers)
+ await updateBadges(
+ octokit,
+ owner,
+ repo,
+ userBadges,
+ oldJson,
+ jsonSha,
+ dryrun,
+ )
+ await updateReadme(octokit, owner, repo, userBadges, size, dryrun)
}
})()
src/update-readme.ts
@@ -7,7 +7,6 @@ export function generateReadme(
readme: string,
badges: Badge[],
size: number | string = 64,
- tiers: boolean,
) {
const startString = '<!-- my-badges start -->'
const endString = '<!-- my-badges end -->'
@@ -17,20 +16,11 @@ export function generateReadme(
const start = content.indexOf(startString)
const end = content.indexOf(endString)
const needToAddNewLine = content[end + endString.length + 1] !== '\n'
- const highestBadges = allBadges.flatMap(({ default: { badges: _badges , tiers: _tiers} }) =>
- _tiers
- ? _badges.find((badge) => badges.some(({ id }) => id === badge))
- : _badges,
- )
- const filter = tiers
- ? ({ id }: Badge) => highestBadges.includes(id)
- : () => true
if (start !== -1 && end !== -1) {
content = content.slice(0, start) + content.slice(end + endString.length)
const badgesHtml = badges
- .filter(filter)
.map((badge) => {
const desc = quoteAttr(badge.desc)
// prettier-ignore
@@ -58,7 +48,6 @@ export async function updateReadme(
badges: Badge[],
size: number | string,
dryrun: boolean,
- tiers: boolean,
) {
const readme = await octokit.request<'readme'>(
'GET /repos/{owner}/{repo}/readme',
@@ -67,11 +56,11 @@ export async function updateReadme(
repo,
},
)
- const content = await generateReadme(
+
+ const content = generateReadme(
Buffer.from(readme.data.content, 'base64').toString('utf8'),
badges,
size,
- tiers,
)
await upload(