Skip to content

Commit 83c516b

Browse files
committed
init
1 parent 7bbe9a3 commit 83c516b

23 files changed

+7707
-2829
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GITHUB_TOKEN=your_github_token
2+
CDN_URL=https://cdn.example.com

.github/workflows/build.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Build
2+
3+
on:
4+
# Runs on pushes targeting the default branch
5+
push:
6+
branches: ["main"]
7+
release:
8+
types: [published]
9+
10+
# Allows you to run this workflow manually from the Actions tab
11+
workflow_dispatch:
12+
13+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
14+
permissions:
15+
contents: read
16+
pages: write
17+
id-token: write
18+
19+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
20+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
21+
concurrency:
22+
group: "pages"
23+
cancel-in-progress: false
24+
25+
jobs:
26+
# Build job
27+
build:
28+
permissions:
29+
contents: write
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
- name: Detect package manager
35+
id: detect-package-manager
36+
run: |
37+
if [ -f "${{ github.workspace }}/yarn.lock" ]; then
38+
echo "manager=yarn" >> $GITHUB_OUTPUT
39+
echo "command=install" >> $GITHUB_OUTPUT
40+
exit 0
41+
elif [ -f "${{ github.workspace }}/package.json" ]; then
42+
echo "manager=npm" >> $GITHUB_OUTPUT
43+
echo "command=ci" >> $GITHUB_OUTPUT
44+
exit 0
45+
else
46+
echo "Unable to determine package manager"
47+
exit 1
48+
fi
49+
- name: Setup Node
50+
uses: actions/setup-node@v4
51+
with:
52+
node-version: "22"
53+
cache: ${{ steps.detect-package-manager.outputs.manager }}
54+
- name: Install dependencies
55+
run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }}
56+
- name: Static HTML export with Next.js
57+
run: ${{ steps.detect-package-manager.outputs.manager }} run build
58+
- name: Upload to Bucket
59+
uses: JohnGuan/oss-upload-action@main
60+
with:
61+
key-id: ${{ secrets.ALICLOUDOSS_KEY_ID }}
62+
key-secret: ${{ secrets.ALICLOUDOSS_KEY_SECRET }}
63+
region: oss-cn-beijing
64+
bucket: rustfs-artifacts
65+
assets: |
66+
./out/**:/

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ yarn-error.log*
3232

3333
# env files (can opt-in for committing if needed)
3434
.env*
35+
!.env.example
3536

3637
# vercel
3738
.vercel

app/[repo]/page.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import ReleaseCard from '@/components/release';
2+
import { projects } from '@/projects.config';
3+
import { fetchReleases } from '@/scripts/generate-releases';
4+
import { Release } from '@/types';
5+
import fs from 'fs';
6+
import Link from 'next/link';
7+
import { notFound } from 'next/navigation';
8+
import path from 'path';
9+
10+
// 生成静态路径参数
11+
export async function generateStaticParams() {
12+
await fetchReleases()
13+
return projects.map(project => ({
14+
repo: project.repo,
15+
}));
16+
}
17+
18+
export default async function ProjectPage({ params }: { params: Promise<{ repo: string }> }) {
19+
const { repo } = await params;
20+
21+
// 查找项目信息
22+
const project = projects.find(p => p.repo === repo);
23+
24+
if (!project) {
25+
notFound();
26+
}
27+
28+
// 读取存储的 releases 数据
29+
let releases: Release[] = [];
30+
try {
31+
releases = JSON.parse(
32+
fs.readFileSync(path.join(process.cwd(), 'data', repo, 'releases.json'), 'utf8')
33+
);
34+
} catch (error) {
35+
console.error('Failed to load releases data:', error);
36+
}
37+
38+
return (
39+
<div className="container mx-auto px-4 py-8 max-w-5xl">
40+
<h1 className="text-3xl font-extrabold mb-2">{project.title || repo}</h1>
41+
{project.description && <p className="text-gray-600 mb-8">{project.description}</p>}
42+
43+
{project.links.length > 0 ? (
44+
<div className="space-x-4 mb-8">
45+
{project.links.map(link => (
46+
<Link
47+
key={link.url}
48+
href={link.url}
49+
className="text-blue-600 hover:underline"
50+
target="_blank"
51+
rel="noopener noreferrer"
52+
>
53+
{link.label}
54+
</Link>
55+
))}
56+
</div>
57+
) : null}
58+
59+
{releases.length > 0 ? (
60+
<div className="space-y-6">
61+
{releases.map((release, index) => (
62+
<ReleaseCard key={release.id} project={project} release={release} isLatest={index == 0} />
63+
))}
64+
</div>
65+
) : (
66+
<p>No releases found for this project.</p>
67+
)}
68+
</div>
69+
);
70+
}

app/globals.css

Lines changed: 112 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,125 @@
11
@import "tailwindcss";
22

3-
:root {
4-
--background: #ffffff;
5-
--foreground: #171717;
6-
}
3+
@plugin "tailwindcss-animate";
4+
@plugin "@tailwindcss/typography";
5+
6+
@custom-variant dark (&:is(.dark *));
77

88
@theme inline {
99
--color-background: var(--background);
1010
--color-foreground: var(--foreground);
1111
--font-sans: var(--font-geist-sans);
1212
--font-mono: var(--font-geist-mono);
13+
--color-sidebar-ring: var(--sidebar-ring);
14+
--color-sidebar-border: var(--sidebar-border);
15+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
16+
--color-sidebar-accent: var(--sidebar-accent);
17+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
18+
--color-sidebar-primary: var(--sidebar-primary);
19+
--color-sidebar-foreground: var(--sidebar-foreground);
20+
--color-sidebar: var(--sidebar);
21+
--color-chart-5: var(--chart-5);
22+
--color-chart-4: var(--chart-4);
23+
--color-chart-3: var(--chart-3);
24+
--color-chart-2: var(--chart-2);
25+
--color-chart-1: var(--chart-1);
26+
--color-ring: var(--ring);
27+
--color-input: var(--input);
28+
--color-border: var(--border);
29+
--color-destructive: var(--destructive);
30+
--color-accent-foreground: var(--accent-foreground);
31+
--color-accent: var(--accent);
32+
--color-muted-foreground: var(--muted-foreground);
33+
--color-muted: var(--muted);
34+
--color-secondary-foreground: var(--secondary-foreground);
35+
--color-secondary: var(--secondary);
36+
--color-primary-foreground: var(--primary-foreground);
37+
--color-primary: var(--primary);
38+
--color-popover-foreground: var(--popover-foreground);
39+
--color-popover: var(--popover);
40+
--color-card-foreground: var(--card-foreground);
41+
--color-card: var(--card);
42+
--radius-sm: calc(var(--radius) - 4px);
43+
--radius-md: calc(var(--radius) - 2px);
44+
--radius-lg: var(--radius);
45+
--radius-xl: calc(var(--radius) + 4px);
1346
}
1447

15-
@media (prefers-color-scheme: dark) {
16-
:root {
17-
--background: #0a0a0a;
18-
--foreground: #ededed;
19-
}
48+
:root {
49+
--radius: 0.625rem;
50+
--background: oklch(1 0 0);
51+
--foreground: oklch(0.145 0 0);
52+
--card: oklch(1 0 0);
53+
--card-foreground: oklch(0.145 0 0);
54+
--popover: oklch(1 0 0);
55+
--popover-foreground: oklch(0.145 0 0);
56+
--primary: oklch(0.205 0 0);
57+
--primary-foreground: oklch(0.985 0 0);
58+
--secondary: oklch(0.97 0 0);
59+
--secondary-foreground: oklch(0.205 0 0);
60+
--muted: oklch(0.97 0 0);
61+
--muted-foreground: oklch(0.556 0 0);
62+
--accent: oklch(0.97 0 0);
63+
--accent-foreground: oklch(0.205 0 0);
64+
--destructive: oklch(0.577 0.245 27.325);
65+
--border: oklch(0.922 0 0);
66+
--input: oklch(0.922 0 0);
67+
--ring: oklch(0.708 0 0);
68+
--chart-1: oklch(0.646 0.222 41.116);
69+
--chart-2: oklch(0.6 0.118 184.704);
70+
--chart-3: oklch(0.398 0.07 227.392);
71+
--chart-4: oklch(0.828 0.189 84.429);
72+
--chart-5: oklch(0.769 0.188 70.08);
73+
--sidebar: oklch(0.985 0 0);
74+
--sidebar-foreground: oklch(0.145 0 0);
75+
--sidebar-primary: oklch(0.205 0 0);
76+
--sidebar-primary-foreground: oklch(0.985 0 0);
77+
--sidebar-accent: oklch(0.97 0 0);
78+
--sidebar-accent-foreground: oklch(0.205 0 0);
79+
--sidebar-border: oklch(0.922 0 0);
80+
--sidebar-ring: oklch(0.708 0 0);
2081
}
2182

22-
body {
23-
background: var(--background);
24-
color: var(--foreground);
25-
font-family: Arial, Helvetica, sans-serif;
83+
.dark {
84+
--background: oklch(0.145 0 0);
85+
--foreground: oklch(0.985 0 0);
86+
--card: oklch(0.205 0 0);
87+
--card-foreground: oklch(0.985 0 0);
88+
--popover: oklch(0.205 0 0);
89+
--popover-foreground: oklch(0.985 0 0);
90+
--primary: oklch(0.922 0 0);
91+
--primary-foreground: oklch(0.205 0 0);
92+
--secondary: oklch(0.269 0 0);
93+
--secondary-foreground: oklch(0.985 0 0);
94+
--muted: oklch(0.269 0 0);
95+
--muted-foreground: oklch(0.708 0 0);
96+
--accent: oklch(0.269 0 0);
97+
--accent-foreground: oklch(0.985 0 0);
98+
--destructive: oklch(0.704 0.191 22.216);
99+
--border: oklch(1 0 0 / 10%);
100+
--input: oklch(1 0 0 / 15%);
101+
--ring: oklch(0.556 0 0);
102+
--chart-1: oklch(0.488 0.243 264.376);
103+
--chart-2: oklch(0.696 0.17 162.48);
104+
--chart-3: oklch(0.769 0.188 70.08);
105+
--chart-4: oklch(0.627 0.265 303.9);
106+
--chart-5: oklch(0.645 0.246 16.439);
107+
--sidebar: oklch(0.205 0 0);
108+
--sidebar-foreground: oklch(0.985 0 0);
109+
--sidebar-primary: oklch(0.488 0.243 264.376);
110+
--sidebar-primary-foreground: oklch(0.985 0 0);
111+
--sidebar-accent: oklch(0.269 0 0);
112+
--sidebar-accent-foreground: oklch(0.985 0 0);
113+
--sidebar-border: oklch(1 0 0 / 10%);
114+
--sidebar-ring: oklch(0.556 0 0);
115+
}
116+
117+
@layer base {
118+
* {
119+
@apply border-border outline-ring/50;
120+
}
121+
122+
body {
123+
@apply bg-background text-foreground;
124+
}
26125
}

0 commit comments

Comments
 (0)