@webywz/breathing-github-profile 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +280 -2
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +126 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/generator.d.ts +16 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +161 -0
- package/dist/generator.js.map +1 -0
- package/dist/github.d.ts +11 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +68 -0
- package/dist/github.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +68 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/examples/README.md +115 -0
- package/examples/demo-config.yml +21 -0
- package/examples/webywz.yml +66 -0
- package/package.json +64 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 webywz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,281 @@
|
|
|
1
|
-
#
|
|
1
|
+
# breathing-github-profile
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**A living GitHub profile README — declarative config, marker-safe refresh, CLI + library.**
|
|
4
|
+
**会呼吸的 GitHub 主页 README:声明式配置、标记保护区刷新,CLI 与库双入口。**
|
|
5
|
+
|
|
6
|
+
[](https://www.npmjs.com/package/@webywz/breathing-github-profile)
|
|
7
|
+
[](https://github.com/webywz/breathing-github-profile/actions/workflows/test.yml)
|
|
8
|
+
[](./LICENSE)
|
|
9
|
+
|
|
10
|
+
Package: `@webywz/breathing-github-profile` · CLI binary: `breathing-profile` · Node 18+
|
|
11
|
+
|
|
12
|
+
> Not on the npm registry yet. Install from GitHub until the first publish.
|
|
13
|
+
> 尚未发布到 npm,请先从 GitHub 安装。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Features · 特性
|
|
18
|
+
|
|
19
|
+
| | EN | 中文 |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| Config | YAML / JSON define intro, sections, and style | YAML / JSON 声明介绍、章节与样式 |
|
|
22
|
+
| Refresh | Updates only `<!--MARKER:START-->…<!--MARKER:END-->` | 只改标记区,手写文案保留 |
|
|
23
|
+
| Stats | Stars, forks, repos, followers; language mix; featured repos | 统计、语言分布、精选仓库 |
|
|
24
|
+
| Sections | `stats` · `languages` · `repos` · `custom` | 四种章节类型 |
|
|
25
|
+
| Automation | Daily GitHub Actions workflow | Actions 每日定时刷新 |
|
|
26
|
+
| API | CLI commands + TypeScript library exports | CLI + 库 |
|
|
27
|
+
|
|
28
|
+
Live example: [webywz/webywz](https://github.com/webywz/webywz).
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Install · 安装
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install github:webywz/breathing-github-profile
|
|
36
|
+
npx breathing-profile --help
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
From source (develop / unpublished):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
git clone https://github.com/webywz/breathing-github-profile.git
|
|
43
|
+
cd breathing-github-profile
|
|
44
|
+
npm install
|
|
45
|
+
npm run build
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
One-shot without a local clone:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npx --yes --package github:webywz/breathing-github-profile -- breathing-profile generate -c config.yml -o README.md
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
After the package is published:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm i -g @webywz/breathing-github-profile
|
|
58
|
+
npx @webywz/breathing-github-profile --help
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Quick start · 快速开始
|
|
64
|
+
|
|
65
|
+
### 1. Config · 配置
|
|
66
|
+
|
|
67
|
+
Create `config.yml`:
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
username: your-github-username
|
|
71
|
+
|
|
72
|
+
intro:
|
|
73
|
+
zh: |
|
|
74
|
+
Full-stack developer · open source
|
|
75
|
+
Happy to connect.
|
|
76
|
+
en: |
|
|
77
|
+
Full-stack developer · open source
|
|
78
|
+
Let's connect.
|
|
79
|
+
|
|
80
|
+
featuredRepos:
|
|
81
|
+
- your-best-repo
|
|
82
|
+
|
|
83
|
+
sections:
|
|
84
|
+
- type: stats
|
|
85
|
+
marker: STATS
|
|
86
|
+
title: GitHub Stats · 统计
|
|
87
|
+
|
|
88
|
+
- type: languages
|
|
89
|
+
marker: LANGUAGES
|
|
90
|
+
title: Languages · 常用语言
|
|
91
|
+
|
|
92
|
+
- type: repos
|
|
93
|
+
marker: REPOS
|
|
94
|
+
title: Featured · 精选项目
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Full sample: [examples/webywz.yml](examples/webywz.yml).
|
|
98
|
+
|
|
99
|
+
### 2. Generate · 生成
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npx breathing-profile generate -c config.yml -o README.md
|
|
103
|
+
npx breathing-profile refresh -c config.yml -r README.md
|
|
104
|
+
npx breathing-profile validate -c config.yml
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
| Command | EN | 中文 |
|
|
108
|
+
| --- | --- | --- |
|
|
109
|
+
| `generate` | Write a full README from config + GitHub data | 按配置与 GitHub 数据生成完整 README |
|
|
110
|
+
| `refresh` | Rewrite marker sections only | 只刷新标记区 |
|
|
111
|
+
| `validate` | Check the config file | 校验配置 |
|
|
112
|
+
|
|
113
|
+
Optional: set `GITHUB_TOKEN` (or use `secrets.GITHUB_TOKEN` in Actions) for higher API rate limits.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Configuration · 配置说明
|
|
118
|
+
|
|
119
|
+
### Top-level · 顶层字段
|
|
120
|
+
|
|
121
|
+
| Field | Type | Required | Notes |
|
|
122
|
+
| --- | --- | --- | --- |
|
|
123
|
+
| `username` | string | yes | GitHub login |
|
|
124
|
+
| `intro.zh` / `intro.en` | string | one of zh/en | Bilingual intro blocks |
|
|
125
|
+
| `featuredRepos` | string[] | no | Pinned repo names |
|
|
126
|
+
| `sections` | Section[] | no | Ordered sections |
|
|
127
|
+
| `style` | StyleConfig | no | Theme / layout knobs |
|
|
128
|
+
|
|
129
|
+
### Section types · 章节类型
|
|
130
|
+
|
|
131
|
+
**`stats`** — totals (stars, forks, public repos, followers, following).
|
|
132
|
+
|
|
133
|
+
```yaml
|
|
134
|
+
- type: stats
|
|
135
|
+
marker: STATS
|
|
136
|
+
title: GitHub Stats · 统计
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**`languages`** — top languages by share.
|
|
140
|
+
|
|
141
|
+
```yaml
|
|
142
|
+
- type: languages
|
|
143
|
+
marker: LANGUAGES
|
|
144
|
+
title: Languages · 常用语言
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**`repos`** — featured list, or highest-star repos when `featuredRepos` is empty.
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
- type: repos
|
|
151
|
+
marker: REPOS
|
|
152
|
+
title: Featured · 精选项目
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**`custom`** — raw Markdown inside a marker.
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
- type: custom
|
|
159
|
+
marker: TECH_STACK
|
|
160
|
+
title: Stack · 技术栈
|
|
161
|
+
content: |
|
|
162
|
+
TypeScript · NestJS · FastAPI · Vue
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Markers must match exactly:
|
|
166
|
+
|
|
167
|
+
```markdown
|
|
168
|
+
<!--STATS:START-->
|
|
169
|
+
…
|
|
170
|
+
<!--STATS:END-->
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Automation · 自动刷新
|
|
176
|
+
|
|
177
|
+
In your profile repo (`USER/USER`):
|
|
178
|
+
|
|
179
|
+
1. Add `config.yml`
|
|
180
|
+
2. Add `.github/workflows/refresh-profile.yml`:
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
name: Refresh profile README
|
|
184
|
+
|
|
185
|
+
on:
|
|
186
|
+
schedule:
|
|
187
|
+
- cron: '0 0 * * *' # daily 00:00 UTC
|
|
188
|
+
workflow_dispatch:
|
|
189
|
+
|
|
190
|
+
permissions:
|
|
191
|
+
contents: write
|
|
192
|
+
|
|
193
|
+
jobs:
|
|
194
|
+
refresh:
|
|
195
|
+
runs-on: ubuntu-latest
|
|
196
|
+
steps:
|
|
197
|
+
- uses: actions/checkout@v4
|
|
198
|
+
- uses: actions/setup-node@v4
|
|
199
|
+
with:
|
|
200
|
+
node-version: '20'
|
|
201
|
+
- run: npm install github:webywz/breathing-github-profile
|
|
202
|
+
- name: Refresh README
|
|
203
|
+
env:
|
|
204
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
205
|
+
run: npx breathing-profile refresh
|
|
206
|
+
- name: Commit if changed
|
|
207
|
+
run: |
|
|
208
|
+
git config user.name "github-actions[bot]"
|
|
209
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
210
|
+
git add README.md data/profile.json
|
|
211
|
+
git diff --quiet || git commit -m "chore: refresh profile README"
|
|
212
|
+
git push
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Flow: cron → GitHub API → rewrite markers → commit only when content changed. Copy outside markers is never touched.
|
|
216
|
+
|
|
217
|
+
流程:定时触发 → 拉 GitHub 数据 → 只改标记区 → 有变更才提交。标记外的手写内容不会被动。
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Library · 作为库使用
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import {
|
|
225
|
+
loadConfig,
|
|
226
|
+
GitHubClient,
|
|
227
|
+
ReadmeGenerator,
|
|
228
|
+
} from '@webywz/breathing-github-profile';
|
|
229
|
+
|
|
230
|
+
const config = loadConfig('config.yml');
|
|
231
|
+
const client = new GitHubClient(process.env.GITHUB_TOKEN);
|
|
232
|
+
const data = await client.getProfileData(config.username);
|
|
233
|
+
const readme = new ReadmeGenerator(config, data).generate();
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Also exported: `validateConfig`, `getDefaultConfig`, `updateReadmeMarkers`.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Develop · 开发
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
git clone https://github.com/webywz/breathing-github-profile.git
|
|
244
|
+
cd breathing-github-profile
|
|
245
|
+
npm install
|
|
246
|
+
npm run build
|
|
247
|
+
npm test
|
|
248
|
+
npm run lint
|
|
249
|
+
|
|
250
|
+
npm run generate -- -c examples/webywz.yml -o examples/README.md
|
|
251
|
+
npm run refresh -- -c examples/webywz.yml -r examples/README.md
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
src/
|
|
256
|
+
types.ts types
|
|
257
|
+
config.ts load / validate
|
|
258
|
+
github.ts GitHub client
|
|
259
|
+
generator.ts README generate + marker update
|
|
260
|
+
cli.ts CLI
|
|
261
|
+
index.ts library entry
|
|
262
|
+
examples/ sample configs
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## FAQ · 常见问题
|
|
268
|
+
|
|
269
|
+
**Rate limits?** Set `GITHUB_TOKEN`. Actions already injects `secrets.GITHUB_TOKEN`.
|
|
270
|
+
|
|
271
|
+
**Only update part of the README?** Use `refresh`, not `generate`.
|
|
272
|
+
|
|
273
|
+
**Markers not updating?** Names must match `marker` in config; use `<!--NAME:START-->` / `<!--NAME:END-->`.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Links · 链接
|
|
278
|
+
|
|
279
|
+
- Demo profile: [webywz/webywz](https://github.com/webywz/webywz)
|
|
280
|
+
- Contributing: [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
281
|
+
- License: [MIT](LICENSE) © webywz
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
9
|
+
const ora_1 = __importDefault(require("ora"));
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
const path_1 = require("path");
|
|
12
|
+
const config_1 = require("./config");
|
|
13
|
+
const github_1 = require("./github");
|
|
14
|
+
const generator_1 = require("./generator");
|
|
15
|
+
const program = new commander_1.Command();
|
|
16
|
+
program
|
|
17
|
+
.name('breathing-profile')
|
|
18
|
+
.description('可复用的活跃 GitHub profile README 生成器')
|
|
19
|
+
.version('1.0.0');
|
|
20
|
+
program
|
|
21
|
+
.command('generate')
|
|
22
|
+
.description('生成新的 README.md')
|
|
23
|
+
.option('-c, --config <path>', '配置文件路径', 'config.yml')
|
|
24
|
+
.option('-o, --output <path>', '输出文件路径', 'README.md')
|
|
25
|
+
.action(async (options) => {
|
|
26
|
+
const spinner = (0, ora_1.default)('正在生成 README...').start();
|
|
27
|
+
try {
|
|
28
|
+
if (!(0, fs_1.existsSync)(options.config)) {
|
|
29
|
+
throw new Error(`配置文件不存在: ${options.config}`);
|
|
30
|
+
}
|
|
31
|
+
const config = (0, config_1.loadConfig)(options.config);
|
|
32
|
+
const client = new github_1.GitHubClient();
|
|
33
|
+
spinner.text = `正在获取 ${config.username} 的 GitHub 数据...`;
|
|
34
|
+
const data = await client.getProfileData(config.username);
|
|
35
|
+
spinner.text = '正在生成 README 内容...';
|
|
36
|
+
const generator = new generator_1.ReadmeGenerator(config, data);
|
|
37
|
+
const readme = generator.generate();
|
|
38
|
+
(0, fs_1.writeFileSync)(options.output, readme, 'utf-8');
|
|
39
|
+
const dataDir = 'data';
|
|
40
|
+
if (!(0, fs_1.existsSync)(dataDir)) {
|
|
41
|
+
(0, fs_1.mkdirSync)(dataDir, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(dataDir, 'profile.json'), JSON.stringify(data, null, 2), 'utf-8');
|
|
44
|
+
spinner.succeed(chalk_1.default.green(`✓ README 已生成: ${options.output}`));
|
|
45
|
+
console.log(chalk_1.default.gray(` 数据已保存到: ${(0, path_1.join)(dataDir, 'profile.json')}`));
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
spinner.fail(chalk_1.default.red('生成失败'));
|
|
49
|
+
console.error(chalk_1.default.red(`错误: ${error.message}`));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
program
|
|
54
|
+
.command('refresh')
|
|
55
|
+
.description('刷新现有 README 的标记部分')
|
|
56
|
+
.option('-c, --config <path>', '配置文件路径', 'config.yml')
|
|
57
|
+
.option('-r, --readme <path>', 'README 文件路径', 'README.md')
|
|
58
|
+
.action(async (options) => {
|
|
59
|
+
const spinner = (0, ora_1.default)('正在刷新 README...').start();
|
|
60
|
+
try {
|
|
61
|
+
if (!(0, fs_1.existsSync)(options.config)) {
|
|
62
|
+
throw new Error(`配置文件不存在: ${options.config}`);
|
|
63
|
+
}
|
|
64
|
+
if (!(0, fs_1.existsSync)(options.readme)) {
|
|
65
|
+
throw new Error(`README 文件不存在: ${options.readme}`);
|
|
66
|
+
}
|
|
67
|
+
const config = (0, config_1.loadConfig)(options.config);
|
|
68
|
+
const client = new github_1.GitHubClient();
|
|
69
|
+
spinner.text = `正在获取 ${config.username} 的 GitHub 数据...`;
|
|
70
|
+
const data = await client.getProfileData(config.username);
|
|
71
|
+
spinner.text = '正在更新 README 标记部分...';
|
|
72
|
+
const existingReadme = (0, fs_1.readFileSync)(options.readme, 'utf-8');
|
|
73
|
+
const markerSections = (config.sections || []).map(section => {
|
|
74
|
+
const marker = section.marker || section.type.toUpperCase();
|
|
75
|
+
let content = '';
|
|
76
|
+
const tempGenerator = new generator_1.ReadmeGenerator(config, data);
|
|
77
|
+
const fullReadme = tempGenerator.generate();
|
|
78
|
+
const startMarker = `<!--${marker}:START-->`;
|
|
79
|
+
const endMarker = `<!--${marker}:END-->`;
|
|
80
|
+
const regex = new RegExp(`${escapeRegex(startMarker)}([\\s\\S]*?)${escapeRegex(endMarker)}`);
|
|
81
|
+
const match = fullReadme.match(regex);
|
|
82
|
+
if (match) {
|
|
83
|
+
content = match[1].trim();
|
|
84
|
+
}
|
|
85
|
+
return { marker, content };
|
|
86
|
+
});
|
|
87
|
+
const updatedReadme = (0, generator_1.updateReadmeMarkers)(existingReadme, markerSections);
|
|
88
|
+
(0, fs_1.writeFileSync)(options.readme, updatedReadme, 'utf-8');
|
|
89
|
+
const dataDir = 'data';
|
|
90
|
+
if (!(0, fs_1.existsSync)(dataDir)) {
|
|
91
|
+
(0, fs_1.mkdirSync)(dataDir, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
(0, fs_1.writeFileSync)((0, path_1.join)(dataDir, 'profile.json'), JSON.stringify(data, null, 2), 'utf-8');
|
|
94
|
+
spinner.succeed(chalk_1.default.green(`✓ README 已刷新: ${options.readme}`));
|
|
95
|
+
console.log(chalk_1.default.gray(` 数据已保存到: ${(0, path_1.join)(dataDir, 'profile.json')}`));
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
spinner.fail(chalk_1.default.red('刷新失败'));
|
|
99
|
+
console.error(chalk_1.default.red(`错误: ${error.message}`));
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
program
|
|
104
|
+
.command('validate')
|
|
105
|
+
.description('验证配置文件')
|
|
106
|
+
.option('-c, --config <path>', '配置文件路径', 'config.yml')
|
|
107
|
+
.action(async (options) => {
|
|
108
|
+
try {
|
|
109
|
+
if (!(0, fs_1.existsSync)(options.config)) {
|
|
110
|
+
throw new Error(`配置文件不存在: ${options.config}`);
|
|
111
|
+
}
|
|
112
|
+
const config = (0, config_1.loadConfig)(options.config);
|
|
113
|
+
console.log(chalk_1.default.green('✓ 配置文件有效'));
|
|
114
|
+
console.log(chalk_1.default.gray('\n配置内容:'));
|
|
115
|
+
console.log(JSON.stringify(config, null, 2));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.error(chalk_1.default.red(`✗ 配置文件无效: ${error.message}`));
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
function escapeRegex(str) {
|
|
123
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
124
|
+
}
|
|
125
|
+
program.parse();
|
|
126
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ProfileConfig } from './types';
|
|
2
|
+
export declare function loadConfig(configPath: string): ProfileConfig;
|
|
3
|
+
export declare function validateConfig(config: ProfileConfig): void;
|
|
4
|
+
export declare function getDefaultConfig(): Partial<ProfileConfig>;
|
|
5
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAc5D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CA+B1D;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,aAAa,CAAC,CAazD"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadConfig = loadConfig;
|
|
4
|
+
exports.validateConfig = validateConfig;
|
|
5
|
+
exports.getDefaultConfig = getDefaultConfig;
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const yaml_1 = require("yaml");
|
|
8
|
+
function loadConfig(configPath) {
|
|
9
|
+
const content = (0, fs_1.readFileSync)(configPath, 'utf-8');
|
|
10
|
+
let config;
|
|
11
|
+
if (configPath.endsWith('.json')) {
|
|
12
|
+
config = JSON.parse(content);
|
|
13
|
+
}
|
|
14
|
+
else if (configPath.endsWith('.yml') || configPath.endsWith('.yaml')) {
|
|
15
|
+
config = (0, yaml_1.parse)(content);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
throw new Error('配置文件必须是 .json, .yml 或 .yaml 格式');
|
|
19
|
+
}
|
|
20
|
+
validateConfig(config);
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
function validateConfig(config) {
|
|
24
|
+
if (!config.username || typeof config.username !== 'string') {
|
|
25
|
+
throw new Error('配置中必须包含有效的 username 字段');
|
|
26
|
+
}
|
|
27
|
+
if (!config.intro || typeof config.intro !== 'object') {
|
|
28
|
+
throw new Error('配置中必须包含 intro 对象');
|
|
29
|
+
}
|
|
30
|
+
if (!config.intro.zh && !config.intro.en) {
|
|
31
|
+
throw new Error('intro 必须至少包含 zh 或 en 字段');
|
|
32
|
+
}
|
|
33
|
+
if (config.featuredRepos && !Array.isArray(config.featuredRepos)) {
|
|
34
|
+
throw new Error('featuredRepos 必须是数组');
|
|
35
|
+
}
|
|
36
|
+
if (config.sections && !Array.isArray(config.sections)) {
|
|
37
|
+
throw new Error('sections 必须是数组');
|
|
38
|
+
}
|
|
39
|
+
if (config.sections) {
|
|
40
|
+
for (const section of config.sections) {
|
|
41
|
+
if (!['stats', 'languages', 'repos', 'custom'].includes(section.type)) {
|
|
42
|
+
throw new Error(`不支持的 section 类型: ${section.type}`);
|
|
43
|
+
}
|
|
44
|
+
if (section.type === 'custom' && !section.content) {
|
|
45
|
+
throw new Error('custom 类型的 section 必须包含 content 字段');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function getDefaultConfig() {
|
|
51
|
+
return {
|
|
52
|
+
sections: [
|
|
53
|
+
{ type: 'stats', marker: 'STATS' },
|
|
54
|
+
{ type: 'languages', marker: 'LANGUAGES' },
|
|
55
|
+
{ type: 'repos', marker: 'REPOS' }
|
|
56
|
+
],
|
|
57
|
+
style: {
|
|
58
|
+
theme: 'auto',
|
|
59
|
+
icons: true,
|
|
60
|
+
badges: true
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;AAIA,gCAcC;AAED,wCA+BC;AAED,4CAaC;AAlED,2BAAkC;AAClC,+BAA0C;AAG1C,SAAgB,UAAU,CAAC,UAAkB;IAC3C,MAAM,OAAO,GAAG,IAAA,iBAAY,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAElD,IAAI,MAAqB,CAAC;IAC1B,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACjC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;SAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvE,MAAM,GAAG,IAAA,YAAS,EAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAgB,cAAc,CAAC,MAAqB;IAClD,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,MAAM,CAAC,aAAa,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,KAAK,CAAC,oBAAoB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,gBAAgB;IAC9B,OAAO;QACL,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;YAClC,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE;YAC1C,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE;SACnC;QACD,KAAK,EAAE;YACL,KAAK,EAAE,MAAM;YACb,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;SACb;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ProfileConfig, ProfileData, MarkerSection } from './types';
|
|
2
|
+
export declare class ReadmeGenerator {
|
|
3
|
+
private config;
|
|
4
|
+
private data;
|
|
5
|
+
constructor(config: ProfileConfig, data: ProfileData);
|
|
6
|
+
generate(): string;
|
|
7
|
+
private generateHeader;
|
|
8
|
+
private generateIntro;
|
|
9
|
+
private generateSection;
|
|
10
|
+
private generateStats;
|
|
11
|
+
private generateLanguages;
|
|
12
|
+
private generateRepos;
|
|
13
|
+
private generateFooter;
|
|
14
|
+
}
|
|
15
|
+
export declare function updateReadmeMarkers(existingReadme: string, markerSections: MarkerSection[]): string;
|
|
16
|
+
//# sourceMappingURL=generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAEpE,qBAAa,eAAe;IAExB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;gBADJ,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,WAAW;IAG3B,QAAQ,IAAI,MAAM;IAiBlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,aAAa;IA+BrB,OAAO,CAAC,cAAc;CAcvB;AAED,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAAE,GAC9B,MAAM,CAsBR"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReadmeGenerator = void 0;
|
|
4
|
+
exports.updateReadmeMarkers = updateReadmeMarkers;
|
|
5
|
+
class ReadmeGenerator {
|
|
6
|
+
constructor(config, data) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
this.data = data;
|
|
9
|
+
}
|
|
10
|
+
generate() {
|
|
11
|
+
const sections = [];
|
|
12
|
+
sections.push(this.generateHeader());
|
|
13
|
+
sections.push(this.generateIntro());
|
|
14
|
+
if (this.config.sections) {
|
|
15
|
+
for (const section of this.config.sections) {
|
|
16
|
+
sections.push(this.generateSection(section));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
sections.push(this.generateFooter());
|
|
20
|
+
return sections.filter(s => s.trim()).join('\n\n');
|
|
21
|
+
}
|
|
22
|
+
generateHeader() {
|
|
23
|
+
const { user } = this.data;
|
|
24
|
+
return `# Hi there, I'm ${user.name || user.login} 👋
|
|
25
|
+
|
|
26
|
+
<div align="center">
|
|
27
|
+
<img src="${user.avatar_url}" width="150" height="150" alt="${user.login}" style="border-radius: 50%;" />
|
|
28
|
+
</div>`;
|
|
29
|
+
}
|
|
30
|
+
generateIntro() {
|
|
31
|
+
const { intro } = this.config;
|
|
32
|
+
const parts = [];
|
|
33
|
+
if (intro.zh) {
|
|
34
|
+
parts.push(`## 👨💻 关于我
|
|
35
|
+
|
|
36
|
+
${intro.zh}`);
|
|
37
|
+
}
|
|
38
|
+
if (intro.en) {
|
|
39
|
+
parts.push(`## 👨💻 About Me
|
|
40
|
+
|
|
41
|
+
${intro.en}`);
|
|
42
|
+
}
|
|
43
|
+
return parts.join('\n\n');
|
|
44
|
+
}
|
|
45
|
+
generateSection(section) {
|
|
46
|
+
const marker = section.marker || section.type.toUpperCase();
|
|
47
|
+
let content = '';
|
|
48
|
+
switch (section.type) {
|
|
49
|
+
case 'stats':
|
|
50
|
+
content = this.generateStats();
|
|
51
|
+
break;
|
|
52
|
+
case 'languages':
|
|
53
|
+
content = this.generateLanguages();
|
|
54
|
+
break;
|
|
55
|
+
case 'repos':
|
|
56
|
+
content = this.generateRepos();
|
|
57
|
+
break;
|
|
58
|
+
case 'custom':
|
|
59
|
+
content = section.content || '';
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
if (!content)
|
|
63
|
+
return '';
|
|
64
|
+
return `<!--${marker}:START-->
|
|
65
|
+
${section.title ? `## ${section.title}\n\n` : ''}${content}
|
|
66
|
+
<!--${marker}:END-->`;
|
|
67
|
+
}
|
|
68
|
+
generateStats() {
|
|
69
|
+
const { user, totalStars, totalForks } = this.data;
|
|
70
|
+
return `## 📊 GitHub 统计
|
|
71
|
+
|
|
72
|
+
<div align="center">
|
|
73
|
+
|
|
74
|
+
| 统计项 | 数值 |
|
|
75
|
+
|:---:|:---:|
|
|
76
|
+
| 🌟 总 Stars | ${totalStars} |
|
|
77
|
+
| 🍴 总 Forks | ${totalForks} |
|
|
78
|
+
| 📦 公开仓库 | ${user.public_repos} |
|
|
79
|
+
| 👥 关注者 | ${user.followers} |
|
|
80
|
+
| 💫 正在关注 | ${user.following} |
|
|
81
|
+
|
|
82
|
+
</div>`;
|
|
83
|
+
}
|
|
84
|
+
generateLanguages() {
|
|
85
|
+
const { languages } = this.data;
|
|
86
|
+
const sorted = Object.entries(languages)
|
|
87
|
+
.sort(([, a], [, b]) => b - a)
|
|
88
|
+
.slice(0, 8);
|
|
89
|
+
if (sorted.length === 0)
|
|
90
|
+
return '';
|
|
91
|
+
const rows = sorted.map(([lang, count]) => {
|
|
92
|
+
const percentage = ((count / Object.values(languages).reduce((a, b) => a + b, 0)) * 100).toFixed(1);
|
|
93
|
+
return `| ${lang} | ${count} | ${percentage}% |`;
|
|
94
|
+
}).join('\n');
|
|
95
|
+
return `## 💻 编程语言
|
|
96
|
+
|
|
97
|
+
| 语言 | 仓库数 | 占比 |
|
|
98
|
+
|:---|:---:|:---:|
|
|
99
|
+
${rows}`;
|
|
100
|
+
}
|
|
101
|
+
generateRepos() {
|
|
102
|
+
const { repos } = this.data;
|
|
103
|
+
const featured = this.config.featuredRepos || [];
|
|
104
|
+
let displayRepos = repos;
|
|
105
|
+
if (featured.length > 0) {
|
|
106
|
+
displayRepos = repos.filter(r => featured.some(f => r.name === f || r.full_name === f));
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
displayRepos = repos
|
|
110
|
+
.sort((a, b) => b.stargazers_count - a.stargazers_count)
|
|
111
|
+
.slice(0, 6);
|
|
112
|
+
}
|
|
113
|
+
if (displayRepos.length === 0)
|
|
114
|
+
return '';
|
|
115
|
+
const cards = displayRepos.map(repo => {
|
|
116
|
+
const lang = repo.language || 'N/A';
|
|
117
|
+
const desc = repo.description || '暂无描述';
|
|
118
|
+
return `### 📦 [${repo.name}](${repo.html_url})
|
|
119
|
+
${desc}
|
|
120
|
+
|
|
121
|
+
⭐ ${repo.stargazers_count} stars | 🍴 ${repo.forks_count} forks | 📝 ${lang}`;
|
|
122
|
+
}).join('\n\n');
|
|
123
|
+
return `## 🔥 精选项目
|
|
124
|
+
|
|
125
|
+
${cards}`;
|
|
126
|
+
}
|
|
127
|
+
generateFooter() {
|
|
128
|
+
const { updatedAt } = this.data;
|
|
129
|
+
const date = new Date(updatedAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
|
|
130
|
+
return `---
|
|
131
|
+
|
|
132
|
+
<div align="center">
|
|
133
|
+
|
|
134
|
+
*此 README 由 [breathing-github-profile](https://github.com/webywz/breathing-github-profile) 自动生成*
|
|
135
|
+
|
|
136
|
+
*最后更新: ${date} (北京时间)*
|
|
137
|
+
|
|
138
|
+
</div>`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
exports.ReadmeGenerator = ReadmeGenerator;
|
|
142
|
+
function updateReadmeMarkers(existingReadme, markerSections) {
|
|
143
|
+
let updated = existingReadme;
|
|
144
|
+
for (const { marker, content } of markerSections) {
|
|
145
|
+
const startMarker = `<!--${marker}:START-->`;
|
|
146
|
+
const endMarker = `<!--${marker}:END-->`;
|
|
147
|
+
const regex = new RegExp(`${escapeRegex(startMarker)}[\\s\\S]*?${escapeRegex(endMarker)}`, 'g');
|
|
148
|
+
const replacement = `${startMarker}\n${content}\n${endMarker}`;
|
|
149
|
+
if (regex.test(updated)) {
|
|
150
|
+
updated = updated.replace(regex, replacement);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
updated += `\n\n${replacement}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return updated;
|
|
157
|
+
}
|
|
158
|
+
function escapeRegex(str) {
|
|
159
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generator.js","sourceRoot":"","sources":["../src/generator.ts"],"names":[],"mappings":"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"}
|
package/dist/github.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GitHubUser, GitHubRepo, ProfileData } from './types';
|
|
2
|
+
export declare class GitHubClient {
|
|
3
|
+
private token?;
|
|
4
|
+
private baseUrl;
|
|
5
|
+
constructor(token?: string);
|
|
6
|
+
private fetch;
|
|
7
|
+
getUser(username: string): Promise<GitHubUser>;
|
|
8
|
+
getRepos(username: string): Promise<GitHubRepo[]>;
|
|
9
|
+
getProfileData(username: string): Promise<ProfileData>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE9D,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,OAAO,CAA4B;gBAE/B,KAAK,CAAC,EAAE,MAAM;YAIZ,KAAK;IAmBb,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqBjD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CA4B7D"}
|
package/dist/github.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitHubClient = void 0;
|
|
4
|
+
class GitHubClient {
|
|
5
|
+
constructor(token) {
|
|
6
|
+
this.baseUrl = 'https://api.github.com';
|
|
7
|
+
this.token = token || process.env.GITHUB_TOKEN;
|
|
8
|
+
}
|
|
9
|
+
async fetch(endpoint) {
|
|
10
|
+
const headers = {
|
|
11
|
+
'Accept': 'application/vnd.github.v3+json',
|
|
12
|
+
'User-Agent': 'breathing-github-profile'
|
|
13
|
+
};
|
|
14
|
+
if (this.token) {
|
|
15
|
+
headers['Authorization'] = `token ${this.token}`;
|
|
16
|
+
}
|
|
17
|
+
const response = await fetch(`${this.baseUrl}${endpoint}`, { headers });
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(`GitHub API 错误: ${response.status} ${response.statusText}`);
|
|
20
|
+
}
|
|
21
|
+
return response.json();
|
|
22
|
+
}
|
|
23
|
+
async getUser(username) {
|
|
24
|
+
return this.fetch(`/users/${username}`);
|
|
25
|
+
}
|
|
26
|
+
async getRepos(username) {
|
|
27
|
+
const repos = [];
|
|
28
|
+
let page = 1;
|
|
29
|
+
const perPage = 100;
|
|
30
|
+
const maxPages = 10;
|
|
31
|
+
while (page <= maxPages) {
|
|
32
|
+
const batch = await this.fetch(`/users/${username}/repos?per_page=${perPage}&page=${page}&sort=updated`);
|
|
33
|
+
if (batch.length === 0)
|
|
34
|
+
break;
|
|
35
|
+
repos.push(...batch);
|
|
36
|
+
if (batch.length < perPage)
|
|
37
|
+
break;
|
|
38
|
+
page++;
|
|
39
|
+
}
|
|
40
|
+
return repos.filter(repo => !repo.fork);
|
|
41
|
+
}
|
|
42
|
+
async getProfileData(username) {
|
|
43
|
+
const [user, repos] = await Promise.all([
|
|
44
|
+
this.getUser(username),
|
|
45
|
+
this.getRepos(username)
|
|
46
|
+
]);
|
|
47
|
+
const languages = {};
|
|
48
|
+
let totalStars = 0;
|
|
49
|
+
let totalForks = 0;
|
|
50
|
+
for (const repo of repos) {
|
|
51
|
+
totalStars += repo.stargazers_count;
|
|
52
|
+
totalForks += repo.forks_count;
|
|
53
|
+
if (repo.language) {
|
|
54
|
+
languages[repo.language] = (languages[repo.language] || 0) + 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
user,
|
|
59
|
+
repos,
|
|
60
|
+
languages,
|
|
61
|
+
totalStars,
|
|
62
|
+
totalForks,
|
|
63
|
+
updatedAt: new Date().toISOString()
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.GitHubClient = GitHubClient;
|
|
68
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":";;;AAEA,MAAa,YAAY;IAIvB,YAAY,KAAc;QAFlB,YAAO,GAAG,wBAAwB,CAAC;QAGzC,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACjD,CAAC;IAEO,KAAK,CAAC,KAAK,CAAI,QAAgB;QACrC,MAAM,OAAO,GAA2B;YACtC,QAAQ,EAAE,gCAAgC;YAC1C,YAAY,EAAE,0BAA0B;SACzC,CAAC;QAEF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,eAAe,CAAC,GAAG,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;QACnD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAExE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,kBAAkB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9E,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,KAAK,CAAa,UAAU,QAAQ,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,MAAM,KAAK,GAAiB,EAAE,CAAC;QAC/B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,CAAC;QACpB,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,OAAO,IAAI,IAAI,QAAQ,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAC5B,UAAU,QAAQ,mBAAmB,OAAO,SAAS,IAAI,eAAe,CACzE,CAAC;YAEF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM;YAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;YAErB,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO;gBAAE,MAAM;YAClC,IAAI,EAAE,CAAC;QACT,CAAC;QAED,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACtC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YACtB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;SACxB,CAAC,CAAC;QAEH,MAAM,SAAS,GAA2B,EAAE,CAAC;QAC7C,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,UAAU,GAAG,CAAC,CAAC;QAEnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,UAAU,IAAI,IAAI,CAAC,gBAAgB,CAAC;YACpC,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC;YAE/B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI;YACJ,KAAK;YACL,SAAS;YACT,UAAU;YACV,UAAU;YACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;IACJ,CAAC;CACF;AAhFD,oCAgFC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { ProfileConfig, ProfileData, GitHubUser, GitHubRepo, Section, StyleConfig } from './types';
|
|
2
|
+
export { loadConfig, validateConfig, getDefaultConfig } from './config';
|
|
3
|
+
export { GitHubClient } from './github';
|
|
4
|
+
export { ReadmeGenerator, updateReadmeMarkers } from './generator';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACnG,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateReadmeMarkers = exports.ReadmeGenerator = exports.GitHubClient = exports.getDefaultConfig = exports.validateConfig = exports.loadConfig = void 0;
|
|
4
|
+
var config_1 = require("./config");
|
|
5
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_1.loadConfig; } });
|
|
6
|
+
Object.defineProperty(exports, "validateConfig", { enumerable: true, get: function () { return config_1.validateConfig; } });
|
|
7
|
+
Object.defineProperty(exports, "getDefaultConfig", { enumerable: true, get: function () { return config_1.getDefaultConfig; } });
|
|
8
|
+
var github_1 = require("./github");
|
|
9
|
+
Object.defineProperty(exports, "GitHubClient", { enumerable: true, get: function () { return github_1.GitHubClient; } });
|
|
10
|
+
var generator_1 = require("./generator");
|
|
11
|
+
Object.defineProperty(exports, "ReadmeGenerator", { enumerable: true, get: function () { return generator_1.ReadmeGenerator; } });
|
|
12
|
+
Object.defineProperty(exports, "updateReadmeMarkers", { enumerable: true, get: function () { return generator_1.updateReadmeMarkers; } });
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,mCAAwE;AAA/D,oGAAA,UAAU,OAAA;AAAE,wGAAA,cAAc,OAAA;AAAE,0GAAA,gBAAgB,OAAA;AACrD,mCAAwC;AAA/B,sGAAA,YAAY,OAAA;AACrB,yCAAmE;AAA1D,4GAAA,eAAe,OAAA;AAAE,gHAAA,mBAAmB,OAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface ProfileConfig {
|
|
2
|
+
username: string;
|
|
3
|
+
intro: {
|
|
4
|
+
zh?: string;
|
|
5
|
+
en?: string;
|
|
6
|
+
};
|
|
7
|
+
featuredRepos?: string[];
|
|
8
|
+
sections?: Section[];
|
|
9
|
+
style?: StyleConfig;
|
|
10
|
+
}
|
|
11
|
+
export interface Section {
|
|
12
|
+
type: 'stats' | 'languages' | 'repos' | 'custom';
|
|
13
|
+
title?: string;
|
|
14
|
+
content?: string;
|
|
15
|
+
marker?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface StyleConfig {
|
|
18
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
19
|
+
icons?: boolean;
|
|
20
|
+
badges?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface GitHubUser {
|
|
23
|
+
login: string;
|
|
24
|
+
name: string;
|
|
25
|
+
bio: string;
|
|
26
|
+
public_repos: number;
|
|
27
|
+
followers: number;
|
|
28
|
+
following: number;
|
|
29
|
+
created_at: string;
|
|
30
|
+
avatar_url: string;
|
|
31
|
+
html_url: string;
|
|
32
|
+
location?: string;
|
|
33
|
+
blog?: string;
|
|
34
|
+
twitter_username?: string;
|
|
35
|
+
company?: string;
|
|
36
|
+
}
|
|
37
|
+
export interface GitHubRepo {
|
|
38
|
+
name: string;
|
|
39
|
+
full_name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
html_url: string;
|
|
42
|
+
homepage: string;
|
|
43
|
+
stargazers_count: number;
|
|
44
|
+
forks_count: number;
|
|
45
|
+
language: string;
|
|
46
|
+
topics: string[];
|
|
47
|
+
created_at: string;
|
|
48
|
+
updated_at: string;
|
|
49
|
+
pushed_at: string;
|
|
50
|
+
size: number;
|
|
51
|
+
watchers_count: number;
|
|
52
|
+
open_issues_count: number;
|
|
53
|
+
archived: boolean;
|
|
54
|
+
fork: boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface ProfileData {
|
|
57
|
+
user: GitHubUser;
|
|
58
|
+
repos: GitHubRepo[];
|
|
59
|
+
languages: Record<string, number>;
|
|
60
|
+
totalStars: number;
|
|
61
|
+
totalForks: number;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
}
|
|
64
|
+
export interface MarkerSection {
|
|
65
|
+
marker: string;
|
|
66
|
+
content: string;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,EAAE,CAAC,EAAE,MAAM,CAAC;KACb,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# 示例和演示
|
|
2
|
+
|
|
3
|
+
本目录包含使用 breathing-github-profile 的示例配置。
|
|
4
|
+
|
|
5
|
+
## 📄 webywz.yml
|
|
6
|
+
|
|
7
|
+
完整的配置示例,展示所有可用功能:
|
|
8
|
+
|
|
9
|
+
- ✅ 中英文双语介绍
|
|
10
|
+
- ✅ 精选仓库列表
|
|
11
|
+
- ✅ 多种章节类型(统计、语言、项目)
|
|
12
|
+
- ✅ 自定义内容(技术栈徽章)
|
|
13
|
+
- ✅ 样式配置
|
|
14
|
+
|
|
15
|
+
## 🚀 快速测试
|
|
16
|
+
|
|
17
|
+
### 1. 验证配置
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run validate -- -c examples/webywz.yml
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
预期输出:
|
|
24
|
+
```
|
|
25
|
+
✓ 配置文件有效
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 2. 生成 README(演示模式)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 生成到临时文件
|
|
32
|
+
npm run generate -- -c examples/webywz.yml -o examples/test-output.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 3. 测试刷新功能
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# 首先生成一个 README
|
|
39
|
+
npm run generate -- -c examples/webywz.yml -o examples/demo.md
|
|
40
|
+
|
|
41
|
+
# 手动编辑 demo.md,在标记外添加自定义内容
|
|
42
|
+
|
|
43
|
+
# 刷新(只更新标记部分)
|
|
44
|
+
npm run refresh -- -c examples/webywz.yml -r examples/demo.md
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
你会发现自定义内容被保留,只有标记部分被更新!
|
|
48
|
+
|
|
49
|
+
## 📝 创建你自己的配置
|
|
50
|
+
|
|
51
|
+
1. 复制 `webywz.yml` 作为模板
|
|
52
|
+
2. 修改 `username` 为你的 GitHub 用户名
|
|
53
|
+
3. 更新 `intro` 中的介绍
|
|
54
|
+
4. 根据需要调整 `sections`
|
|
55
|
+
5. 运行 `npm run generate` 生成 README
|
|
56
|
+
|
|
57
|
+
## 🔧 配置选项参考
|
|
58
|
+
|
|
59
|
+
### 章节类型
|
|
60
|
+
|
|
61
|
+
#### stats
|
|
62
|
+
显示 GitHub 统计信息
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
- type: stats
|
|
66
|
+
marker: STATS
|
|
67
|
+
title: 📊 我的统计
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### languages
|
|
71
|
+
显示编程语言分布
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
- type: languages
|
|
75
|
+
marker: LANGUAGES
|
|
76
|
+
title: 💻 技术栈
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### repos
|
|
80
|
+
显示精选项目
|
|
81
|
+
|
|
82
|
+
```yaml
|
|
83
|
+
- type: repos
|
|
84
|
+
marker: REPOS
|
|
85
|
+
title: 🔥 热门项目
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### custom
|
|
89
|
+
自定义 Markdown 内容
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
- type: custom
|
|
93
|
+
marker: BADGES
|
|
94
|
+
title: 🎯 技能徽章
|
|
95
|
+
content: |
|
|
96
|
+

|
|
97
|
+

|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## 💡 提示
|
|
101
|
+
|
|
102
|
+
1. **标记名称**: 确保每个章节的 `marker` 唯一
|
|
103
|
+
2. **GitHub Token**: 设置 `GITHUB_TOKEN` 环境变量以避免 API 速率限制
|
|
104
|
+
3. **精选仓库**: 使用 `featuredRepos` 手动选择要展示的项目
|
|
105
|
+
4. **自定义样式**: 在 `custom` 章节中使用 HTML 和 Markdown
|
|
106
|
+
|
|
107
|
+
## 🌟 实际案例
|
|
108
|
+
|
|
109
|
+
使用此工具的 Profile README:
|
|
110
|
+
|
|
111
|
+
- [webywz/webywz](https://github.com/webywz/webywz) - 配套的 profile 仓库
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
有问题?查看 [主文档](../README.md) 或提交 [issue](https://github.com/webywz/breathing-github-profile/issues)。
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
username: octocat
|
|
2
|
+
|
|
3
|
+
intro:
|
|
4
|
+
zh: |
|
|
5
|
+
👋 你好!我是 Octocat
|
|
6
|
+
|
|
7
|
+
GitHub 的吉祥物,开源爱好者
|
|
8
|
+
|
|
9
|
+
en: |
|
|
10
|
+
👋 Hi! I'm Octocat
|
|
11
|
+
|
|
12
|
+
GitHub's mascot and open source enthusiast
|
|
13
|
+
|
|
14
|
+
sections:
|
|
15
|
+
- type: stats
|
|
16
|
+
marker: STATS
|
|
17
|
+
title: 📊 统计数据
|
|
18
|
+
|
|
19
|
+
- type: languages
|
|
20
|
+
marker: LANGUAGES
|
|
21
|
+
title: 💻 编程语言
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
username: webywz
|
|
2
|
+
|
|
3
|
+
intro:
|
|
4
|
+
zh: |
|
|
5
|
+
🚀 全栈开发者 | AI 爱好者 | 开源贡献者
|
|
6
|
+
|
|
7
|
+
💡 专注于现代 Web 开发和人工智能技术
|
|
8
|
+
- 🔧 后端:Node.js (NestJS) / Python (FastAPI)
|
|
9
|
+
- 🎨 前端:React / Vue / TypeScript
|
|
10
|
+
- 🤖 AI:LangChain / Prompt Engineering
|
|
11
|
+
- 🛠 工具:GitHub Actions / Docker / Cloudflare
|
|
12
|
+
|
|
13
|
+
📫 欢迎交流合作!
|
|
14
|
+
|
|
15
|
+
en: |
|
|
16
|
+
🚀 Full-stack Developer | AI Enthusiast | Open Source Contributor
|
|
17
|
+
|
|
18
|
+
💡 Focus on Modern Web Development and AI Technologies
|
|
19
|
+
- 🔧 Backend: Node.js (NestJS) / Python (FastAPI)
|
|
20
|
+
- 🎨 Frontend: React / Vue / TypeScript
|
|
21
|
+
- 🤖 AI: LangChain / Prompt Engineering
|
|
22
|
+
- 🛠 Tools: GitHub Actions / Docker / Cloudflare
|
|
23
|
+
|
|
24
|
+
📫 Let's connect and collaborate!
|
|
25
|
+
|
|
26
|
+
featuredRepos:
|
|
27
|
+
- breathing-github-profile
|
|
28
|
+
- webywz
|
|
29
|
+
|
|
30
|
+
sections:
|
|
31
|
+
- type: stats
|
|
32
|
+
marker: STATS
|
|
33
|
+
title: 📊 GitHub 统计
|
|
34
|
+
|
|
35
|
+
- type: languages
|
|
36
|
+
marker: LANGUAGES
|
|
37
|
+
title: 💻 常用语言
|
|
38
|
+
|
|
39
|
+
- type: repos
|
|
40
|
+
marker: REPOS
|
|
41
|
+
title: 🔥 精选项目
|
|
42
|
+
|
|
43
|
+
- type: custom
|
|
44
|
+
marker: TECH_STACK
|
|
45
|
+
title: 🛠 技术栈
|
|
46
|
+
content: |
|
|
47
|
+
### 后端开发
|
|
48
|
+

|
|
49
|
+

|
|
50
|
+

|
|
51
|
+

|
|
52
|
+
|
|
53
|
+
### 前端开发
|
|
54
|
+

|
|
55
|
+

|
|
56
|
+

|
|
57
|
+
|
|
58
|
+
### AI & 工具
|
|
59
|
+

|
|
60
|
+

|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
style:
|
|
64
|
+
theme: auto
|
|
65
|
+
icons: true
|
|
66
|
+
badges: true
|
package/package.json
CHANGED
|
@@ -1,6 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webywz/breathing-github-profile",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "可复用的活跃 GitHub profile README 生成器,支持每日自动刷新",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"breathing-profile": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc && node -e \"require('fs').chmodSync('dist/cli.js', 0o755)\"",
|
|
12
|
+
"dev": "tsc --watch",
|
|
13
|
+
"test": "jest",
|
|
14
|
+
"test:watch": "jest --watch",
|
|
15
|
+
"refresh": "tsx src/cli.ts refresh",
|
|
16
|
+
"generate": "tsx src/cli.ts generate",
|
|
17
|
+
"validate": "tsx src/cli.ts validate",
|
|
18
|
+
"lint": "eslint src --ext .ts",
|
|
19
|
+
"prepare": "npm run build",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"github",
|
|
24
|
+
"profile",
|
|
25
|
+
"readme",
|
|
26
|
+
"generator",
|
|
27
|
+
"automation"
|
|
28
|
+
],
|
|
29
|
+
"author": "webywz",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"examples"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"yaml": "^2.3.4",
|
|
37
|
+
"commander": "^11.1.0",
|
|
38
|
+
"chalk": "^4.1.2",
|
|
39
|
+
"ora": "^5.4.1"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^20.10.5",
|
|
43
|
+
"@types/jest": "^29.5.11",
|
|
44
|
+
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
45
|
+
"@typescript-eslint/parser": "^6.15.0",
|
|
46
|
+
"eslint": "^8.56.0",
|
|
47
|
+
"jest": "^29.7.0",
|
|
48
|
+
"ts-jest": "^29.1.1",
|
|
49
|
+
"typescript": "^5.3.3",
|
|
50
|
+
"tsx": "^4.7.0"
|
|
51
|
+
},
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=16.0.0"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/webywz/breathing-github-profile.git"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://github.com/webywz/breathing-github-profile#readme",
|
|
63
|
+
"bugs": {
|
|
64
|
+
"url": "https://github.com/webywz/breathing-github-profile/issues"
|
|
65
|
+
}
|
|
66
|
+
}
|