heyq02 0.0.0-stage → 0.1.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/README.md +15 -2
- package/dist/b.js +165 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +304 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.js +1 -0
- package/package.json +75 -3
package/README.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
<h1>Hello, I'm 永琪(Ari)</h1>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## 经历
|
|
4
|
+
|
|
5
|
+
**[北京京东世纪贸易有限公司](https://www.jd.com/)** · 2024.06 – 至今
|
|
6
|
+
|
|
7
|
+
- 负责京东外卖跨端小程序&H5、管理后台需求迭代
|
|
8
|
+
- 进行管理后台老旧架构升级,TP95性能优化
|
|
9
|
+
- 本地生活产研C3层面 AI Infra 建设,提升研发效能
|
|
10
|
+
|
|
11
|
+
## 技能
|
|
12
|
+
|
|
13
|
+
<picture>
|
|
14
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://simpleicons.dev/icons?icons=vuedotjs,react,nextdotjs,rolldown,vite,oxc,spring,redis,rabbitmq,nginx,docker&perline=11&theme=dark" />
|
|
15
|
+
<img width="100%" alt="Vue、React、Next、Rolldown、Vite、Oxc、Spring、Redis、RabbitMQ、Nginx、Docker" src="https://simpleicons.dev/icons?icons=vuedotjs,react,nextdotjs,rolldown,vite,oxc,spring,redis,rabbitmq,nginx,docker&perline=11&theme=light" />
|
|
16
|
+
</picture>
|
package/dist/b.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const site = 'https://intro.heyq02.com';
|
|
2
|
+
const profile = {
|
|
3
|
+
name: '永琪(Ari)',
|
|
4
|
+
givenNames: [
|
|
5
|
+
'永琪',
|
|
6
|
+
'Ari'
|
|
7
|
+
],
|
|
8
|
+
role: ',全栈研发',
|
|
9
|
+
bio: '南京邮电大学生物医学工程本科毕业。专注前端工程化,推动 AI 在业务场景中落地。',
|
|
10
|
+
quote: 'everything always works out at the end',
|
|
11
|
+
phone: '+86 135****8086',
|
|
12
|
+
email: 'hello@heyq02.com',
|
|
13
|
+
site: site,
|
|
14
|
+
places: [
|
|
15
|
+
{
|
|
16
|
+
label: 'GitHub',
|
|
17
|
+
href: 'https://github.com/heyq02',
|
|
18
|
+
detail: 'heyq02'
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: 'X',
|
|
22
|
+
href: 'https://x.com/heyq02',
|
|
23
|
+
detail: '@heyq02'
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: 'Bilibili',
|
|
27
|
+
href: 'https://space.bilibili.com/3493273159075938',
|
|
28
|
+
detail: '全栈糕手Ari'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
label: '掘金',
|
|
32
|
+
href: 'https://juejin.cn/user/708557910842296',
|
|
33
|
+
detail: '编程糕手Ari'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: '微信',
|
|
37
|
+
href: `${site}/wechat.jpg`,
|
|
38
|
+
detail: '扫码添加'
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
experiences: [
|
|
42
|
+
{
|
|
43
|
+
company: '北京京东世纪贸易有限公司',
|
|
44
|
+
href: 'https://www.jd.com/',
|
|
45
|
+
start: '2024.06',
|
|
46
|
+
end: '至今',
|
|
47
|
+
points: [
|
|
48
|
+
'负责京东外卖跨端小程序&H5、管理后台需求迭代',
|
|
49
|
+
'进行管理后台老旧架构升级,TP95性能优化',
|
|
50
|
+
'本地生活产研C3层面 AI Infra 建设,提升研发效能'
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
skills: [
|
|
55
|
+
{
|
|
56
|
+
name: 'Vue',
|
|
57
|
+
href: 'https://vuejs.org/',
|
|
58
|
+
summary: '渐进式 JavaScript 框架,用来构建 Web 界面'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'React',
|
|
62
|
+
href: 'https://react.dev/',
|
|
63
|
+
summary: '构建 Web 和原生用户界面的库'
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Next',
|
|
67
|
+
href: 'https://nextjs.org/',
|
|
68
|
+
summary: '面向 Web 的 React 框架'
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Rolldown',
|
|
72
|
+
href: 'https://rolldown.rs/',
|
|
73
|
+
summary: '基于 Rust 的 JavaScript 打包器,API 兼容 Rollup'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Vite',
|
|
77
|
+
href: 'https://vite.dev/',
|
|
78
|
+
summary: '用来构建 Web 应用的前端构建工具'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'Oxc',
|
|
82
|
+
href: 'https://oxc.rs/',
|
|
83
|
+
summary: '用 Rust 编写的高性能 JavaScript 工具集'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'Spring',
|
|
87
|
+
href: 'https://spring.io/',
|
|
88
|
+
summary: '用来创建 Java 企业级应用'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'Redis',
|
|
92
|
+
href: 'https://redis.io/',
|
|
93
|
+
summary: '内存数据存储,可用作数据库、缓存和消息代理'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'RabbitMQ',
|
|
97
|
+
href: 'https://www.rabbitmq.com/',
|
|
98
|
+
summary: '开源的消息与流代理'
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'Nginx',
|
|
102
|
+
href: 'https://nginx.org/',
|
|
103
|
+
summary: 'HTTP 服务器、反向代理和负载均衡'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Docker',
|
|
107
|
+
href: 'https://www.docker.com/',
|
|
108
|
+
summary: '开发、交付和运行应用的开放平台'
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
projects: [
|
|
112
|
+
{
|
|
113
|
+
name: 'jd-opensource/taro-ui',
|
|
114
|
+
href: 'https://github.com/jd-opensource/taro-ui',
|
|
115
|
+
summary: '一款基于 Taro 框架开发的多端 UI 组件库',
|
|
116
|
+
language: 'TypeScript',
|
|
117
|
+
stars: 4730,
|
|
118
|
+
forks: 743
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'simpleicons.dev',
|
|
122
|
+
href: 'https://github.com/heyq02/simpleicons.dev',
|
|
123
|
+
summary: 'Showcase your skills on your GitHub readme or resumé with ease.',
|
|
124
|
+
language: 'TypeScript',
|
|
125
|
+
stars: 171,
|
|
126
|
+
forks: 0
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
};
|
|
130
|
+
function formatCount(count) {
|
|
131
|
+
if (count < 1000) return String(count);
|
|
132
|
+
return `${(count / 1000).toFixed(1).replace(/\.0$/, '')}k`;
|
|
133
|
+
}
|
|
134
|
+
function fullName() {
|
|
135
|
+
return `${profile.name}${profile.role}`;
|
|
136
|
+
}
|
|
137
|
+
function renderPlain() {
|
|
138
|
+
const lines = [
|
|
139
|
+
fullName(),
|
|
140
|
+
'',
|
|
141
|
+
profile.bio,
|
|
142
|
+
'',
|
|
143
|
+
profile.quote,
|
|
144
|
+
'',
|
|
145
|
+
profile.site,
|
|
146
|
+
'',
|
|
147
|
+
'经历'
|
|
148
|
+
];
|
|
149
|
+
for (const job of profile.experiences)lines.push(`${job.company} · ${job.start} – ${job.end}`, job.href, ...job.points.map((point)=>`- ${point}`), '');
|
|
150
|
+
lines.push('技能');
|
|
151
|
+
for (const skill of profile.skills)lines.push(`${skill.name} — ${skill.summary}`, skill.href);
|
|
152
|
+
lines.push('', '开源');
|
|
153
|
+
for (const project of profile.projects){
|
|
154
|
+
const stats = [
|
|
155
|
+
`★ ${formatCount(project.stars)}`
|
|
156
|
+
];
|
|
157
|
+
if (project.forks > 0) stats.push(`${formatCount(project.forks)} forks`);
|
|
158
|
+
lines.push(`${project.name} · ${project.language} · ${stats.join(' · ')}`, project.summary, project.href, '');
|
|
159
|
+
}
|
|
160
|
+
lines.push('联系');
|
|
161
|
+
for (const place of profile.places)lines.push(`${place.label} · ${place.detail}`, place.href);
|
|
162
|
+
lines.push(profile.phone, profile.email);
|
|
163
|
+
return lines.join('\n');
|
|
164
|
+
}
|
|
165
|
+
export { formatCount, fullName, profile, renderPlain };
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { }
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { command, description, name as router_name, parse, printErrors, printHelp, printVersion, version } from "@bomb.sh/router";
|
|
3
|
+
import { Box, Text, render, useApp, useInput, useStdout } from "ink";
|
|
4
|
+
import { profile, fullName, renderPlain, formatCount } from "./b.js";
|
|
5
|
+
const glyphs = {
|
|
6
|
+
A: [
|
|
7
|
+
' ████ ',
|
|
8
|
+
'██ ██',
|
|
9
|
+
'██████',
|
|
10
|
+
'██ ██',
|
|
11
|
+
'██ ██'
|
|
12
|
+
],
|
|
13
|
+
R: [
|
|
14
|
+
'█████ ',
|
|
15
|
+
'██ ██',
|
|
16
|
+
'█████ ',
|
|
17
|
+
'██ ██ ',
|
|
18
|
+
'██ ██'
|
|
19
|
+
],
|
|
20
|
+
I: [
|
|
21
|
+
'██████',
|
|
22
|
+
' ██ ',
|
|
23
|
+
' ██ ',
|
|
24
|
+
' ██ ',
|
|
25
|
+
'██████'
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
function wordmark(text) {
|
|
29
|
+
const letters = [];
|
|
30
|
+
for (const char of text)letters.push(glyphs[char]);
|
|
31
|
+
return [
|
|
32
|
+
0,
|
|
33
|
+
1,
|
|
34
|
+
2,
|
|
35
|
+
3,
|
|
36
|
+
4
|
|
37
|
+
].map((row)=>letters.map((glyph)=>glyph?.[row] ?? ' ').join(' '));
|
|
38
|
+
}
|
|
39
|
+
const paper = '#F6F3ED';
|
|
40
|
+
const ink = '#343945';
|
|
41
|
+
const muted = '#8991A0';
|
|
42
|
+
const accent = '#3F6CC4';
|
|
43
|
+
const card = '#FFFFFF';
|
|
44
|
+
const bar = '#EAE1D3';
|
|
45
|
+
const gold = '#C08A3E';
|
|
46
|
+
function IntroScreen({ columns, rows, onExit }) {
|
|
47
|
+
const { exit } = useApp();
|
|
48
|
+
const { stdout } = useStdout();
|
|
49
|
+
const stream = stdout;
|
|
50
|
+
const measuredWidth = stream?.columns ?? 0;
|
|
51
|
+
const measuredHeight = stream?.rows ?? 0;
|
|
52
|
+
const width = columns ?? (measuredWidth > 0 ? measuredWidth : 80);
|
|
53
|
+
const height = rows ?? (measuredHeight > 0 ? measuredHeight : 32);
|
|
54
|
+
const showWordmark = height >= 38 && width >= 64;
|
|
55
|
+
const padded = height >= 48 && width >= 80;
|
|
56
|
+
const spaced = height >= 30;
|
|
57
|
+
const showSummaries = height >= 36;
|
|
58
|
+
const showPlaces = height >= 32;
|
|
59
|
+
useInput(()=>{
|
|
60
|
+
onExit?.();
|
|
61
|
+
exit();
|
|
62
|
+
});
|
|
63
|
+
return /*#__PURE__*/ React.createElement(Box, {
|
|
64
|
+
width: width,
|
|
65
|
+
height: height,
|
|
66
|
+
flexDirection: "column",
|
|
67
|
+
backgroundColor: paper
|
|
68
|
+
}, /*#__PURE__*/ React.createElement(Box, {
|
|
69
|
+
paddingX: 2,
|
|
70
|
+
justifyContent: "space-between"
|
|
71
|
+
}, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
72
|
+
color: accent,
|
|
73
|
+
bold: true
|
|
74
|
+
}, "heyq02"), /*#__PURE__*/ React.createElement(Text, {
|
|
75
|
+
color: muted
|
|
76
|
+
}, " \xb7 intro")), /*#__PURE__*/ React.createElement(Text, {
|
|
77
|
+
color: muted
|
|
78
|
+
}, "0.1.0")), /*#__PURE__*/ React.createElement(Box, {
|
|
79
|
+
flexGrow: 1,
|
|
80
|
+
flexShrink: 1,
|
|
81
|
+
flexDirection: "column",
|
|
82
|
+
overflow: "hidden",
|
|
83
|
+
paddingX: 3,
|
|
84
|
+
paddingTop: showWordmark ? 1 : 0
|
|
85
|
+
}, showWordmark ? wordmark('ARI').map((line)=>/*#__PURE__*/ React.createElement(Text, {
|
|
86
|
+
key: line,
|
|
87
|
+
color: accent
|
|
88
|
+
}, line)) : null, /*#__PURE__*/ React.createElement(Box, {
|
|
89
|
+
flexShrink: 0,
|
|
90
|
+
marginTop: showWordmark ? 1 : 0,
|
|
91
|
+
flexDirection: "column"
|
|
92
|
+
}, /*#__PURE__*/ React.createElement(Text, {
|
|
93
|
+
color: ink,
|
|
94
|
+
bold: true
|
|
95
|
+
}, fullName()), sentences(profile.bio).map((line)=>/*#__PURE__*/ React.createElement(Text, {
|
|
96
|
+
key: line,
|
|
97
|
+
color: ink
|
|
98
|
+
}, line)), /*#__PURE__*/ React.createElement(Text, {
|
|
99
|
+
color: muted,
|
|
100
|
+
italic: true
|
|
101
|
+
}, profile.quote)), /*#__PURE__*/ React.createElement(Section, {
|
|
102
|
+
title: "经历",
|
|
103
|
+
padded: padded,
|
|
104
|
+
spaced: spaced
|
|
105
|
+
}, profile.experiences.map((job)=>/*#__PURE__*/ React.createElement(Box, {
|
|
106
|
+
key: job.company,
|
|
107
|
+
flexDirection: "column"
|
|
108
|
+
}, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
109
|
+
color: ink,
|
|
110
|
+
bold: true
|
|
111
|
+
}, job.company), /*#__PURE__*/ React.createElement(Text, {
|
|
112
|
+
color: muted
|
|
113
|
+
}, ` ${job.start} – ${job.end}`)), job.points.map((point)=>/*#__PURE__*/ React.createElement(Text, {
|
|
114
|
+
key: point,
|
|
115
|
+
color: ink
|
|
116
|
+
}, /*#__PURE__*/ React.createElement(Text, {
|
|
117
|
+
color: accent
|
|
118
|
+
}, "\xb7 "), point))))), /*#__PURE__*/ React.createElement(Section, {
|
|
119
|
+
title: "技能",
|
|
120
|
+
padded: padded,
|
|
121
|
+
spaced: spaced
|
|
122
|
+
}, skillRows(width).map((row)=>/*#__PURE__*/ React.createElement(Text, {
|
|
123
|
+
key: row.join('·')
|
|
124
|
+
}, row.map((name, index)=>/*#__PURE__*/ React.createElement(Text, {
|
|
125
|
+
key: name
|
|
126
|
+
}, index > 0 ? /*#__PURE__*/ React.createElement(Text, {
|
|
127
|
+
color: muted
|
|
128
|
+
}, " \xb7 ") : null, /*#__PURE__*/ React.createElement(Text, {
|
|
129
|
+
color: accent
|
|
130
|
+
}, name)))))), /*#__PURE__*/ React.createElement(Section, {
|
|
131
|
+
title: "开源",
|
|
132
|
+
padded: padded,
|
|
133
|
+
spaced: spaced
|
|
134
|
+
}, profile.projects.map((project)=>/*#__PURE__*/ React.createElement(Box, {
|
|
135
|
+
key: project.name,
|
|
136
|
+
flexDirection: "column"
|
|
137
|
+
}, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
138
|
+
color: ink,
|
|
139
|
+
bold: true
|
|
140
|
+
}, project.name), /*#__PURE__*/ React.createElement(Text, {
|
|
141
|
+
color: gold
|
|
142
|
+
}, ` ★ ${formatCount(project.stars)}`), project.forks > 0 ? /*#__PURE__*/ React.createElement(Text, {
|
|
143
|
+
color: muted
|
|
144
|
+
}, ` · ${formatCount(project.forks)} forks`) : null), showSummaries ? /*#__PURE__*/ React.createElement(Text, {
|
|
145
|
+
color: muted
|
|
146
|
+
}, project.summary) : null))), /*#__PURE__*/ React.createElement(Section, {
|
|
147
|
+
title: "联系",
|
|
148
|
+
padded: padded,
|
|
149
|
+
spaced: spaced
|
|
150
|
+
}, showPlaces ? /*#__PURE__*/ React.createElement(Box, {
|
|
151
|
+
flexDirection: "column"
|
|
152
|
+
}, profile.places.map((place)=>/*#__PURE__*/ React.createElement(Text, {
|
|
153
|
+
key: place.label
|
|
154
|
+
}, /*#__PURE__*/ React.createElement(Text, {
|
|
155
|
+
color: muted
|
|
156
|
+
}, pad(place.label, 10)), /*#__PURE__*/ React.createElement(Text, {
|
|
157
|
+
color: ink
|
|
158
|
+
}, place.detail))), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
159
|
+
color: muted
|
|
160
|
+
}, pad('电话', 10)), /*#__PURE__*/ React.createElement(Text, {
|
|
161
|
+
color: ink
|
|
162
|
+
}, profile.phone)), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
163
|
+
color: muted
|
|
164
|
+
}, pad('邮箱', 10)), /*#__PURE__*/ React.createElement(Text, {
|
|
165
|
+
color: ink
|
|
166
|
+
}, profile.email))) : /*#__PURE__*/ React.createElement(Box, {
|
|
167
|
+
flexDirection: "column"
|
|
168
|
+
}, placeRows(width).map((row)=>/*#__PURE__*/ React.createElement(Text, {
|
|
169
|
+
key: row,
|
|
170
|
+
color: ink
|
|
171
|
+
}, row)), /*#__PURE__*/ React.createElement(Text, {
|
|
172
|
+
color: ink
|
|
173
|
+
}, `${profile.phone} ${profile.email}`)))), /*#__PURE__*/ React.createElement(Box, {
|
|
174
|
+
paddingX: 2,
|
|
175
|
+
backgroundColor: bar,
|
|
176
|
+
justifyContent: "space-between"
|
|
177
|
+
}, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
|
|
178
|
+
backgroundColor: accent,
|
|
179
|
+
color: paper
|
|
180
|
+
}, ' heyq02 '), /*#__PURE__*/ React.createElement(Text, {
|
|
181
|
+
color: muted
|
|
182
|
+
}, ` ${profile.site.replace('https://', '')}`)), /*#__PURE__*/ React.createElement(Text, {
|
|
183
|
+
color: muted
|
|
184
|
+
}, "任意键退出")));
|
|
185
|
+
}
|
|
186
|
+
function Section({ title, padded, spaced, children }) {
|
|
187
|
+
return /*#__PURE__*/ React.createElement(Box, {
|
|
188
|
+
flexShrink: 0,
|
|
189
|
+
marginTop: spaced ? 1 : 0,
|
|
190
|
+
flexDirection: "column",
|
|
191
|
+
backgroundColor: padded ? card : void 0,
|
|
192
|
+
paddingX: padded ? 2 : 0,
|
|
193
|
+
paddingY: padded ? 1 : 0
|
|
194
|
+
}, /*#__PURE__*/ React.createElement(Text, {
|
|
195
|
+
color: accent,
|
|
196
|
+
bold: true
|
|
197
|
+
}, title), children);
|
|
198
|
+
}
|
|
199
|
+
function sentences(text) {
|
|
200
|
+
return text.split('。').filter((part)=>part.length > 0).map((part)=>`${part}。`);
|
|
201
|
+
}
|
|
202
|
+
function skillRows(width) {
|
|
203
|
+
const budget = Math.max(24, width - 10);
|
|
204
|
+
const rows = [
|
|
205
|
+
[]
|
|
206
|
+
];
|
|
207
|
+
let used = 0;
|
|
208
|
+
for (const skill of profile.skills){
|
|
209
|
+
const size = displayWidth(skill.name) + (used > 0 ? 5 : 0);
|
|
210
|
+
const row = rows[rows.length - 1];
|
|
211
|
+
if (void 0 !== row) if (row.length > 0 && used + size > budget) {
|
|
212
|
+
rows.push([
|
|
213
|
+
skill.name
|
|
214
|
+
]);
|
|
215
|
+
used = displayWidth(skill.name);
|
|
216
|
+
} else {
|
|
217
|
+
row.push(skill.name);
|
|
218
|
+
used += size;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return rows;
|
|
222
|
+
}
|
|
223
|
+
function placeRows(width) {
|
|
224
|
+
const budget = Math.max(20, width - 8);
|
|
225
|
+
const items = profile.places.map((place)=>`${place.label} ${place.detail}`);
|
|
226
|
+
const rows = [];
|
|
227
|
+
let current = '';
|
|
228
|
+
for (const item of items){
|
|
229
|
+
const next = 0 === current.length ? item : `${current} ${item}`;
|
|
230
|
+
if (current.length > 0 && displayWidth(next) > budget) {
|
|
231
|
+
rows.push(current);
|
|
232
|
+
current = item;
|
|
233
|
+
} else current = next;
|
|
234
|
+
}
|
|
235
|
+
if (current.length > 0) rows.push(current);
|
|
236
|
+
return rows;
|
|
237
|
+
}
|
|
238
|
+
function pad(text, columns) {
|
|
239
|
+
const gap = columns - displayWidth(text);
|
|
240
|
+
return gap > 0 ? `${text}${' '.repeat(gap)}` : text;
|
|
241
|
+
}
|
|
242
|
+
function displayWidth(text) {
|
|
243
|
+
let width = 0;
|
|
244
|
+
for (const char of text)width += isWide(char.codePointAt(0) ?? 0) ? 2 : 1;
|
|
245
|
+
return width;
|
|
246
|
+
}
|
|
247
|
+
function isWide(code) {
|
|
248
|
+
return code >= 0x1100 && code <= 0x115f || code >= 0x2e80 && code <= 0xa4cf || code >= 0xac00 && code <= 0xd7a3 || code >= 0xf900 && code <= 0xfaff || code >= 0xfe10 && code <= 0xfe19 || code >= 0xfe30 && code <= 0xfe6f || code >= 0xff00 && code <= 0xff60 || code >= 0xffe0 && code <= 0xffe6;
|
|
249
|
+
}
|
|
250
|
+
const enterScreen = '\u001b[?1049h\u001b[?25l';
|
|
251
|
+
const leaveScreen = '\u001b[?25h\u001b[?1049l';
|
|
252
|
+
async function showIntro() {
|
|
253
|
+
if (!process.stdout.isTTY || !process.stdin.isTTY) return void process.stdout.write(`${renderPlain()}\n`);
|
|
254
|
+
process.stdout.write(enterScreen);
|
|
255
|
+
try {
|
|
256
|
+
const app = render(/*#__PURE__*/ React.createElement(IntroScreen, null), {
|
|
257
|
+
exitOnCtrlC: true
|
|
258
|
+
});
|
|
259
|
+
await app.waitUntilExit();
|
|
260
|
+
} finally{
|
|
261
|
+
process.stdout.write(leaveScreen);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const program = command(router_name('heyq02'), description('永琪(Ari),全栈研发。'), version('0.1.0'), command(router_name('intro'), description('展示介绍,任意键退出。')), command(router_name('hw'), description('打印 Hello, World!')));
|
|
265
|
+
async function main(argv = process.argv.slice(2)) {
|
|
266
|
+
const result = parse(program, {
|
|
267
|
+
argv
|
|
268
|
+
});
|
|
269
|
+
if (!result.ok) {
|
|
270
|
+
process.stderr.write(`${printErrors(result)}\n`);
|
|
271
|
+
process.exitCode = 1;
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
switch(result.method){
|
|
275
|
+
case 'help':
|
|
276
|
+
return void process.stdout.write(`${printHelp(result)}\n`);
|
|
277
|
+
case 'version':
|
|
278
|
+
return void process.stdout.write(`${printVersion(result)}\n`);
|
|
279
|
+
case 'execute':
|
|
280
|
+
switch(result.route){
|
|
281
|
+
case '/':
|
|
282
|
+
{
|
|
283
|
+
const help = parse(program, {
|
|
284
|
+
argv: [
|
|
285
|
+
'--help'
|
|
286
|
+
]
|
|
287
|
+
});
|
|
288
|
+
if (help.ok && 'help' === help.method) process.stdout.write(`${printHelp(help)}\n`);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
case '/intro':
|
|
292
|
+
return void await showIntro();
|
|
293
|
+
case '/hw':
|
|
294
|
+
return void process.stdout.write('Hello, World!\n');
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
await main();
|
|
300
|
+
} catch (error) {
|
|
301
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
302
|
+
process.stderr.write(`${message}\n`);
|
|
303
|
+
process.exitCode = 1;
|
|
304
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare function formatCount(count: number): string;
|
|
2
|
+
|
|
3
|
+
export declare function fullName(): string;
|
|
4
|
+
|
|
5
|
+
export declare const profile: {
|
|
6
|
+
name: string;
|
|
7
|
+
givenNames: readonly ["永琪", "Ari"];
|
|
8
|
+
role: string;
|
|
9
|
+
bio: string;
|
|
10
|
+
quote: string;
|
|
11
|
+
phone: string;
|
|
12
|
+
email: string;
|
|
13
|
+
site: string;
|
|
14
|
+
places: {
|
|
15
|
+
label: string;
|
|
16
|
+
href: string;
|
|
17
|
+
detail: string;
|
|
18
|
+
}[];
|
|
19
|
+
experiences: {
|
|
20
|
+
company: string;
|
|
21
|
+
href: string;
|
|
22
|
+
start: string;
|
|
23
|
+
end: string;
|
|
24
|
+
points: string[];
|
|
25
|
+
}[];
|
|
26
|
+
skills: {
|
|
27
|
+
name: string;
|
|
28
|
+
href: string;
|
|
29
|
+
summary: string;
|
|
30
|
+
}[];
|
|
31
|
+
projects: {
|
|
32
|
+
name: string;
|
|
33
|
+
href: string;
|
|
34
|
+
summary: string;
|
|
35
|
+
language: string;
|
|
36
|
+
stars: number;
|
|
37
|
+
forks: number;
|
|
38
|
+
}[];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export declare function renderPlain(): string;
|
|
42
|
+
|
|
43
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { formatCount, fullName, profile, renderPlain } from "./b.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,78 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heyq02",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "永琪(Ari),全栈研发。终端里的个人介绍。",
|
|
5
|
+
"homepage": "https://intro.heyq02.com",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/heyq02/heyq02/issues"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/heyq02/heyq02.git"
|
|
12
|
+
},
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"author": "永琪(Ari) <hello@heyq02.com>",
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
22
|
+
},
|
|
23
|
+
"bin": {
|
|
24
|
+
"heyq02": "./dist/cli.js"
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@bomb.sh/router": "0.8.0",
|
|
31
|
+
"ink": "^8.0.0",
|
|
32
|
+
"react": "19.3.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@commitlint/cli": "20.5.3",
|
|
36
|
+
"@heyq02/rstack-config": "^0.0.6",
|
|
37
|
+
"@microsoft/api-extractor": "^7.59.4",
|
|
38
|
+
"@rsdoctor/rspack-plugin": "^1.6.5",
|
|
39
|
+
"@rslib/core": "^1.0.3",
|
|
40
|
+
"@rslint/core": "^0.9.5",
|
|
41
|
+
"@rstest/core": "^0.12.3",
|
|
42
|
+
"@rstest/coverage-v8": "^0.12.3",
|
|
43
|
+
"@types/node": "^26.1.1",
|
|
44
|
+
"@types/react": "19.3.0",
|
|
45
|
+
"bumpp": "^11.1.0",
|
|
46
|
+
"ink-testing-library": "^4.0.0",
|
|
47
|
+
"rstack": "^0.8.4",
|
|
48
|
+
"typescript": "npm:@typescript/typescript6@^6.0.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=22.12.0"
|
|
52
|
+
},
|
|
53
|
+
"devEngines": {
|
|
54
|
+
"packageManager": {
|
|
55
|
+
"name": "pnpm",
|
|
56
|
+
"version": "12.10.1",
|
|
57
|
+
"onFail": "download"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "rs lib",
|
|
65
|
+
"build:rsdoctor": "RSDOCTOR=true rs lib",
|
|
66
|
+
"check": "rs check && pnpm run typecheck",
|
|
67
|
+
"commitlint": "commitlint",
|
|
68
|
+
"dev": "rs lib --watch",
|
|
69
|
+
"format": "rs fmt",
|
|
70
|
+
"format:check": "rs fmt --check",
|
|
71
|
+
"lint": "rs lint .",
|
|
72
|
+
"lint:fix": "rs lint --fix .",
|
|
73
|
+
"release": "bumpp",
|
|
74
|
+
"test": "rs test",
|
|
75
|
+
"test:coverage": "rs test --coverage",
|
|
76
|
+
"typecheck": "tsc6 --noEmit -p tsconfig.typecheck.json"
|
|
77
|
+
}
|
|
6
78
|
}
|