@nbtca/prompt 1.0.8 → 1.0.13

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.
Files changed (71) hide show
  1. package/README.md +16 -289
  2. package/dist/config/data.d.ts +1 -1
  3. package/dist/config/data.js +1 -1
  4. package/dist/config/data.js.map +1 -1
  5. package/dist/core/logo.d.ts.map +1 -1
  6. package/dist/core/logo.js +13 -2
  7. package/dist/core/logo.js.map +1 -1
  8. package/dist/core/menu.d.ts +5 -0
  9. package/dist/core/menu.d.ts.map +1 -1
  10. package/dist/core/menu.js +12 -5
  11. package/dist/core/menu.js.map +1 -1
  12. package/dist/core/ui.d.ts.map +1 -1
  13. package/dist/core/ui.js +5 -3
  14. package/dist/core/ui.js.map +1 -1
  15. package/dist/features/calendar.d.ts +13 -14
  16. package/dist/features/calendar.d.ts.map +1 -1
  17. package/dist/features/calendar.js +57 -59
  18. package/dist/features/calendar.js.map +1 -1
  19. package/dist/features/docs.d.ts.map +1 -1
  20. package/dist/features/docs.js +50 -47
  21. package/dist/features/docs.js.map +1 -1
  22. package/dist/features/repair.d.ts +4 -0
  23. package/dist/features/repair.d.ts.map +1 -1
  24. package/dist/features/repair.js +1 -1
  25. package/dist/features/repair.js.map +1 -1
  26. package/dist/features/website.d.ts +10 -0
  27. package/dist/features/website.d.ts.map +1 -1
  28. package/dist/features/website.js +14 -2
  29. package/dist/features/website.js.map +1 -1
  30. package/dist/i18n/index.d.ts +9 -0
  31. package/dist/i18n/index.d.ts.map +1 -1
  32. package/dist/i18n/index.js.map +1 -1
  33. package/dist/i18n/locales/en.json +10 -1
  34. package/dist/i18n/locales/zh.json +10 -1
  35. package/dist/index.d.ts +1 -2
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +133 -4
  38. package/dist/index.js.map +1 -1
  39. package/dist/main.d.ts +4 -1
  40. package/dist/main.d.ts.map +1 -1
  41. package/dist/main.js +7 -3
  42. package/dist/main.js.map +1 -1
  43. package/package.json +8 -2
  44. package/.github/workflows/ci.yml +0 -40
  45. package/.github/workflows/publish.yml +0 -59
  46. package/CHANGELOG.md +0 -125
  47. package/DEVELOPMENT.md +0 -258
  48. package/TERMINAL_UX.md +0 -184
  49. package/assets/Prompt_demo.gif +0 -0
  50. package/src/config/data.js +0 -484
  51. package/src/config/data.ts +0 -28
  52. package/src/config/theme.js +0 -138
  53. package/src/config/theme.ts +0 -26
  54. package/src/core/logo.ts +0 -189
  55. package/src/core/menu.ts +0 -213
  56. package/src/core/ui.ts +0 -89
  57. package/src/core/vim-keys.ts +0 -70
  58. package/src/features/calendar.ts +0 -161
  59. package/src/features/docs.ts +0 -588
  60. package/src/features/repair.ts +0 -36
  61. package/src/features/website.ts +0 -45
  62. package/src/i18n/index.ts +0 -236
  63. package/src/i18n/locales/en.json +0 -107
  64. package/src/i18n/locales/zh.json +0 -107
  65. package/src/index.ts +0 -9
  66. package/src/logo/ascii-logo.txt +0 -6
  67. package/src/logo/logo.txt +0 -2
  68. package/src/logo/printLogo.js +0 -26
  69. package/src/main.ts +0 -45
  70. package/src/types.ts +0 -51
  71. package/tsconfig.json +0 -53
@@ -1,588 +0,0 @@
1
- /**
2
- * 知识库终端查看模块
3
- * 获取并渲染Markdown文档
4
- */
5
-
6
- import axios from 'axios';
7
- import { marked } from 'marked';
8
- import TerminalRenderer from 'marked-terminal';
9
- import chalk from 'chalk';
10
- import open from 'open';
11
- import inquirer from 'inquirer';
12
- import { error, info, success, warning } from '../core/ui.js';
13
- import { spawn } from 'child_process';
14
- import { t } from '../i18n/index.js';
15
-
16
- /**
17
- * Terminal capability detection
18
- * Detects if the terminal supports advanced features like images, colors, etc.
19
- */
20
- interface TerminalCapabilities {
21
- supportsColor: boolean;
22
- supportsImages: boolean;
23
- supportsUnicode: boolean;
24
- terminalType: 'basic' | 'enhanced' | 'advanced';
25
- }
26
-
27
- /**
28
- * Detect terminal capabilities
29
- */
30
- function detectTerminalCapabilities(): TerminalCapabilities {
31
- const term = (process.env['TERM'] || '').toLowerCase();
32
- const termProgram = (process.env['TERM_PROGRAM'] || '').toLowerCase();
33
- const colorTerm = process.env['COLORTERM'];
34
-
35
- // Detect image support (iTerm2, Kitty, WezTerm, etc.)
36
- const supportsImages =
37
- termProgram.includes('iterm') ||
38
- term.includes('kitty') ||
39
- termProgram.includes('wezterm') ||
40
- term.includes('sixel');
41
-
42
- // Detect color support
43
- const supportsColor =
44
- colorTerm !== undefined ||
45
- term.includes('color') ||
46
- term.includes('256') ||
47
- term.includes('ansi') ||
48
- termProgram !== '';
49
-
50
- // Detect Unicode support
51
- const supportsUnicode =
52
- (process.env['LANG'] || '').includes('UTF-8') ||
53
- (process.env['LC_ALL'] || '').includes('UTF-8');
54
-
55
- // Determine terminal type
56
- let terminalType: 'basic' | 'enhanced' | 'advanced' = 'basic';
57
- if (supportsImages && supportsColor && supportsUnicode) {
58
- terminalType = 'advanced';
59
- } else if (supportsColor && supportsUnicode) {
60
- terminalType = 'enhanced';
61
- }
62
-
63
- return {
64
- supportsColor,
65
- supportsImages,
66
- supportsUnicode,
67
- terminalType
68
- };
69
- }
70
-
71
- /**
72
- * Get marked-terminal renderer options based on terminal capabilities
73
- */
74
- function getRendererOptions(capabilities: TerminalCapabilities): any {
75
- // Text width for better readability
76
- const width = Math.min(process.stdout.columns || 80, 100);
77
-
78
- // For basic terminals, use simpler ASCII characters
79
- if (capabilities.terminalType === 'basic') {
80
- return {
81
- width,
82
- tableOptions: {
83
- chars: {
84
- top: '-', 'top-mid': '+', 'top-left': '+', 'top-right': '+',
85
- bottom: '-', 'bottom-mid': '+', 'bottom-left': '+', 'bottom-right': '+',
86
- left: '|', 'left-mid': '+', mid: '-', 'mid-mid': '+',
87
- right: '|', 'right-mid': '+', middle: '|'
88
- }
89
- }
90
- };
91
- }
92
-
93
- // For enhanced and advanced terminals, use Unicode box-drawing characters
94
- return {
95
- width,
96
- tableOptions: {
97
- chars: {
98
- top: '─',
99
- 'top-mid': '┬',
100
- 'top-left': '┌',
101
- 'top-right': '┐',
102
- bottom: '─',
103
- 'bottom-mid': '┴',
104
- 'bottom-left': '└',
105
- 'bottom-right': '┘',
106
- left: '│',
107
- 'left-mid': '├',
108
- mid: '─',
109
- 'mid-mid': '┼',
110
- right: '│',
111
- 'right-mid': '┤',
112
- middle: '│'
113
- }
114
- }
115
- };
116
- }
117
-
118
- // Detect terminal capabilities once at startup
119
- const terminalCapabilities = detectTerminalCapabilities();
120
-
121
- // Configure marked with terminal-optimized renderer
122
- marked.setOptions({
123
- // @ts-ignore - markedTerminal类型定义问题
124
- renderer: new TerminalRenderer(getRendererOptions(terminalCapabilities))
125
- });
126
-
127
- /**
128
- * GitHub仓库配置
129
- */
130
- const GITHUB_REPO = {
131
- owner: 'nbtca',
132
- repo: 'documents',
133
- branch: 'main'
134
- };
135
-
136
- /**
137
- * GitHub Token (可选 - 用于避免 API 速率限制)
138
- * 从环境变量读取,如果没有则使用未认证请求
139
- */
140
- const GITHUB_TOKEN = process.env['GITHUB_TOKEN'] || process.env['GH_TOKEN'];
141
-
142
- /**
143
- * 文档结构类型
144
- */
145
- interface DocItem {
146
- name: string;
147
- path: string;
148
- type: 'file' | 'dir';
149
- sha?: string;
150
- }
151
-
152
- /**
153
- * 预定义的文档分类
154
- */
155
- const DOC_CATEGORIES = [
156
- { name: '[Tutorial] 教程', path: 'tutorial' },
157
- { name: '[Repair] 维修日', path: '维修日' },
158
- { name: '[Events] 相关活动举办', path: '相关活动举办' },
159
- { name: '[Process] 流程文档', path: 'process' },
160
- { name: '[Repair] 维修相关', path: 'repair' },
161
- { name: '[Archive] 归档文档', path: 'archived' },
162
- { name: '[README] 项目说明', path: 'README.md' }
163
- ];
164
-
165
- /**
166
- * 从GitHub获取目录内容
167
- */
168
- async function fetchGitHubDirectory(path: string = ''): Promise<DocItem[]> {
169
- const url = `https://api.github.com/repos/${GITHUB_REPO.owner}/${GITHUB_REPO.repo}/contents/${path}?ref=${GITHUB_REPO.branch}`;
170
-
171
- try {
172
- const headers: any = {
173
- 'Accept': 'application/vnd.github.v3+json',
174
- 'User-Agent': 'NBTCA-CLI'
175
- };
176
-
177
- // 如果有 GitHub Token,添加认证头以避免速率限制
178
- if (GITHUB_TOKEN) {
179
- headers['Authorization'] = `Bearer ${GITHUB_TOKEN}`;
180
- }
181
-
182
- const response = await axios.get(url, {
183
- timeout: 10000,
184
- headers
185
- });
186
-
187
- return response.data
188
- .filter((item: any) => {
189
- // 过滤掉 node_modules, .git 等目录
190
- if (item.name.startsWith('.')) return false;
191
- if (item.name === 'node_modules') return false;
192
- if (item.name === 'package.json') return false;
193
- if (item.name === 'pnpm-lock.yaml') return false;
194
-
195
- // 只显示目录和 markdown 文件
196
- if (item.type === 'file' && !item.name.endsWith('.md')) return false;
197
-
198
- return true;
199
- })
200
- .map((item: any) => ({
201
- name: item.name,
202
- path: item.path,
203
- type: item.type === 'dir' ? 'dir' : 'file',
204
- sha: item.sha
205
- }))
206
- .sort((a: DocItem, b: DocItem) => {
207
- // 目录排在前面
208
- if (a.type === 'dir' && b.type === 'file') return -1;
209
- if (a.type === 'file' && b.type === 'dir') return 1;
210
- return a.name.localeCompare(b.name);
211
- });
212
- } catch (err: any) {
213
- // 提供更详细的错误信息
214
- if (err.response?.status === 403) {
215
- const rateLimitRemaining = err.response.headers['x-ratelimit-remaining'];
216
- const rateLimitReset = err.response.headers['x-ratelimit-reset'];
217
-
218
- if (rateLimitRemaining === '0') {
219
- const resetDate = new Date(parseInt(rateLimitReset) * 1000);
220
- throw new Error(`GitHub API 速率限制已达上限,将在 ${resetDate.toLocaleTimeString()} 重置。\n提示: 设置 GITHUB_TOKEN 环境变量可获得更高的速率限制。`);
221
- }
222
- throw new Error(`GitHub API 拒绝访问 (403)。\n提示: 尝试设置 GITHUB_TOKEN 环境变量。`);
223
- }
224
- throw new Error(`无法获取目录内容: ${err.message}`);
225
- }
226
- }
227
-
228
- /**
229
- * 从GitHub获取文件原始内容
230
- */
231
- async function fetchGitHubRawContent(path: string): Promise<string> {
232
- const url = `https://raw.githubusercontent.com/${GITHUB_REPO.owner}/${GITHUB_REPO.repo}/${GITHUB_REPO.branch}/${path}`;
233
-
234
- try {
235
- const response = await axios.get(url, {
236
- timeout: 15000,
237
- headers: {
238
- 'User-Agent': 'NBTCA-CLI'
239
- }
240
- });
241
-
242
- return response.data;
243
- } catch (err: any) {
244
- throw new Error(`无法获取文件内容: ${err.message}`);
245
- }
246
- }
247
-
248
- /**
249
- * 清理和格式化Markdown内容
250
- * 移除VitePress frontmatter和特殊语法,优化终端显示
251
- */
252
- function cleanMarkdownContent(content: string, capabilities: TerminalCapabilities): string {
253
- let cleaned = content;
254
-
255
- // 1. 移除 YAML frontmatter (---开头结尾的部分)
256
- cleaned = cleaned.replace(/^---\n[\s\S]*?\n---\n/m, '');
257
-
258
- // 2. 移除 VitePress 的特殊容器语法 (:::info, :::tip, :::warning 等)
259
- // 保留内容,只移除容器标记
260
- cleaned = cleaned.replace(/^:::(info|tip|warning|danger|details).*$/gm, '');
261
- cleaned = cleaned.replace(/^:::$/gm, '');
262
-
263
- // 3. 处理 VitePress 的 [[toc]] 语法
264
- cleaned = cleaned.replace(/\[\[toc\]\]/gi, '**目录**\n\n_(请在浏览器中查看完整目录)_\n');
265
-
266
- // 4. 优化图片显示 - 根据终端能力调整
267
- if (capabilities.terminalType === 'basic') {
268
- // Basic terminals: Replace images with simple text references
269
- // This prevents clutter from image syntax that can't be displayed
270
- cleaned = cleaned.replace(
271
- /!\[([^\]]*)\]\(([^)]+)\)/g,
272
- (_match, alt, _url) => {
273
- const description = alt || '图片';
274
- return `📎 [${description}]`;
275
- }
276
- );
277
- } else if (capabilities.terminalType === 'enhanced') {
278
- // Enhanced terminals: Keep alt text and show it's an image
279
- cleaned = cleaned.replace(
280
- /!\[([^\]]*)\]\(([^)]+)\)/g,
281
- (_match, alt, url) => {
282
- const description = alt || '图片';
283
- const filename = url.split('/').pop() || url;
284
- return `🖼️ **[图片: ${description}]**\n _${filename}_`;
285
- }
286
- );
287
- }
288
- // For advanced terminals (supportsImages), keep original markdown
289
- // marked-terminal will handle the image syntax appropriately
290
-
291
- // 5. 清理多余的空行(超过2个连续空行压缩为2个)
292
- cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
293
-
294
- // 6. 移除 HTML 注释
295
- cleaned = cleaned.replace(/<!--[\s\S]*?-->/g, '');
296
-
297
- // 7. 移除 HTML 标签但保留内容 (for better terminal display)
298
- cleaned = cleaned.replace(/<([a-z][a-z0-9]*)[^>]*>(.*?)<\/\1>/gi, '$2');
299
-
300
- // 8. 清理开头和结尾的空白
301
- cleaned = cleaned.trim();
302
-
303
- return cleaned;
304
- }
305
-
306
- /**
307
- * 提取文档标题(从第一个 # 标题)
308
- */
309
- function extractDocTitle(content: string): string | null {
310
- const match = content.match(/^#\s+(.+)$/m);
311
- return match?.[1]?.trim() ?? null;
312
- }
313
-
314
- /**
315
- * 浏览目录并选择文档
316
- */
317
- async function browseDirectory(dirPath: string = ''): Promise<void> {
318
- const trans = t();
319
- try {
320
- info(dirPath ? `${trans.docs.loadingDir}: ${dirPath}` : trans.docs.loading);
321
-
322
- const items = await fetchGitHubDirectory(dirPath);
323
-
324
- console.log('\r' + ' '.repeat(60) + '\r'); // 清除加载提示
325
-
326
- if (items.length === 0) {
327
- warning(trans.docs.emptyDir);
328
- return;
329
- }
330
-
331
- // 构建选择列表
332
- const choices = [
333
- ...(dirPath ? [
334
- { name: chalk.gray(trans.docs.upToParent), value: { type: 'back' } },
335
- new inquirer.Separator()
336
- ] : []),
337
- ...items.map(item => ({
338
- name: item.type === 'dir'
339
- ? chalk.cyan(`[DIR] ${item.name}/`)
340
- : chalk.white(`[MD] ${item.name}`),
341
- value: item
342
- })),
343
- new inquirer.Separator(),
344
- { name: chalk.gray(trans.docs.returnToMenu), value: { type: 'exit' } }
345
- ];
346
-
347
- const { selected } = await inquirer.prompt([
348
- {
349
- type: 'list',
350
- name: 'selected',
351
- message: dirPath ? `${trans.docs.currentDir}: ${dirPath}` : trans.docs.chooseDoc,
352
- choices,
353
- pageSize: 15,
354
- loop: false
355
- }
356
- ]);
357
-
358
- // 处理用户选择
359
- if (selected.type === 'exit') {
360
- return;
361
- } else if (selected.type === 'back') {
362
- // 返回上级目录
363
- const parentPath = dirPath.split('/').slice(0, -1).join('/');
364
- await browseDirectory(parentPath);
365
- } else if (selected.type === 'dir') {
366
- // 进入子目录
367
- await browseDirectory(selected.path);
368
- } else if (selected.type === 'file') {
369
- // 查看文件
370
- await viewMarkdownFile(selected.path);
371
- // 查看完后继续浏览当前目录
372
- await browseDirectory(dirPath);
373
- }
374
-
375
- } catch (err: any) {
376
- error(trans.docs.loadError);
377
- console.log(chalk.gray(` ${trans.docs.errorHint}: ${err.message}`));
378
-
379
- const { retry } = await inquirer.prompt([
380
- {
381
- type: 'confirm',
382
- name: 'retry',
383
- message: trans.docs.retry,
384
- default: true
385
- }
386
- ]);
387
-
388
- if (retry) {
389
- await browseDirectory(dirPath);
390
- }
391
- }
392
- }
393
-
394
- /**
395
- * 使用系统pager (less/more) 显示内容
396
- * 提供类似vim/journalctl的阅读体验
397
- */
398
- async function displayInPager(content: string, title: string): Promise<boolean> {
399
- const trans = t();
400
- return new Promise((resolve) => {
401
- // 检测可用的pager程序
402
- const pager = process.env['PAGER'] || 'less';
403
-
404
- // 为内容添加标题
405
- const fullContent = `${chalk.cyan.bold(`>> ${title}`)}\n${chalk.gray('='.repeat(80))}\n\n${content}\n\n${chalk.gray('='.repeat(80))}\n${chalk.dim(trans.docs.endOfDocument)}\n`;
406
-
407
- // less的参数: -R (支持颜色), -F (如果内容少于一屏则直接显示), -X (退出时不清屏)
408
- const lessArgs = ['-R', '-F', '-X'];
409
-
410
- try {
411
- const child = spawn(pager, lessArgs, {
412
- stdio: ['pipe', 'inherit', 'inherit'],
413
- shell: true
414
- });
415
-
416
- // 将内容写入pager的stdin
417
- child.stdin.write(fullContent);
418
- child.stdin.end();
419
-
420
- child.on('exit', (code) => {
421
- resolve(code === 0);
422
- });
423
-
424
- child.on('error', () => {
425
- // 如果pager失败,回退到直接输出
426
- console.error(chalk.yellow(trans.docs.pagerNotAvailable));
427
- console.log(fullContent);
428
- resolve(false);
429
- });
430
-
431
- } catch {
432
- // 回退方案: 直接输出
433
- console.log(fullContent);
434
- resolve(false);
435
- }
436
- });
437
- }
438
-
439
- /**
440
- * 查看Markdown文件
441
- */
442
- async function viewMarkdownFile(path: string): Promise<void> {
443
- const trans = t();
444
- try {
445
- info(`${trans.docs.loading.replace('...', '')}: ${path}`);
446
-
447
- // 从GitHub获取原始Markdown内容
448
- const rawContent = await fetchGitHubRawContent(path);
449
-
450
- // 清理VitePress特殊语法 - 使用终端能力优化显示
451
- const cleanedContent = cleanMarkdownContent(rawContent, terminalCapabilities);
452
-
453
- // 提取标题
454
- const title = extractDocTitle(cleanedContent) || path.split('/').pop() || path;
455
-
456
- // 渲染Markdown到终端
457
- const rendered = await marked(cleanedContent);
458
-
459
- console.log('\r' + ' '.repeat(60) + '\r'); // 清除加载提示
460
-
461
- // 使用pager显示文档 (类似vim/journalctl的阅读体验)
462
- await displayInPager(rendered, `${title}\n${chalk.gray(` ${path}`)}`);
463
-
464
- console.log(); // 添加空行
465
- success(trans.docs.docCompleted);
466
- console.log();
467
-
468
- // 提供后续操作选项
469
- const { action } = await inquirer.prompt([
470
- {
471
- type: 'list',
472
- name: 'action',
473
- message: trans.docs.chooseAction,
474
- choices: [
475
- { name: trans.docs.backToList, value: 'back' },
476
- { name: trans.docs.reread, value: 'reread' },
477
- { name: trans.docs.openBrowser, value: 'browser' }
478
- ]
479
- }
480
- ]);
481
-
482
- if (action === 'browser') {
483
- await openDocsInBrowser(path);
484
- } else if (action === 'reread') {
485
- // 重新阅读文档
486
- await viewMarkdownFile(path);
487
- }
488
-
489
- } catch (err: any) {
490
- console.log('\r' + ' '.repeat(60) + '\r');
491
- error(trans.docs.loadError);
492
- console.log(chalk.gray(` ${trans.docs.errorHint}: ${err.message}`));
493
- warning(trans.docs.openBrowserPrompt.replace('是否', '建议'));
494
- console.log();
495
-
496
- const { openBrowser } = await inquirer.prompt([
497
- {
498
- type: 'confirm',
499
- name: 'openBrowser',
500
- message: trans.docs.openBrowserPrompt,
501
- default: true
502
- }
503
- ]);
504
-
505
- if (openBrowser) {
506
- await openDocsInBrowser(path);
507
- }
508
- }
509
- }
510
-
511
- /**
512
- * 在浏览器中打开知识库
513
- */
514
- export async function openDocsInBrowser(path?: string): Promise<void> {
515
- const trans = t();
516
- try {
517
- info(trans.docs.opening);
518
- const url = path
519
- ? `https://docs.nbtca.space/${path.replace(/\.md$/, '')}`
520
- : 'https://docs.nbtca.space';
521
- await open(url);
522
- success(trans.docs.browserOpened);
523
- } catch (err) {
524
- error(trans.docs.browserError);
525
- console.log(chalk.gray(` ${trans.docs.browserErrorHint}`));
526
- }
527
- console.log();
528
- }
529
-
530
- /**
531
- * 显示知识库菜单
532
- */
533
- export async function showDocsMenu(): Promise<void> {
534
- const trans = t();
535
- console.log();
536
- console.log(chalk.cyan.bold(` >> ${trans.docs.title}`));
537
- console.log(chalk.dim(` ${trans.docs.subtitle}`));
538
-
539
- // 显示终端能力信息 - 帮助用户了解文档渲染能力
540
- const terminalTypeDisplay = {
541
- 'basic': chalk.yellow('基础'),
542
- 'enhanced': chalk.cyan('增强'),
543
- 'advanced': chalk.green('高级')
544
- }[terminalCapabilities.terminalType];
545
-
546
- console.log(chalk.dim(` 终端类型: ${terminalTypeDisplay} | 支持: ${
547
- [
548
- terminalCapabilities.supportsColor && '彩色',
549
- terminalCapabilities.supportsUnicode && 'Unicode',
550
- terminalCapabilities.supportsImages && '图片'
551
- ].filter(Boolean).join(', ') || '纯文本'
552
- }`));
553
- console.log();
554
-
555
- const choices = [
556
- ...DOC_CATEGORIES.map(cat => ({
557
- name: cat.name,
558
- value: cat.path
559
- })),
560
- new inquirer.Separator(),
561
- { name: chalk.gray(trans.docs.openBrowser), value: 'browser' },
562
- { name: chalk.gray(trans.docs.returnToMenu), value: 'back' }
563
- ];
564
-
565
- const { action } = await inquirer.prompt([
566
- {
567
- type: 'list',
568
- name: 'action',
569
- message: trans.docs.chooseCategory,
570
- choices,
571
- pageSize: 15,
572
- loop: false
573
- }
574
- ]);
575
-
576
- if (action === 'back') {
577
- return;
578
- } else if (action === 'browser') {
579
- await openDocsInBrowser();
580
- } else if (action === 'README.md') {
581
- // 直接查看 README
582
- await viewMarkdownFile('README.md');
583
- } else {
584
- // 浏览指定目录
585
- await browseDirectory(action);
586
- }
587
- }
588
-
@@ -1,36 +0,0 @@
1
- /**
2
- * 维修服务模块
3
- * 打开维修服务网页
4
- */
5
-
6
- import open from 'open';
7
- import chalk from 'chalk';
8
- import { error, info, success } from '../core/ui.js';
9
- import { t } from '../i18n/index.js';
10
-
11
- /**
12
- * 维修服务URL
13
- */
14
- const REPAIR_URL = 'https://nbtca.space/repair';
15
-
16
- /**
17
- * 打开维修服务页面
18
- */
19
- export async function openRepairService(): Promise<void> {
20
- const trans = t();
21
- try {
22
- console.log();
23
- info(trans.repair.opening);
24
- console.log();
25
-
26
- await open(REPAIR_URL);
27
-
28
- success(trans.repair.opened);
29
- console.log();
30
- } catch (err) {
31
- error(trans.repair.error);
32
- console.log();
33
- console.log(chalk.yellow(' ' + trans.repair.errorHint));
34
- console.log();
35
- }
36
- }
@@ -1,45 +0,0 @@
1
- /**
2
- * 官网访问模块
3
- * 打开NBTCA官方网站或GitHub
4
- */
5
-
6
- import open from 'open';
7
- import chalk from 'chalk';
8
- import { error, info, success } from '../core/ui.js';
9
- import { t } from '../i18n/index.js';
10
-
11
- /**
12
- * 打开指定URL
13
- */
14
- export async function openWebsite(url: string): Promise<void> {
15
- const trans = t();
16
- try {
17
- console.log();
18
- info(trans.website.opening);
19
-
20
- await open(url);
21
-
22
- success(trans.website.opened);
23
- console.log(chalk.gray(` ${url}`));
24
- console.log();
25
- } catch (err) {
26
- error(trans.website.error);
27
- console.log();
28
- console.log(chalk.yellow(' ' + trans.website.errorHint + ': ') + chalk.cyan(url));
29
- console.log();
30
- }
31
- }
32
-
33
- /**
34
- * Open NBTCA homepage
35
- */
36
- export async function openHomepage(): Promise<void> {
37
- await openWebsite('https://nbtca.space');
38
- }
39
-
40
- /**
41
- * Open GitHub page
42
- */
43
- export async function openGithub(): Promise<void> {
44
- await openWebsite('https://github.com/nbtca');
45
- }