heyq02 0.2.5 → 0.2.7
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/dist/cli.js +30 -258
- package/package.json +5 -2
package/dist/cli.js
CHANGED
|
@@ -1,274 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { Marked } from "marked";
|
|
3
|
+
import { markedTerminal } from "marked-terminal";
|
|
4
|
+
|
|
2
5
|
// package.json
|
|
3
|
-
var version = "0.2.
|
|
6
|
+
var version = "0.2.7";
|
|
4
7
|
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
city: "China",
|
|
11
|
-
bio: "Full-stack engineer / open-source enthusiast / vlogger on career. Focused on AI that speeds up development and ships in real products",
|
|
12
|
-
kaomoji: "(๑•̀ㅂ•́)و",
|
|
13
|
-
avatar: "https://avatars.githubusercontent.com/u/206218794?v=4",
|
|
14
|
-
site: "https://heyq02.com",
|
|
15
|
-
kicker: "PROFILE",
|
|
16
|
-
title: "Ari He",
|
|
17
|
-
description: "Ari He. Full-stack engineer, open-source enthusiast, and vlogger on career. Focused on AI that speeds up development and ships in real products.",
|
|
18
|
-
contact: {
|
|
19
|
-
"phone": "+86 135****8086",
|
|
20
|
-
"email": "hello@heyq02.com"
|
|
21
|
-
},
|
|
22
|
-
sections: {
|
|
23
|
-
"experience": "Experience",
|
|
24
|
-
"skills": "Skills",
|
|
25
|
-
"openSource": "Open source"
|
|
26
|
-
},
|
|
27
|
-
places: [
|
|
28
|
-
{
|
|
29
|
-
"label": "GitHub",
|
|
30
|
-
"href": "https://github.com/heyq02",
|
|
31
|
-
"detail": "heyq02"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"label": "Bluesky",
|
|
35
|
-
"href": "https://bsky.app/profile/heyq02.com",
|
|
36
|
-
"detail": "heyq02.com"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"label": "Bilibili",
|
|
40
|
-
"href": "https://space.bilibili.com/3493273159075938",
|
|
41
|
-
"detail": "全栈糕手Ari"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"label": "Juejin",
|
|
45
|
-
"href": "https://juejin.cn/user/708557910842296",
|
|
46
|
-
"detail": "编程糕手Ari"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"label": "WeChat",
|
|
50
|
-
"href": "/wechat.jpg",
|
|
51
|
-
"detail": "Scan to add"
|
|
52
|
-
}
|
|
53
|
-
],
|
|
54
|
-
experiences: [{
|
|
55
|
-
"company": "JD.com, Inc.",
|
|
56
|
-
"href": "https://www.jd.com/",
|
|
57
|
-
"start": "2024.06",
|
|
58
|
-
"end": "Present",
|
|
59
|
-
"points": [
|
|
60
|
-
"Owned iterations for JD Takeout across the mini program, H5, and admin console",
|
|
61
|
-
"Upgraded the admin console off its legacy architecture and improved TP95",
|
|
62
|
-
"Built C3-level AI Infra for Local Life product and engineering, improving R&D efficiency"
|
|
63
|
-
]
|
|
64
|
-
}],
|
|
65
|
-
skills: [
|
|
66
|
-
{
|
|
67
|
-
"name": "Vue",
|
|
68
|
-
"href": "https://vuejs.org/",
|
|
69
|
-
"summary": "Progressive JavaScript framework for building web UIs"
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
"name": "React",
|
|
73
|
-
"href": "https://react.dev/",
|
|
74
|
-
"summary": "The library for web and native user interfaces"
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
"name": "Next",
|
|
78
|
-
"href": "https://nextjs.org/",
|
|
79
|
-
"summary": "The React framework for the web"
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
"name": "Rolldown",
|
|
83
|
-
"href": "https://rolldown.rs/",
|
|
84
|
-
"summary": "Rust-based JavaScript bundler with a Rollup-compatible API"
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"name": "Vite",
|
|
88
|
-
"href": "https://vite.dev/",
|
|
89
|
-
"summary": "Frontend build tool for the web"
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
"name": "Oxc",
|
|
93
|
-
"href": "https://oxc.rs/",
|
|
94
|
-
"summary": "High-performance JavaScript tools written in Rust"
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
"name": "Spring",
|
|
98
|
-
"href": "https://spring.io/",
|
|
99
|
-
"summary": "Framework for creating Java enterprise applications"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"name": "Redis",
|
|
103
|
-
"href": "https://redis.io/",
|
|
104
|
-
"summary": "In-memory store for databases, cache, and messaging"
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
"name": "RabbitMQ",
|
|
108
|
-
"href": "https://www.rabbitmq.com/",
|
|
109
|
-
"summary": "Open-source messaging and streaming broker"
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
"name": "Nginx",
|
|
113
|
-
"href": "https://nginx.org/",
|
|
114
|
-
"summary": "HTTP server, reverse proxy, and load balancer"
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
"name": "Docker",
|
|
118
|
-
"href": "https://www.docker.com/",
|
|
119
|
-
"summary": "Open platform for building, shipping, and running apps"
|
|
120
|
-
}
|
|
121
|
-
],
|
|
122
|
-
projects: [{
|
|
123
|
-
"name": "jd-opensource/taro-ui",
|
|
124
|
-
"href": "https://github.com/jd-opensource/taro-ui",
|
|
125
|
-
"summary": "一款基于 Taro 框架开发的多端 UI 组件库",
|
|
126
|
-
"language": "TypeScript",
|
|
127
|
-
"languageColor": "#3178c6",
|
|
128
|
-
"stars": 4730,
|
|
129
|
-
"forks": 743
|
|
130
|
-
}, {
|
|
131
|
-
"name": "simpleicons.dev",
|
|
132
|
-
"href": "https://github.com/heyq02/simpleicons.dev",
|
|
133
|
-
"summary": "Showcase your skills on your GitHub readme or resumé with ease.",
|
|
134
|
-
"language": "TypeScript",
|
|
135
|
-
"languageColor": "#3178c6",
|
|
136
|
-
"stars": 171,
|
|
137
|
-
"forks": 0
|
|
138
|
-
}]
|
|
139
|
-
};
|
|
140
|
-
var intro_zh_default = {
|
|
141
|
-
alias: "开发者",
|
|
142
|
-
degree: "学士",
|
|
143
|
-
city: "中国",
|
|
144
|
-
bio: "全栈工程师 / 开源爱好者 / 职业向视频创作者。专注于能加速研发并落地到真实产品中的 AI",
|
|
145
|
-
kicker: "简介",
|
|
146
|
-
description: "Ari He。全栈工程师、开源爱好者、职业向视频创作者。专注于能加速研发并落地到真实产品中的 AI。",
|
|
147
|
-
sections: {
|
|
148
|
-
"experience": "经历",
|
|
149
|
-
"skills": "技能",
|
|
150
|
-
"openSource": "开源"
|
|
151
|
-
},
|
|
152
|
-
places: [
|
|
153
|
-
{ "detail": "heyq02" },
|
|
154
|
-
{ "detail": "heyq02.com" },
|
|
155
|
-
{ "detail": "全栈糕手Ari" },
|
|
156
|
-
{ "detail": "编程糕手Ari" },
|
|
157
|
-
{ "detail": "扫码添加" }
|
|
158
|
-
],
|
|
159
|
-
experiences: [{
|
|
160
|
-
"company": "京东集团",
|
|
161
|
-
"end": "至今",
|
|
162
|
-
"points": [
|
|
163
|
-
"负责京东外卖小程序、H5 与管理后台的迭代交付",
|
|
164
|
-
"推动管理后台脱离旧架构升级,并提升 TP95",
|
|
165
|
-
"搭建本地生活产研 C3 级 AI Infra,提升研发效率"
|
|
166
|
-
]
|
|
167
|
-
}],
|
|
168
|
-
skills: [
|
|
169
|
-
{ "summary": "渐进式 JavaScript 框架,用于构建 Web 界面" },
|
|
170
|
-
{ "summary": "用于构建 Web 与原生用户界面的库" },
|
|
171
|
-
{ "summary": "面向 Web 的 React 框架" },
|
|
172
|
-
{ "summary": "兼容 Rollup API 的 Rust 版 JavaScript 打包器" },
|
|
173
|
-
{ "summary": "面向 Web 的前端构建工具" },
|
|
174
|
-
{ "summary": "用 Rust 编写的高性能 JavaScript 工具集" },
|
|
175
|
-
{ "summary": "用于构建 Java 企业应用的框架" },
|
|
176
|
-
{ "summary": "内存数据库,可用于缓存与消息" },
|
|
177
|
-
{ "summary": "开源消息与流式代理" },
|
|
178
|
-
{ "summary": "HTTP 服务器、反向代理与负载均衡器" },
|
|
179
|
-
{ "summary": "构建、交付与运行应用的开放平台" }
|
|
180
|
-
],
|
|
181
|
-
projects: [{ "summary": "一款基于 Taro 框架开发的多端 UI 组件库" }, { "summary": "轻松在 GitHub README 或简历中展示你的技能图标。" }]
|
|
182
|
-
};
|
|
183
|
-
/** Shared intro SSOT from `static/data/intro.json` for site, cli, and readme. */
|
|
184
|
-
const intro = intro_default;
|
|
185
|
-
const chinese = intro_zh_default;
|
|
186
|
-
function zip(label, base, overlay, merge) {
|
|
187
|
-
if (base.length !== overlay.length) throw new Error(`Chinese ${label} (${overlay.length}) must match English (${base.length})`);
|
|
188
|
-
return base.map((item, index) => merge(item, overlay[index]));
|
|
189
|
-
}
|
|
190
|
-
function mergeIntro(english, overlay) {
|
|
191
|
-
return {
|
|
192
|
-
...english,
|
|
193
|
-
names: [english.name, overlay.alias],
|
|
194
|
-
degree: overlay.degree,
|
|
195
|
-
city: overlay.city,
|
|
196
|
-
bio: overlay.bio,
|
|
197
|
-
kicker: overlay.kicker,
|
|
198
|
-
description: overlay.description,
|
|
199
|
-
sections: overlay.sections,
|
|
200
|
-
places: zip("places", english.places, overlay.places, (place, extra) => ({
|
|
201
|
-
...place,
|
|
202
|
-
detail: extra.detail
|
|
203
|
-
})),
|
|
204
|
-
experiences: zip("experiences", english.experiences, overlay.experiences, (job, extra) => ({
|
|
205
|
-
...job,
|
|
206
|
-
company: extra.company,
|
|
207
|
-
end: extra.end,
|
|
208
|
-
points: extra.points
|
|
209
|
-
})),
|
|
210
|
-
skills: zip("skills", english.skills, overlay.skills, (skill, extra) => ({
|
|
211
|
-
...skill,
|
|
212
|
-
summary: extra.summary
|
|
213
|
-
})),
|
|
214
|
-
projects: zip("projects", english.projects, overlay.projects, (project, extra) => ({
|
|
215
|
-
...project,
|
|
216
|
-
summary: extra.summary
|
|
217
|
-
}))
|
|
218
|
-
};
|
|
8
|
+
// src/readme.ts
|
|
9
|
+
const README_URL = "https://raw.githubusercontent.com/heyq02/heyq02/main/README.md";
|
|
10
|
+
const README_TIMEOUT_MS = 1e4;
|
|
11
|
+
function errorText(error) {
|
|
12
|
+
return error instanceof Error ? error.message : String(error);
|
|
219
13
|
}
|
|
220
|
-
const
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
|
|
14
|
+
const marked = new Marked(markedTerminal());
|
|
15
|
+
async function fetchReadme(fetchImpl = globalThis.fetch, url = README_URL) {
|
|
16
|
+
let response;
|
|
17
|
+
try {
|
|
18
|
+
response = await fetchImpl(url, { signal: AbortSignal.timeout(README_TIMEOUT_MS) });
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw new Error(`Failed to fetch README: ${errorText(error)}`, { cause: error });
|
|
21
|
+
}
|
|
22
|
+
if (!response.ok) throw new Error(`Failed to fetch README: ${response.status} ${response.statusText}`);
|
|
23
|
+
return response.text();
|
|
224
24
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
href: absoluteHref(place.href)
|
|
228
|
-
}));
|
|
229
|
-
const skills = intro.skills.map((skill) => ({
|
|
230
|
-
...skill,
|
|
231
|
-
href: absoluteHref(skill.href)
|
|
232
|
-
}));
|
|
233
|
-
const { name, names, degree, city, bio, kaomoji, avatar, site, kicker, title, description, contact, sections, experiences, projects } = intro;
|
|
234
|
-
/** Terminal-oriented view of the same intro. */
|
|
235
|
-
const profile = {
|
|
236
|
-
name: intro.name,
|
|
237
|
-
givenNames: intro.names,
|
|
238
|
-
role: "",
|
|
239
|
-
bio: `${intro.bio} ${intro.kaomoji}`,
|
|
240
|
-
phone: intro.contact.phone,
|
|
241
|
-
email: intro.contact.email,
|
|
242
|
-
site: intro.site,
|
|
243
|
-
places,
|
|
244
|
-
experiences: intro.experiences,
|
|
245
|
-
skills,
|
|
246
|
-
projects: intro.projects.map(({ languageColor: _languageColor, ...project }) => project)
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
// src/intro.ts
|
|
250
|
-
function renderIntro() {
|
|
251
|
-
const lines = [
|
|
252
|
-
`Hello, I'm ${intro.name}`,
|
|
253
|
-
"",
|
|
254
|
-
intro.sections.experience,
|
|
255
|
-
""
|
|
256
|
-
];
|
|
257
|
-
for (const job of intro.experiences) lines.push(`${job.company} · ${job.start} – ${job.end}`, ...job.points.map((point) => `- ${point}`), "");
|
|
258
|
-
lines.push(intro.sections.skills, "", intro.skills.map((skill) => skill.name).join(" · "));
|
|
259
|
-
return lines.join("\n");
|
|
25
|
+
async function renderPreview(markdown) {
|
|
26
|
+
return `${(await marked.parse(markdown)).trimEnd()}\n`;
|
|
260
27
|
}
|
|
261
28
|
|
|
262
29
|
// src/main.ts
|
|
263
30
|
const help = `Usage: heyq02
|
|
264
31
|
|
|
265
|
-
|
|
32
|
+
Fetch and print the GitHub README.
|
|
266
33
|
|
|
267
34
|
Options:
|
|
268
35
|
-h, --help Show help
|
|
269
36
|
-v, --version Show version
|
|
270
37
|
`;
|
|
271
|
-
function main(argv = process.argv.slice(2)) {
|
|
38
|
+
async function main(argv = process.argv.slice(2)) {
|
|
272
39
|
const arg = argv[0];
|
|
273
40
|
if (arg === "-h" || arg === "--help") {
|
|
274
41
|
process.stdout.write(help);
|
|
@@ -283,12 +50,17 @@ function main(argv = process.argv.slice(2)) {
|
|
|
283
50
|
process.exitCode = 1;
|
|
284
51
|
return;
|
|
285
52
|
}
|
|
286
|
-
|
|
53
|
+
try {
|
|
54
|
+
process.stdout.write(await renderPreview(await fetchReadme()));
|
|
55
|
+
} catch (error) {
|
|
56
|
+
process.stderr.write(`${errorText(error)}\n`);
|
|
57
|
+
process.exitCode = 1;
|
|
58
|
+
}
|
|
287
59
|
}
|
|
288
60
|
|
|
289
61
|
// src/cli.ts
|
|
290
62
|
try {
|
|
291
|
-
main();
|
|
63
|
+
await main();
|
|
292
64
|
} catch (error) {
|
|
293
65
|
const message = error instanceof Error ? error.message : String(error);
|
|
294
66
|
process.stderr.write(`${message}\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heyq02",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"description": "Ari He. A terminal introduction.",
|
|
5
5
|
"homepage": "https://heyq02.com",
|
|
6
6
|
"bugs": {
|
|
@@ -27,8 +27,11 @@
|
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"marked": "^13.0.3",
|
|
32
|
+
"marked-terminal": "^8.0.0"
|
|
33
|
+
},
|
|
30
34
|
"devDependencies": {
|
|
31
|
-
"@heyq02/profile": "0.2.5",
|
|
32
35
|
"@liangmi/vp-config": "^1.0.0",
|
|
33
36
|
"@types/node": "^26.6.5",
|
|
34
37
|
"typescript": "7.0.2",
|