Skip to content

Commit 1a7fdea

Browse files
nozomeefengmk2
andauthored
docs: refresh home stats for oxlint, vite, and vitest Issue: #1511 (#1512)
## Changes made ### 1. `docs/.vitepress/theme/components/home/FeatureCheck.vue` - **ESLint rule count (Vite+ check section):** `600+` → `750+` (text before the `ESLint` code span). ### 2. `docs/.vitepress/theme/components/home/ProductivityGrid.vue` **“A trusted stack to standardize on” — Vite** - Weekly npm downloads: `69m+` → `115m+` - GitHub stars: `78.7k` → `80.4k` **Vitest** - Weekly npm downloads: `35m+` → `57m+` - GitHub stars: `16.1k` → `16.5k` **OXC** (npm row uses `oxlint` package downloads) - Weekly npm downloads: `5m+` → `5.3m+` - GitHub stars: `19.8k` → `21.0k` --- **Files touched:** 2 **Net:** 7 lines updated (string substitutions only; no logic or layout changes). --------- Signed-off-by: deep <sarkarreall@gmail.com> Co-authored-by: nozomee <nozomee@users.noreply.github.com> Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
1 parent 76d962a commit 1a7fdea

11 files changed

Lines changed: 367 additions & 71 deletions
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Update trusted stack stats
2+
3+
on:
4+
schedule:
5+
# Weekly: Monday 06:00 UTC
6+
- cron: '0 6 * * 1'
7+
workflow_dispatch:
8+
9+
permissions: {}
10+
11+
defaults:
12+
run:
13+
shell: bash
14+
15+
jobs:
16+
update:
17+
if: github.repository == 'voidzero-dev/vite-plus' && github.event.repository.fork == false
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
with:
24+
persist-credentials: false
25+
26+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
27+
with:
28+
node-version-file: .node-version
29+
30+
- name: Fetch npm and GitHub stats
31+
env:
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
run: node docs/.vitepress/theme/data/fetch-trusted-stack-stats.ts
34+
35+
- uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
36+
id: app-token
37+
with:
38+
client-id: ${{ secrets.APP_ID }}
39+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
40+
41+
- name: Create or update PR
42+
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
43+
with:
44+
base: main
45+
branch: chore/docs-trusted-stack-stats
46+
title: 'chore(docs): refresh trusted stack stats'
47+
sign-commits: true
48+
token: ${{ steps.app-token.outputs.token }}
49+
commit-message: 'chore(docs): refresh trusted stack stats'
50+
add-paths: |
51+
docs/.vitepress/theme/data/trusted-stack-stats.json
52+
body: |
53+
Automated update of trusted stack statistics on the docs homepage.
54+
55+
- npm weekly downloads (last-week): vite, vitest, oxlint
56+
- GitHub stars: vitejs/vite, vitest-dev/vitest, oxc-project/oxc

docs/.vitepress/theme/components/home/FeatureCheck.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import oxcIcon from '@assets/icons/oxc-light.svg';
1818
formatting
1919
</li>
2020
<li>
21-
600+ <code class="mx-1 outline-none bg-nickel/50 text-aqua">ESLint</code> compatible
21+
750+ <code class="mx-1 outline-none bg-nickel/50 text-aqua">ESLint</code> compatible
2222
rules
2323
</li>
2424
<li>

docs/.vitepress/theme/components/home/ProductivityGrid.vue

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import productivitySecurityImage from '@local-assets/productivity-security.png';
66
import tileOxc from '@local-assets/tiles/oxc.png';
77
import tileVite from '@local-assets/tiles/vite.png';
88
import tileVitest from '@local-assets/tiles/vitest.png';
9+
10+
import { trustedStackById } from '../../data/trusted-stack-stats';
11+
12+
const viteStack = trustedStackById('vite');
13+
const vitestStack = trustedStackById('vitest');
14+
const oxcStack = trustedStackById('oxc');
915
</script>
1016

1117
<template>
@@ -31,13 +37,17 @@ import tileVitest from '@local-assets/tiles/vitest.png';
3137
<div
3238
class="relative flex flex-col flex-1 sm:pl-6 before:content-none sm:before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
3339
>
34-
<p class="text-primary font-medium text-base sm:text-xl">69m+</p>
40+
<p class="text-primary font-medium text-base sm:text-xl">
41+
{{ viteStack.npmWeeklyDownloadsDisplay }}
42+
</p>
3543
<p class="leading-tight text-base">Weekly npm downloads</p>
3644
</div>
3745
<div
3846
class="relative flex flex-col flex-shrink-0 pl-6 before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
3947
>
40-
<p class="text-primary font-medium text-base sm:text-xl">78.7k</p>
48+
<p class="text-primary font-medium text-base sm:text-xl">
49+
{{ viteStack.githubStarsDisplay }}
50+
</p>
4151
<p class="leading-tight text-base">GitHub stars</p>
4252
</div>
4353
</div>
@@ -54,13 +64,17 @@ import tileVitest from '@local-assets/tiles/vitest.png';
5464
<div
5565
class="relative flex flex-col flex-1 sm:pl-6 before:content-none sm:before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
5666
>
57-
<p class="text-primary font-medium text-base sm:text-xl">35m+</p>
67+
<p class="text-primary font-medium text-base sm:text-xl">
68+
{{ vitestStack.npmWeeklyDownloadsDisplay }}
69+
</p>
5870
<p class="leading-tight text-base">Weekly npm downloads</p>
5971
</div>
6072
<div
6173
class="relative flex flex-col flex-shrink-0 pl-6 before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
6274
>
63-
<p class="text-primary font-medium text-base sm:text-xl">16.1k</p>
75+
<p class="text-primary font-medium text-base sm:text-xl">
76+
{{ vitestStack.githubStarsDisplay }}
77+
</p>
6478
<p class="leading-tight text-base">GitHub stars</p>
6579
</div>
6680
</div>
@@ -77,13 +91,17 @@ import tileVitest from '@local-assets/tiles/vitest.png';
7791
<div
7892
class="relative flex flex-col flex-1 sm:pl-6 before:content-none sm:before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
7993
>
80-
<p class="text-primary font-medium text-base sm:text-xl">5m+</p>
94+
<p class="text-primary font-medium text-base sm:text-xl">
95+
{{ oxcStack.npmWeeklyDownloadsDisplay }}
96+
</p>
8197
<p class="leading-tight text-base">Weekly npm downloads</p>
8298
</div>
8399
<div
84100
class="relative flex flex-col flex-shrink-0 pl-6 before:content-[''] before:absolute before:left-0 before:top-1/2 before:-translate-y-1/2 before:h-full before:w-px before:bg-stroke"
85101
>
86-
<p class="text-primary font-medium text-base sm:text-xl">19.8k</p>
102+
<p class="text-primary font-medium text-base sm:text-xl">
103+
{{ oxcStack.githubStarsDisplay }}
104+
</p>
87105
<p class="leading-tight text-base">GitHub stars</p>
88106
</div>
89107
</div>
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { writeFile } from 'node:fs/promises';
2+
import { dirname, join } from 'node:path';
3+
import { fileURLToPath } from 'node:url';
4+
5+
/**
6+
* Fetches last-week npm download counts and GitHub star counts, then writes
7+
* `trusted-stack-stats.json` for the docs home page.
8+
*
9+
* Requires Node.js >=22.18 (strip types). Run:
10+
* `pnpm -C docs update-trusted-stack-stats`
11+
* or: `node docs/.vitepress/theme/data/fetch-trusted-stack-stats.ts`
12+
*/
13+
import type {
14+
TrustedStackProjectId,
15+
TrustedStackStatProject,
16+
TrustedStackStatsFile,
17+
} from './trusted-stack-stats.types';
18+
19+
const currentDir = dirname(fileURLToPath(import.meta.url));
20+
const OUT = join(currentDir, 'trusted-stack-stats.json');
21+
22+
interface ProjectSource {
23+
readonly id: TrustedStackProjectId;
24+
readonly npmPackage: string;
25+
readonly githubRepo: string;
26+
}
27+
28+
const PROJECTS: readonly ProjectSource[] = [
29+
{ id: 'vite', npmPackage: 'vite', githubRepo: 'vitejs/vite' },
30+
{ id: 'vitest', npmPackage: 'vitest', githubRepo: 'vitest-dev/vitest' },
31+
/** OXC row uses `oxlint` npm weekly downloads as a concrete proxy for the Oxc toolchain. */
32+
{ id: 'oxc', npmPackage: 'oxlint', githubRepo: 'oxc-project/oxc' },
33+
];
34+
35+
function formatWeeklyDownloads(n: number): string {
36+
if (n >= 10_000_000) {
37+
// "m+" reads as a lower bound, so avoid rounding up.
38+
return `${Math.floor(n / 1e6)}m+`;
39+
}
40+
const m = n / 1e6;
41+
const s = m.toFixed(1).replace(/\.0$/, '');
42+
return `${s}m+`;
43+
}
44+
45+
function formatStars(s: number): string {
46+
return `${(s / 1000).toFixed(1)}k`;
47+
}
48+
49+
function parseNpmDownloadsJson(data: unknown, pkg: string): number {
50+
if (typeof data !== 'object' || data === null || !('downloads' in data)) {
51+
throw new Error(`npm API ${pkg}: unexpected payload`);
52+
}
53+
const downloads = (data as { downloads: unknown }).downloads;
54+
if (typeof downloads !== 'number') {
55+
throw new Error(`npm API ${pkg}: unexpected payload`);
56+
}
57+
return downloads;
58+
}
59+
60+
async function npmLastWeekDownloads(pkg: string): Promise<number> {
61+
const url = `https://api.npmjs.org/downloads/point/last-week/${encodeURIComponent(pkg)}`;
62+
const res = await fetch(url);
63+
if (!res.ok) {
64+
const body = await res.text();
65+
throw new Error(`npm API ${pkg}: HTTP ${res.status} ${body}`);
66+
}
67+
return parseNpmDownloadsJson(await res.json(), pkg);
68+
}
69+
70+
function parseGithubRepoJson(data: unknown, repo: string): number {
71+
if (typeof data !== 'object' || data === null || !('stargazers_count' in data)) {
72+
throw new Error(`GitHub API ${repo}: unexpected payload`);
73+
}
74+
const count = (data as { stargazers_count: unknown }).stargazers_count;
75+
if (typeof count !== 'number') {
76+
throw new Error(`GitHub API ${repo}: unexpected payload`);
77+
}
78+
return count;
79+
}
80+
81+
async function fetchGithubStargazers(repo: string): Promise<number> {
82+
const url = `https://api.github.com/repos/${repo}`;
83+
const headers: Record<string, string> = {
84+
Accept: 'application/vnd.github+json',
85+
'X-GitHub-Api-Version': '2022-11-28',
86+
'User-Agent':
87+
'voidzero-dev/vite-plus (docs/.vitepress/theme/data/fetch-trusted-stack-stats.ts)',
88+
};
89+
const token = process.env.GITHUB_TOKEN;
90+
if (token !== undefined && token !== '') {
91+
headers.Authorization = `Bearer ${token}`;
92+
}
93+
const res = await fetch(url, { headers });
94+
if (!res.ok) {
95+
const body = await res.text();
96+
throw new Error(`GitHub API ${repo}: HTTP ${res.status} ${body}`);
97+
}
98+
return parseGithubRepoJson(await res.json(), repo);
99+
}
100+
101+
async function main(): Promise<void> {
102+
const projects: TrustedStackStatProject[] = [];
103+
for (const p of PROJECTS) {
104+
const [npmWeeklyDownloads, stars] = await Promise.all([
105+
npmLastWeekDownloads(p.npmPackage),
106+
fetchGithubStargazers(p.githubRepo),
107+
]);
108+
const row: TrustedStackStatProject = {
109+
id: p.id,
110+
npmPackage: p.npmPackage,
111+
githubRepo: p.githubRepo,
112+
npmWeeklyDownloads,
113+
githubStargazers: stars,
114+
npmWeeklyDownloadsDisplay: formatWeeklyDownloads(npmWeeklyDownloads),
115+
githubStarsDisplay: formatStars(stars),
116+
};
117+
projects.push(row);
118+
}
119+
const payload: TrustedStackStatsFile = { projects };
120+
await writeFile(OUT, `${JSON.stringify(payload, null, 2)}\n`, 'utf8');
121+
console.error(`Wrote ${OUT} at ${new Date().toISOString()}`);
122+
}
123+
124+
void main().catch((err: unknown) => {
125+
console.error(err);
126+
process.exitCode = 1;
127+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"projects": [
3+
{
4+
"id": "vite",
5+
"npmPackage": "vite",
6+
"githubRepo": "vitejs/vite",
7+
"npmWeeklyDownloads": 114052837,
8+
"githubStargazers": 80401,
9+
"npmWeeklyDownloadsDisplay": "114m+",
10+
"githubStarsDisplay": "80.4k"
11+
},
12+
{
13+
"id": "vitest",
14+
"npmPackage": "vitest",
15+
"githubRepo": "vitest-dev/vitest",
16+
"npmWeeklyDownloads": 56727793,
17+
"githubStargazers": 16471,
18+
"npmWeeklyDownloadsDisplay": "57m+",
19+
"githubStarsDisplay": "16.5k"
20+
},
21+
{
22+
"id": "oxc",
23+
"npmPackage": "oxlint",
24+
"githubRepo": "oxc-project/oxc",
25+
"npmWeeklyDownloads": 5237088,
26+
"githubStargazers": 20981,
27+
"npmWeeklyDownloadsDisplay": "5.2m+",
28+
"githubStarsDisplay": "21.0k"
29+
}
30+
]
31+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import raw from './trusted-stack-stats.json';
2+
import type {
3+
TrustedStackProjectId,
4+
TrustedStackStatProject,
5+
TrustedStackStatsFile,
6+
} from './trusted-stack-stats.types';
7+
8+
export type {
9+
TrustedStackProjectId,
10+
TrustedStackStatProject,
11+
TrustedStackStatsFile,
12+
} from './trusted-stack-stats.types';
13+
14+
export const trustedStackStats = raw as TrustedStackStatsFile;
15+
16+
export function trustedStackById(id: TrustedStackProjectId): TrustedStackStatProject {
17+
const project = trustedStackStats.projects.find((p) => p.id === id);
18+
if (!project) {
19+
throw new Error(`trusted-stack-stats.json: missing project "${id}"`);
20+
}
21+
return project;
22+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export type TrustedStackProjectId = 'vite' | 'vitest' | 'oxc';
2+
3+
export interface TrustedStackStatProject {
4+
id: TrustedStackProjectId;
5+
npmPackage: string;
6+
githubRepo: string;
7+
npmWeeklyDownloads: number;
8+
githubStargazers: number;
9+
npmWeeklyDownloadsDisplay: string;
10+
githubStarsDisplay: string;
11+
}
12+
13+
export interface TrustedStackStatsFile {
14+
projects: TrustedStackStatProject[];
15+
}

docs/.vitepress/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
"@components/*": ["../node_modules/@voidzero-dev/vitepress-theme/src/components/*"]
1919
}
2020
},
21-
"include": ["**/*.ts", "**/*.d.ts", "**/*.vue"]
21+
"include": ["**/*.ts", "**/*.d.ts", "**/*.vue", "theme/data/*.json"]
2222
}

docs/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"scripts": {
66
"dev": "vitepress dev",
77
"build": "cp ../packages/cli/install.sh ../packages/cli/install.ps1 public/ && vitepress build",
8-
"preview": "vitepress preview"
8+
"preview": "vitepress preview",
9+
"update-trusted-stack-stats": "node .vitepress/theme/data/fetch-trusted-stack-stats.ts"
910
},
1011
"dependencies": {
1112
"@iconify/vue": "^5.0.0",

0 commit comments

Comments
 (0)