Skip to content

Commit 7f6a8f1

Browse files
committed
docs: update sponsor stats during build
1 parent 89962dd commit 7f6a8f1

4 files changed

Lines changed: 152 additions & 4 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"repository": "massCodeIO/massCode",
3+
"stars": 6713,
4+
"releaseDownloads": 202805,
5+
"activeDevelopmentStartYear": 2019,
6+
"activeDevelopmentYears": 7,
7+
"updatedAt": "2026-05-06T13:14:33.070Z"
8+
}

docs/website/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"description": "massCode documentation website",
66
"scripts": {
77
"dev": "vitepress dev",
8-
"build": "vitepress build",
8+
"build": "node scripts/update-github-stats.mjs && vitepress build",
9+
"stats:update": "node scripts/update-github-stats.mjs",
910
"preview": "vitepress preview"
1011
},
1112
"dependencies": {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import { mkdir, readFile, writeFile } from 'node:fs/promises'
2+
import { dirname, join } from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
5+
const __dirname = dirname(fileURLToPath(import.meta.url))
6+
const outputPath = join(__dirname, '../.vitepress/_data/github-stats.json')
7+
const repository = 'massCodeIO/massCode'
8+
const startYear = 2019
9+
10+
async function readExistingStats() {
11+
try {
12+
return JSON.parse(await readFile(outputPath, 'utf-8'))
13+
}
14+
catch {
15+
return {
16+
repository,
17+
stars: 0,
18+
releaseDownloads: 0,
19+
activeDevelopmentStartYear: startYear,
20+
activeDevelopmentYears: new Date().getUTCFullYear() - startYear,
21+
updatedAt: null,
22+
}
23+
}
24+
}
25+
26+
function createHeaders() {
27+
const headers = {
28+
'Accept': 'application/vnd.github+json',
29+
'User-Agent': 'masscode-docs-build',
30+
'X-GitHub-Api-Version': '2022-11-28',
31+
}
32+
33+
// eslint-disable-next-line node/prefer-global/process
34+
const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN
35+
36+
if (token)
37+
headers.Authorization = `Bearer ${token}`
38+
39+
return headers
40+
}
41+
42+
async function fetchJson(url) {
43+
const response = await fetch(url, { headers: createHeaders() })
44+
45+
if (!response.ok)
46+
throw new Error(`GitHub API returned ${response.status} for ${url}`)
47+
48+
return response.json()
49+
}
50+
51+
async function fetchAllReleases() {
52+
const releases = []
53+
let page = 1
54+
55+
while (true) {
56+
const batch = await fetchJson(`https://api.github.com/repos/${repository}/releases?per_page=100&page=${page}`)
57+
58+
if (!Array.isArray(batch) || batch.length === 0)
59+
break
60+
61+
releases.push(...batch)
62+
63+
if (batch.length < 100)
64+
break
65+
66+
page += 1
67+
}
68+
69+
return releases
70+
}
71+
72+
function getReleaseDownloads(releases) {
73+
return releases.reduce((total, release) => {
74+
if (release.draft)
75+
return total
76+
77+
return total + release.assets.reduce((assetTotal, asset) => assetTotal + asset.download_count, 0)
78+
}, 0)
79+
}
80+
81+
async function updateStats() {
82+
const existingStats = await readExistingStats()
83+
84+
try {
85+
const [repo, releases] = await Promise.all([
86+
fetchJson(`https://api.github.com/repos/${repository}`),
87+
fetchAllReleases(),
88+
])
89+
90+
const stats = {
91+
repository,
92+
stars: repo.stargazers_count,
93+
releaseDownloads: getReleaseDownloads(releases),
94+
activeDevelopmentStartYear: startYear,
95+
activeDevelopmentYears: new Date().getUTCFullYear() - startYear,
96+
updatedAt: new Date().toISOString(),
97+
}
98+
99+
await mkdir(dirname(outputPath), { recursive: true })
100+
await writeFile(outputPath, `${JSON.stringify(stats, null, 2)}\n`)
101+
102+
console.log(`Updated GitHub stats: ${stats.stars} stars, ${stats.releaseDownloads} release downloads`)
103+
}
104+
catch (error) {
105+
const message = error instanceof Error ? error.message : String(error)
106+
107+
console.warn(`Could not update GitHub stats, using existing values: ${message}`)
108+
109+
await mkdir(dirname(outputPath), { recursive: true })
110+
await writeFile(outputPath, `${JSON.stringify(existingStats, null, 2)}\n`)
111+
}
112+
}
113+
114+
await updateStats()

docs/website/sponsor/index.md

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,31 @@ title: Sponsor massCode
33
description: "Sponsor massCode and be recognized across the project website, GitHub repository, release notes, and community updates."
44
---
55

6+
<script setup>
7+
import githubStats from '../.vitepress/_data/github-stats.json'
8+
9+
function formatMetric(value) {
10+
const number = Number(value)
11+
12+
if (!Number.isFinite(number) || number <= 0)
13+
return ''
14+
15+
if (number < 1000)
16+
return `${Math.floor(number).toLocaleString('en-US')}+`
17+
18+
const precision = number >= 100000 ? 1000 : 100
19+
const rounded = Math.floor(number / precision) * precision
20+
const shortValue = rounded / 1000
21+
const formatted = Number.isInteger(shortValue) ? shortValue.toString() : shortValue.toFixed(1)
22+
23+
return `${formatted}k`
24+
}
25+
26+
const githubStars = formatMetric(githubStats.stars)
27+
const releaseDownloads = formatMetric(githubStats.releaseDownloads)
28+
const activeDevelopmentYears = `${githubStats.activeDevelopmentYears}+`
29+
</script>
30+
631
# Sponsor massCode
732

833
**Support massCode and be recognized across the project website, GitHub repository, release notes, and community updates.**
@@ -32,9 +57,9 @@ Unlike cloud-based alternatives, massCode stores user content locally as plain M
3257

3358
| Metric | Value |
3459
| --- | --- |
35-
| GitHub stars | **6,700+** |
36-
| GitHub release downloads | **201,000+** |
37-
| Years in active development | **6+**, since 2019 |
60+
| GitHub stars | <strong>{{ githubStars }}</strong> |
61+
| GitHub release downloads | <strong>{{ releaseDownloads }}</strong> |
62+
| Years in active development | <strong>{{ activeDevelopmentYears }}</strong>, since 2019 |
3863
| Platforms | macOS, Windows, Linux |
3964
| Companion ecosystem | VS Code extension, Raycast extension, CLI tools |
4065
| Telemetry / tracking | **None, by design** |

0 commit comments

Comments
 (0)